diff --git a/api/customs/serializers.py b/api/customs/serializers.py index 89e8bf0..ec675b5 100644 --- a/api/customs/serializers.py +++ b/api/customs/serializers.py @@ -9,6 +9,7 @@ from api.customs.models import ( Partida ) from django.db import models +from django.db.models import Q from api.record.models import Document # Asegúrate de importar el modelo Documento from api.record.serializers import DocumentSerializer from api.vucem.serializers import VucemSerializer @@ -43,6 +44,59 @@ class PedimentoSerializer(serializers.ModelSerializer): return rep class PartidaSerializer(serializers.ModelSerializer): + documentos = serializers.SerializerMethodField() + + def get_documentos(self, obj): + """ + Busca documentos en la tabla `document` que coincidan EXACTAMENTE con: + 'documents/vu_PT_{pedimentoApp}_{numero}' al inicio del nombre del archivo. + """ + + if not obj or not getattr(obj, 'pedimento', None): + return [] + + if not obj or not getattr(obj, 'numero_partida', None): + return [] + + try: + pedimentoApp = str(obj.pedimento.pedimento_app).strip() + numero = str(obj.numero_partida).strip() + + # Construir el patrón exacto de búsqueda + patron_exacto = f'documents/vu_PT_{pedimentoApp}_{numero}.xml' + + # Buscar documentos que empiecen EXACTAMENTE con ese patrón + qs = Document.objects.filter( + archivo=patron_exacto + ) + + # Opción 2: Si puede tener diferentes extensiones + # patron_base = f'documents/vu_PT_{pedimentoApp}_{numero}' + # qs = Document.objects.filter( + # archivo__startswith=patron_base + # ).filter( + # archivo__in=[ + # f'{patron_base}.xml', + # f'{patron_base}.pdf', + # f'{patron_base}.zip' + # ] + # ) + + # Filtro adicional por pedimento si el modelo Document tiene este campo + if hasattr(Document, 'pedimento'): + qs = qs.filter(pedimento=obj.pedimento) + + # Filtro por organización + if hasattr(obj, 'organizacion') and obj.organizacion: + qs = qs.filter(organizacion=obj.organizacion) + + serializer = DocumentSerializer(qs, many=True, context=self.context) + return serializer.data + + #return [] + except Exception: + # En caso de cualquier error (por ejemplo, importaciones circulares), devolver lista vacía + return [] class Meta: model = Partida fields = '__all__' @@ -129,6 +183,47 @@ class ProcesamientoPedimentoSerializer(serializers.ModelSerializer): return representation class EDocumentSerializer(serializers.ModelSerializer): + documentos = serializers.SerializerMethodField() + + def get_documentos(self, obj): + """ + Busca documentos en la tabla `document` que coincidan con el + `numero_edocument` dentro del nombre del archivo (`archivo`). Se + filtra por organización para evitar devolver documentos de otras orgs. + Devuelve la serialización completa de los documentos encontrados: + 1. Empiecen con 'vu_EDOCUMENT' en el nombre del archivo + 2. Terminen con el numero_edocument + .xml + 3. Pertenezcan a la misma organización + """ + if not obj or not getattr(obj, 'numero_edocument', None): + return [] + + if not obj or not getattr(obj, 'pedimento', None): + return [] + + # if not obj or not getattr(obj, 'pedimento_id', None): + # return [] + + try: + numero = str(obj.numero_edocument).strip() + # id_pedimento = str(obj.pedimento_id).strip() + + qs = Document.objects.filter( + pedimento=obj.pedimento, + archivo__icontains=numero, + ) + + # Filtro por organización si aplica + if hasattr(obj, 'organizacion') and obj.organizacion: + qs = qs.filter(organizacion=obj.organizacion) + + serializer = DocumentSerializer(qs, many=True, context=self.context) + return serializer.data + + except Exception: + # En caso de cualquier error (por ejemplo, importaciones circulares), devolver lista vacía + return [] + class Meta: model = EDocument fields = '__all__' @@ -142,11 +237,48 @@ class EDocumentSerializer(serializers.ModelSerializer): self.fields['organizacion'].read_only = True class CoveSerializer(serializers.ModelSerializer): + documentos = serializers.SerializerMethodField() + class Meta: model = Cove fields = '__all__' read_only_fields = ('created_at', 'updated_at') + def get_documentos(self, obj): + """ + Busca documentos en la tabla `document` que coincidan con el + `numero_cove` dentro del nombre del archivo (`archivo`). Se + filtra por organización para evitar devolver documentos de otras orgs. + Devuelve la serialización completa de los documentos encontrados: + 1. Empiecen con 'vu_COVE' en el nombre del archivo + 2. Terminen con el numero_cove + .xml + 3. Pertenezcan a la misma organización + """ + if not obj or not getattr(obj, 'numero_cove', None): + return [] + + if not obj or not getattr(obj, 'pedimento', None): + return [] + + try: + numero = str(obj.numero_cove).strip() + + qs = Document.objects.filter( + pedimento=obj.pedimento, + archivo__icontains=numero, + ) + + # Filtro por organización si aplica + if hasattr(obj, 'organizacion') and obj.organizacion: + qs = qs.filter(organizacion=obj.organizacion) + + serializer = DocumentSerializer(qs, many=True, context=self.context) + return serializer.data + + except Exception: + # En caso de cualquier error (por ejemplo, importaciones circulares), devolver lista vacía + return [] + class ImportadorSerializer(serializers.ModelSerializer): class Meta: model = Importador diff --git a/api/record/urls.py b/api/record/urls.py index e8781a8..1ea522d 100644 --- a/api/record/urls.py +++ b/api/record/urls.py @@ -4,7 +4,16 @@ from rest_framework.routers import DefaultRouter # import necessary viewsets # from .views import YourViewSet # Import your viewsets here -from .views import DocumentViewSet, ProtectedDocumentDownloadView, BulkDownloadZipView, GetFuenteView, DocumentTypeView, ExpedienteZipDownloadView, MultiPedimentoZipDownloadView +from .views import (DocumentViewSet + , ProtectedDocumentDownloadView + , BulkDownloadZipView + , GetFuenteView + , DocumentTypeView + , ExpedienteZipDownloadView + , MultiPedimentoZipDownloadView + , PedimentoDocumentViewSet) + + # Create a router and register your viewsets with it router = DefaultRouter() @@ -25,5 +34,6 @@ urlpatterns = [ path('document-type/', DocumentTypeView.as_view(), name='document-type-list-create'), path('documents/expediente-zip/', ExpedienteZipDownloadView.as_view(), name='expediente-zip-download'), path('documents/multi-pedimento-zip/', MultiPedimentoZipDownloadView.as_view(), name='multi-pedimento-zip-download'), + path('pedimento-documents/', PedimentoDocumentViewSet.as_view({'get': 'list'}), name='pedimento-document-list'), path('', include(router.urls)), ] \ No newline at end of file diff --git a/api/record/views.py b/api/record/views.py index 7c33d45..f2688f9 100644 --- a/api/record/views.py +++ b/api/record/views.py @@ -63,7 +63,8 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin): pagination_class = CustomPagination serializer_class = DocumentSerializer # Habilitar filtro por pedimento (UUID) y pedimento_numero (campo pedimento del modelo relacionado) - filterset_fields = ['extension', 'size', 'document_type', 'pedimento', 'pedimento__pedimento'] + filterset_fields = ['extension', 'size', 'document_type', 'pedimento', 'pedimento__pedimento', 'created_at'] + # filterset_fields = ['extension', 'size', 'pedimento', 'pedimento__pedimento'] # Puedes filtrar por pedimento usando: /api/record/documents/?pedimento= o /api/record/documents/?pedimento__pedimento= # Ejemplo: /api/record/documents/?pedimento_numero=12345678 @@ -71,6 +72,33 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin): def get_queryset(self): queryset = self.get_queryset_filtrado_por_organizacion() + + modulo_efc = self.request.query_params.get('modulo') + if modulo_efc: + if modulo_efc == 'expedientes-detalle-pedimentos': + queryset = queryset.filter(document_type_id='11') + # Filtro personalizado por document_type + # document_type = self.request.query_params.get('document_type') + # if document_type: + # # Puedes agregar lógica personalizada aquí si es necesario + # if document_type == '1': + # queryset = queryset.filter(document_type_id=document_type) + # elif document_type == '2': + # queryset = queryset.filter(document_type_id=document_type) + # else: + # queryset = queryset.filter(document_type_id=document_type) + # else: + # queryset = queryset.filter(document_type_id='11') + + fechaCreacion = self.request.query_params.get('created_at__date') + if fechaCreacion: + queryset = queryset.filter(created_at=fechaCreacion) + + buscarArchivo = self.request.query_params.get('archivo__icontains') + if buscarArchivo: + queryset = queryset.filter(archivo__icontains=buscarArchivo) + + pedimento_numero = self.request.query_params.get('pedimento_numero') if pedimento_numero: queryset = queryset.filter(pedimento__pedimento_app=pedimento_numero) @@ -762,6 +790,50 @@ class MultiPedimentoZipDownloadView(APIView): return response - +class PedimentoDocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin): + """ + ViewSet for Document model. + """ + permission_classes = [IsAuthenticated & (IsSuperUser | IsSameOrganization | IsSameOrganizationAndAdmin | IsSameOrganizationDeveloper )] + model = Document + + pagination_class = CustomPagination + serializer_class = DocumentSerializer + # Habilitar filtro por pedimento (UUID) y pedimento_numero (campo pedimento del modelo relacionado) + # filterset_fields = ['extension', 'size', 'document_type', 'pedimento', 'pedimento__pedimento'] + filterset_fields = ['extension', 'size', 'pedimento', 'pedimento__pedimento','fuente'] + + # Puedes filtrar por pedimento usando: /api/record/documents/?pedimento= o /api/record/documents/?pedimento__pedimento= + # Ejemplo: /api/record/documents/?pedimento_numero=12345678 + my_tags = ['Documents'] + + def get_queryset(self): + queryset = self.get_queryset_filtrado_por_organizacion() + + # Tipos de documento permitidos (fijos en código, Pedimento completo y remesas) + TIPOS_PERMITIDOS = ['2', '3'] # <-- Ajusta aquí tus tipos + tipo_documento = self.request.query_params.get('document_type') + if tipo_documento: + queryset = queryset.filter(document_type_id=tipo_documento) + else: + # Filtrar por tipos permitidos + queryset = queryset.filter(document_type_id__in=TIPOS_PERMITIDOS) + + buscar_archivo = self.request.query_params.get('archivo__icontains') + if buscar_archivo: + queryset = queryset.filter(archivo__icontains=buscar_archivo) + + created_at__date = self.request.query_params.get('created_at__date') + if created_at__date: + queryset = queryset.filter(created_at=created_at__date) + + # Filtro adicional por pedimento_numero si se proporciona + pedimento_numero = self.request.query_params.get('pedimento_numero') + if pedimento_numero: + queryset = queryset.filter(pedimento__pedimento_app=pedimento_numero) + + return queryset + + \ No newline at end of file