Skip to content

Commit

Permalink
Merge pull request #15 from guivaloz:guivaloz/storage
Browse files Browse the repository at this point in the history
Ya se guardan archivos en Storage
  • Loading branch information
guivaloz authored May 14, 2024
2 parents a9448e3 + 421cd2c commit 3bef415
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 66 deletions.
2 changes: 1 addition & 1 deletion carina/core/exh_areas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ExhArea(Base, UniversalMixin):

# Columnas
clave = Column(String(16), unique=True, nullable=False)
descripcion = Column(String(256), nullable=False)
nombre = Column(String(256), unique=True, nullable=False)

# Hijos
exh_exhortos = relationship("ExhExhorto", back_populates="exh_area")
Expand Down
11 changes: 10 additions & 1 deletion carina/v4/exh_exhortos/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ def create_exh_exhorto(database: Session, exh_exhorto_in: ExhExhortoIn) -> ExhEx
municipio_destino = (
database.query(Municipio).filter_by(estado_id=ESTADO_DESTINO_ID).filter_by(clave=municipio_destino_clave).first()
)

if municipio_destino is None:
raise MyNotExistsError("No existe ese municipio de destino")
exh_exhorto.municipio_destino_id = municipio_destino.id
Expand Down Expand Up @@ -155,3 +154,13 @@ def create_exh_exhorto(database: Session, exh_exhorto_in: ExhExhortoIn) -> ExhEx

# Entregar
return exh_exhorto


def update_set_exhorto(database: Session, exh_exhorto: ExhExhorto, **kwargs) -> ExhExhorto:
"""Actualizar un exhorto"""
for key, value in kwargs.items():
setattr(exh_exhorto, key, value)
database.add(exh_exhorto)
database.commit()
database.refresh(exh_exhorto)
return exh_exhorto
10 changes: 10 additions & 0 deletions carina/v4/exh_exhortos_archivos/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,13 @@ def get_exh_exhorto_archivo(database: Session, exh_exhorto_archivo_id: int) -> E
if exh_exhorto_archivo.estatus != "A":
raise MyIsDeletedError("No es activo ese archivo, está eliminado")
return exh_exhorto_archivo


def update_set_exhorto_archivo(database: Session, exh_exhorto_archivo: ExhExhortoArchivo, **kwargs) -> ExhExhortoArchivo:
"""Actualizar un archivo"""
for key, value in kwargs.items():
setattr(exh_exhorto_archivo, key, value)
database.add(exh_exhorto_archivo)
database.commit()
database.refresh(exh_exhorto_archivo)
return exh_exhorto_archivo
125 changes: 91 additions & 34 deletions carina/v4/exh_exhortos_archivos/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from datetime import datetime
from typing import Annotated
import uuid

from fastapi import APIRouter, Depends, HTTPException, status, UploadFile
from fastapi_pagination.ext.sqlalchemy import paginate
Expand All @@ -12,20 +13,20 @@
from lib.database import Session, get_db
from lib.exceptions import MyAnyError
from lib.fastapi_pagination_custom_page import CustomPage
from lib.google_cloud_storage import get_blob_name_from_url, get_media_type_from_filename, get_file_from_gcs, upload_file_to_gcs
from lib.google_cloud_storage import upload_file_to_gcs

from ...core.permisos.models import Permiso
from ..exh_exhortos.crud import get_exh_exhorto
from ..usuarios.authentications import UsuarioInDB, get_current_active_user
from .crud import get_exh_exhortos_archivos, get_exh_exhorto_archivo
from .schemas import (
from carina.core.permisos.models import Permiso
from carina.v4.exh_exhortos.crud import get_exh_exhorto, update_set_exhorto
from carina.v4.exh_exhortos_archivos.crud import get_exh_exhortos_archivos, get_exh_exhorto_archivo, update_set_exhorto_archivo
from carina.v4.exh_exhortos_archivos.schemas import (
ExhExhortoArchivoFileDataAcuseOut,
ExhExhortoArchivoFileDataArchivoOut,
ExhExhortoArchivoFileDataOut,
ExhExhortoArchivoFileOut,
ExhExhortoArchivoOut,
OneExhExhortoArchivoOut,
)
from carina.v4.usuarios.authentications import UsuarioInDB, get_current_active_user

exh_exhortos_archivos = APIRouter(prefix="/v4/exh_exhortos_archivos", tags=["exhortos"])

Expand Down Expand Up @@ -72,53 +73,109 @@ async def upload_exh_exhorto_archivo(
if current_user.permissions.get("EXH EXHORTOS ARCHIVOS", 0) < Permiso.CREAR:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden")

# Validar que el nombre del archivo termine en pdf
if not archivo.filename.lower().endswith(".pdf"):
return ExhExhortoArchivoFileOut(success=False, errors=["El archivo debe ser un PDF"])

# Consultar y validar el exhorto a partir del exhortoOrigenId
try:
exh_exhorto = get_exh_exhorto(database, exhortoOrigenId)
except MyAnyError as error:
return ExhExhortoArchivoFileOut(success=False, errors=[str(error)])

# Consultar los archivos del exhorto
exh_exhortos_archivos = get_exh_exhortos_archivos(database, exhortoOrigenId).all()

# Buscar el archivo del exhorto a partir del nombre del archivo
se_encontro = False
for exh_exhorto_archivo in exh_exhortos_archivos:
if exh_exhorto_archivo.nombre_archivo == archivo.filename:
se_encontro = True
break
# Consultar los archivos del exhorto y buscar el archivo a partir del nombre del archivo
total_contador = 0
pendientes_contador = 0
recibidos_contador = 0
exh_exhorto_archivo_encontrado = False
for exh_exhorto_archivo in get_exh_exhortos_archivos(database, exhortoOrigenId).all():
total_contador += 1
if exh_exhorto_archivo.nombre_archivo == archivo.filename and exh_exhorto_archivo.estado == "PENDIENTE":
exh_exhorto_archivo_encontrado = exh_exhorto_archivo
if exh_exhorto_archivo.estado == "PENDIENTE":
pendientes_contador += 1
else:
recibidos_contador += 1

# Si NO se encontró el archivo, entonces entregar un error
if not se_encontro:
if exh_exhorto_archivo_encontrado is False:
return ExhExhortoArchivoFileOut(success=False, errors=["No se encontró el archivo"])

# Validar la integridad del archivo con los hashes
# TODO: Validar la integridad del archivo con los hashes

# Definir el nombre del archivo a subir a Google Storage
archivo_pdf_nombre = f"{exhortoOrigenId}_{str(recibidos_contador + 1).zfill(4)}.pdf"

# Definir la ruta para blob_name con la fecha actual
fecha_hora_recepcion = datetime.now()
year = fecha_hora_recepcion.strftime("%Y")
month = fecha_hora_recepcion.strftime("%m")
day = fecha_hora_recepcion.strftime("%d")
blob_name = f"exh_exhortos_archivos/{year}/{month}/{day}/{archivo_pdf_nombre}"

# Determinar el tamano del archivo
archivo_pdf_tamanio = archivo.size

# Almacenar el archivo en Google Storage
settings = get_settings()
upload_file_to_gcs(
bucket_name=settings.cloud_storage_deposito,
blob_name=f"exh_exhortos_archivos/YYYY/MM/DD/{archivo.filename}",
content_type="application/pdf",
data=archivo.file,
try:
archivo_pdf_url = upload_file_to_gcs(
bucket_name=settings.cloud_storage_deposito,
blob_name=blob_name,
content_type="application/pdf",
data=archivo.file,
)
except MyAnyError as error:
return ExhExhortoArchivoFileOut(success=False, errors=[str(error)])

# Cambiar el estado de exh_exhorto_archivo_encontrado a RECIBIDO
exh_exhorto_archivo_encontrado = update_set_exhorto_archivo(
database=database,
exh_exhorto_archivo=exh_exhorto_archivo_encontrado,
estado="RECIBIDO",
url=archivo_pdf_url,
tamano=archivo_pdf_tamanio,
fecha_hora_recepcion=fecha_hora_recepcion,
)

# Definir los datos del archivo para la respuesta
archivo = ExhExhortoArchivoFileDataArchivoOut(
nombreArchivo=archivo.filename,
tamano=1024,
nombreArchivo=exh_exhorto_archivo_encontrado.nombre_archivo,
tamano=archivo_pdf_tamanio,
)

# Definir los datos del acuse para la respuesta
acuse = ExhExhortoArchivoFileDataAcuseOut(
exhortoOrigenId="",
folioSeguimiento="",
fechaHoraRecepcion=datetime.now(),
municipioAreaRecibeId=1,
areaRecibeId="",
areaRecibeNombre="",
urlInfo="",
)
# Si pendientes_contador + 1 = total_contador
if pendientes_contador + 1 >= total_contador:
# Generar el folio_seguimiento como un UUID
folio_seguimiento = str(uuid.uuid4())
# Entonces ES EL ULTIMO ARCHIVO, se cambia el estado de exh_exhorto a RECIBIDO
exh_exhorto_actualizado = update_set_exhorto(
database=database,
exh_exhorto=exh_exhorto,
estado="RECIBIDO",
folio_seguimiento=folio_seguimiento,
)
# Y se va a elaborar el acuse
acuse = ExhExhortoArchivoFileDataAcuseOut(
exhortoOrigenId=exh_exhorto_actualizado.exhorto_origen_id,
folioSeguimiento=folio_seguimiento,
fechaHoraRecepcion=fecha_hora_recepcion,
municipioAreaRecibeId=exh_exhorto_actualizado.municipio_destino_id,
areaRecibeId=exh_exhorto_actualizado.exh_area.clave,
areaRecibeNombre=exh_exhorto_actualizado.exh_area.nombre,
urlInfo="https://www.google.com.mx",
)
else:
# Definir el acuse VACIO, porque aun faltan archivos
acuse = ExhExhortoArchivoFileDataAcuseOut(
exhortoOrigenId="",
folioSeguimiento="",
fechaHoraRecepcion=None,
municipioAreaRecibeId=1,
areaRecibeId="",
areaRecibeNombre="",
urlInfo="",
)

# Juntar los datos para la respuesta
data = ExhExhortoArchivoFileDataOut(
Expand Down
8 changes: 4 additions & 4 deletions lib/google_cloud_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,23 +171,23 @@ def upload_file_to_gcs(

# Check content type
if content_type not in EXTENSIONS_MEDIA_TYPES.values():
raise MyFileNotAllowedError("File not allowed")
raise MyFileNotAllowedError("Tipo de archivo no permitido")

# Get bucket
storage_client = storage.Client()
try:
bucket = storage_client.get_bucket(bucket_name)
except NotFound as error:
raise MyBucketNotFoundError("Bucket not found") from error
raise MyBucketNotFoundError("No existe el deposito en Google Cloud Storage") from error

# Create blob
blob = bucket.blob(blob_name)

# Upload file
try:
blob.upload_from_string(data, content_type=content_type)
blob.upload_from_file(data, content_type=content_type)
except Exception as error:
raise MyUploadError("Error uploading file") from error
raise MyUploadError("Error al subir el archivo a Google Cloud Storage") from error

# Return public URL
return blob.public_url
55 changes: 29 additions & 26 deletions tests/test_exh_exhortos.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
Unit test for exhortos category
"""

import time
import unittest
import uuid
import random
import requests
from faker import Faker
from tests.load_env import config
Expand All @@ -21,18 +23,6 @@ def test_get_exh_exhortos(self):
)
self.assertEqual(response.status_code, 200)

def test_get_exh_exhorto_by_id(self):
"""Test GET method for exh_exhorto by id"""
response = requests.get(
f"{config['api_base_url']}/exh_exhortos/1",
headers={"X-Api-Key": config["api_key"]},
timeout=config["timeout"],
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data["success"], True)
self.assertEqual(data["data"]["id"], 1)

def test_post_exh_exhorto(self):
"""Test POST method for exh_exhorto"""

Expand Down Expand Up @@ -66,6 +56,18 @@ def test_post_exh_exhorto(self):
apellido_paterno_demandado = faker.last_name()
apellido_materno_demandado = faker.last_name()

# Generar de 1 a 4 archivos de prueba
archivos = []
for numero in range(1, random.randint(1, 4) + 1):
archivos.append(
{
"nombreArchivo": f"prueba-{numero}.pdf",
"hashSha1": "",
"hashSha256": "",
"tipoDocumento": 1,
}
)

# Mandar Exhorto
datos_nuevo_exhorto = {
"exhortoOrigenId": exhorto_origen_id,
Expand Down Expand Up @@ -104,7 +106,7 @@ def test_post_exh_exhorto(self):
"tipoDiligenciacionNombre": "OFICIO",
"fechaOrigen": "2024-05-03T21:58:45.258Z",
"observaciones": "CELEBRIDADES QUE SE VAN A DIVORCIAR",
"archivos": [{"nombreArchivo": "prueba.pdf", "hashSha1": "ABC123", "hashSha256": "ABC123", "tipoDocumento": 1}],
"archivos": archivos,
}
response = requests.post(
f"{config['api_base_url']}/exh_exhortos",
Expand All @@ -118,19 +120,20 @@ def test_post_exh_exhorto(self):
self.assertEqual(data["data"]["exhortoOrigenId"], exhorto_origen_id)

# Mandar un archivo multipart/form-data
archivo_prueba_nombre = "prueba.pdf"
with open(f"tests/{archivo_prueba_nombre}", "rb") as archivo_prueba:
response = requests.post(
f"{config['api_base_url']}/exh_exhortos_archivos/upload",
headers={"X-Api-Key": config["api_key"]},
timeout=config["timeout"],
params={"exhortoOrigenId": exhorto_origen_id},
files={"archivo": (archivo_prueba_nombre, archivo_prueba, "application/pdf")},
)
self.assertEqual(response.status_code, 200)
data = response.json()
# self.assertEqual(data["success"], True)
self.assertEqual(data["message"], archivo_prueba_nombre)
for archivo in archivos:
time.sleep(5) # Pausa de 5 segundos
archivo_prueba_nombre = archivo["nombreArchivo"]
with open(f"tests/{archivo_prueba_nombre}", "rb") as archivo_prueba:
response = requests.post(
f"{config['api_base_url']}/exh_exhortos_archivos/upload",
headers={"X-Api-Key": config["api_key"]},
timeout=config["timeout"],
params={"exhortoOrigenId": exhorto_origen_id},
files={"archivo": (archivo_prueba_nombre, archivo_prueba, "application/pdf")},
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data["success"], True)


if __name__ == "__main__":
Expand Down

0 comments on commit 3bef415

Please sign in to comment.