feat(tests): Añadido soporte de autenticación con access token en tests GET de todos los módulos de reference_data. Ahora los tests usan un fixture access_token y envían el header Authorization. Módulos actualizados: containers, countries, currency_types, material_types, states, valuation_methods, incoterms, payment_methods, sectors, customs_sections, customs_warehouses, invoice_types, pedimento_codes, pedimento_regimens, code_pedimento_regimens, transport_modes, transport_types.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
from typing import Optional
|
||||
|
||||
class CodePedimentoRegimenDTO(BaseModel):
|
||||
@@ -7,5 +8,4 @@ class CodePedimentoRegimenDTO(BaseModel):
|
||||
regimen_code: Optional[str] = Field(None, min_length=1, max_length=3)
|
||||
type_code: Optional[str] = Field(None, min_length=1, max_length=1)
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -1,19 +1,40 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import CodePedimentoRegimen
|
||||
from .dto import CodePedimentoRegimenDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/code-pedimento-regimens", tags=["Code Pedimento Regimens"])
|
||||
|
||||
@router.get("/", response_model=list[CodePedimentoRegimenDTO])
|
||||
def list_code_pedimento_regimens(db: Session = Depends(get_core_db)):
|
||||
objs = db.query(CodePedimentoRegimen).all()
|
||||
return [CodePedimentoRegimenDTO.model_validate(obj) for obj in objs]
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_code_pedimento_regimens(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(CodePedimentoRegimen)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [CodePedimentoRegimenDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{id}", response_model=CodePedimentoRegimenDTO)
|
||||
def get_code_pedimento_regimen(id: int, db: Session = Depends(get_core_db)):
|
||||
def get_code_pedimento_regimen(
|
||||
id: int,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
obj = db.query(CodePedimentoRegimen).filter(CodePedimentoRegimen.id == id).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.code_pedimento_regimens.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_code_pedimento_regimens(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/code-pedimento-regimens/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_code_pedimento_regimen_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/code-pedimento-regimens/999999", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_code_pedimento_regimen_forbidden():
|
||||
response = client.post("/code-pedimento-regimens/", json={"id": 999999, "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_code_pedimento_regimen_forbidden():
|
||||
response = client.put("/code-pedimento-regimens/999999", json={"id": 999999, "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_code_pedimento_regimen_forbidden():
|
||||
response = client.delete("/code-pedimento-regimens/999999")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
15
backend/api/v1/modules/public/reference_data/conftest.py
Normal file
15
backend/api/v1/modules/public/reference_data/conftest.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.transport_types.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def access_token():
|
||||
# Reemplaza este token por uno válido generado por Keycloak
|
||||
return "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyTS1iTEZZYm9OaklYM3NjaVlmODNGZGVRY2s3ZzI3cmxZckowNzRCMGVFIn0.eyJleHAiOjE3NjIwNzM2ODksImlhdCI6MTc2MjAzNzY4OSwianRpIjoib25ydHJvOmM5OGM2M2I2LTcxMWUtNWUxYS0wZmE4LTFjNTMwN2VlNTY5NSIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiNzVmM2E0MzQtODM2MC00NTY0LTk0NmMtMGE3ZTFkNWI3MzMwIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYW5leG83Ni1iYWNrZW5kIiwic2lkIjoiYTYwMzdkZjQtMGIzYS02MGZjLTU4NmQtYTc1NWMwMzc5YjAxIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjgwMDAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsImRlZmF1bHQtcm9sZXMtbWFzdGVyIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIiwidXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im1hc3Rlci1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LXJlYWxtIiwidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsInRlbmFudF9pZCI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJLZXZpbiBSb3NhbGVzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoia3Jvc2FsZXMiLCJnaXZlbl9uYW1lIjoiS2V2aW4iLCJmYW1pbHlfbmFtZSI6IlJvc2FsZXMiLCJlbWFpbCI6Imtyb3NhbGVzQGFkdWFuYXNvZnQuY29tLm14In0.NgofV0pK3tiLN-hyWechIIG67QPIfJDK3fZvLkBuhhgExlQNcargt3zK6dn3JIzPPE3hpmaVBZmmARRTNB7v9xgP3Hg8tXsnJMPVU4gStBM8-XDn0vYNEEehAemp-F2xLNlbCmZtOtBk2ZF-lLecSa67yQ6VXJJv1_1K420w7KSUUU4nxXobAcXmYgJSb9d8O5zJekDRlDSp8TQCa25qOZTqUbjdpVnZh_sdMpzPxnFGDqxQd99_erQMPGG0Mu5CuhH9V8EIin9BdkjWWtafc6q64qmig8yNVJIJ0I3Mul01Bo0A2EZXIQhTaDxsGf8GiAIEYDjUZSl-5u5EYck7lg"
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def client():
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
return TestClient(app)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class ContainerDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=3)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,25 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import Container
|
||||
from .dto import ContainerDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/containers", tags=["Containers"])
|
||||
|
||||
@router.get("/", response_model=list[ContainerDTO])
|
||||
def list_containers(db: Session = Depends(get_core_db)):
|
||||
return db.query(Container).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_containers(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(Container)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [ContainerDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=ContainerDTO)
|
||||
def get_container(key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_container(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(Container).filter(Container.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=ContainerDTO, status_code=201)
|
||||
def create_container(
|
||||
async def create_container(
|
||||
data: ContainerDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -30,8 +51,9 @@ def create_container(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=ContainerDTO)
|
||||
def update_container(
|
||||
async def update_container(
|
||||
key: str,
|
||||
data: ContainerDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -46,8 +68,9 @@ def update_container(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{key}", status_code=204)
|
||||
def delete_container(
|
||||
async def delete_container(
|
||||
key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.containers.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_containers(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/containers/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_container_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/containers/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_container_forbidden():
|
||||
response = client.post("/containers/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_container_forbidden():
|
||||
response = client.put("/containers/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_container_forbidden():
|
||||
response = client.delete("/containers/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,4 +1,5 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class CountryDTO(BaseModel):
|
||||
m3_key: str = Field(..., min_length=1, max_length=3)
|
||||
@@ -7,6 +8,5 @@ class CountryDTO(BaseModel):
|
||||
description_es: str
|
||||
description_en: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,25 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import Country
|
||||
from .dto import CountryDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/countries", tags=["Countries"])
|
||||
|
||||
@router.get("/", response_model=list[CountryDTO])
|
||||
def list_countries(db: Session = Depends(get_core_db)):
|
||||
return db.query(Country).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_countries(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(Country)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [CountryDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{m3_key}", response_model=CountryDTO)
|
||||
def get_country(m3_key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_country(m3_key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(Country).filter(Country.m3_key == m3_key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=CountryDTO, status_code=201)
|
||||
def create_country(
|
||||
async def create_country(
|
||||
data: CountryDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -30,8 +51,9 @@ def create_country(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{m3_key}", response_model=CountryDTO)
|
||||
def update_country(
|
||||
async def update_country(
|
||||
m3_key: str,
|
||||
data: CountryDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -46,8 +68,9 @@ def update_country(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{m3_key}", status_code=204)
|
||||
def delete_country(
|
||||
async def delete_country(
|
||||
m3_key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.countries.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_countries(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/countries/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_country_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/countries/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_country_forbidden():
|
||||
response = client.post("/countries/", json={"m3_key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_country_forbidden():
|
||||
response = client.put("/countries/TST", json={"m3_key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_country_forbidden():
|
||||
response = client.delete("/countries/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,10 +1,10 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class CurrencyTypeDTO(BaseModel):
|
||||
code: str = Field(..., min_length=1, max_length=3)
|
||||
currency_name: str
|
||||
country_description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,25 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import CurrencyType
|
||||
from .dto import CurrencyTypeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/currency-types", tags=["Currency Types"])
|
||||
|
||||
@router.get("/", response_model=list[CurrencyTypeDTO])
|
||||
def list_currency_types(db: Session = Depends(get_core_db)):
|
||||
return db.query(CurrencyType).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_currency_types(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(CurrencyType)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [CurrencyTypeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{code}", response_model=CurrencyTypeDTO)
|
||||
def get_currency_type(code: str, db: Session = Depends(get_core_db)):
|
||||
async def get_currency_type(code: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(CurrencyType).filter(CurrencyType.code == code).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=CurrencyTypeDTO, status_code=201)
|
||||
def create_currency_type(
|
||||
async def create_currency_type(
|
||||
data: CurrencyTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -30,8 +51,9 @@ def create_currency_type(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{code}", response_model=CurrencyTypeDTO)
|
||||
def update_currency_type(
|
||||
async def update_currency_type(
|
||||
code: str,
|
||||
data: CurrencyTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -46,8 +68,9 @@ def update_currency_type(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{code}", status_code=204)
|
||||
def delete_currency_type(
|
||||
async def delete_currency_type(
|
||||
code: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.currency_types.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_currency_types(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/currency-types/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_currency_type_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/currency-types/invalid_code", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_currency_type_forbidden():
|
||||
response = client.post("/currency-types/", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_currency_type_forbidden():
|
||||
response = client.put("/currency-types/TST", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_currency_type_forbidden():
|
||||
response = client.delete("/currency-types/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class CustomsSectionDTO(BaseModel):
|
||||
customs_code: str = Field(..., min_length=1, max_length=3)
|
||||
section_name: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import CustomsSection
|
||||
from .dto import CustomsSectionDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/customs-sections", tags=["Customs Sections"])
|
||||
|
||||
@router.get("/", response_model=list[CustomsSectionDTO])
|
||||
def list_customs_sections(db: Session = Depends(get_core_db)):
|
||||
return db.query(CustomsSection).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_customs_sections(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(CustomsSection)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [CustomsSectionDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{customs_code}", response_model=CustomsSectionDTO)
|
||||
def get_customs_section(customs_code: str, db: Session = Depends(get_core_db)):
|
||||
def get_customs_section(customs_code: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(CustomsSection).filter(CustomsSection.customs_code == customs_code).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.customs_sections.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_customs_sections(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/customs-sections/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_customs_section_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/customs-sections/invalid_code", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_customs_section_forbidden():
|
||||
response = client.post("/customs-sections/", json={"customs_code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_customs_section_forbidden():
|
||||
response = client.put("/customs-sections/TST", json={"customs_code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_customs_section_forbidden():
|
||||
response = client.delete("/customs-sections/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,10 +1,10 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class CustomsWarehouseDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=3)
|
||||
customs: str
|
||||
fiscalized_warehouse: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import CustomsWarehouse
|
||||
from .dto import CustomsWarehouseDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/customs-warehouses", tags=["Customs Warehouses"])
|
||||
|
||||
@router.get("/", response_model=list[CustomsWarehouseDTO])
|
||||
def list_customs_warehouses(db: Session = Depends(get_core_db)):
|
||||
return db.query(CustomsWarehouse).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_customs_warehouses(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(CustomsWarehouse)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [CustomsWarehouseDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{key}/{customs}", response_model=CustomsWarehouseDTO)
|
||||
def get_customs_warehouse(key: str, customs: str, db: Session = Depends(get_core_db)):
|
||||
def get_customs_warehouse(key: str, customs: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(CustomsWarehouse).filter(CustomsWarehouse.key == key, CustomsWarehouse.customs == customs).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.customs_warehouses.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_customs_warehouses(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/customs-warehouses/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_customs_warehouse_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/customs-warehouses/invalid_key/invalid_customs", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_customs_warehouse_forbidden():
|
||||
response = client.post("/customs-warehouses/", json={"key": "TST", "customs": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_customs_warehouse_forbidden():
|
||||
response = client.put("/customs-warehouses/TST/TST", json={"key": "TST", "customs": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_customs_warehouse_forbidden():
|
||||
response = client.delete("/customs-warehouses/TST/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class IncotermDTO(BaseModel):
|
||||
code: str = Field(..., min_length=1, max_length=5)
|
||||
description_es: str
|
||||
description_en: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -1,26 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import Incoterm
|
||||
from .dto import IncotermDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/incoterms", tags=["Incoterms"])
|
||||
|
||||
@router.get("/", response_model=list[IncotermDTO])
|
||||
def list_incoterms(db: Session = Depends(get_core_db)):
|
||||
objs = db.query(Incoterm).all()
|
||||
return [IncotermDTO.model_validate(obj) for obj in objs]
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_incoterms(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(Incoterm)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [IncotermDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=IncotermDTO)
|
||||
def get_incoterm(key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_incoterm(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(Incoterm).filter(Incoterm.code == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return IncotermDTO.model_validate(obj)
|
||||
|
||||
|
||||
@router.post("/", response_model=IncotermDTO, status_code=201)
|
||||
def create_incoterm(
|
||||
async def create_incoterm(
|
||||
data: IncotermDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -31,8 +51,9 @@ def create_incoterm(
|
||||
db.refresh(obj)
|
||||
return IncotermDTO.model_validate(obj)
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=IncotermDTO)
|
||||
def update_incoterm(
|
||||
async def update_incoterm(
|
||||
key: str,
|
||||
data: IncotermDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -47,8 +68,9 @@ def update_incoterm(
|
||||
db.refresh(obj)
|
||||
return IncotermDTO.model_validate(obj)
|
||||
|
||||
|
||||
@router.delete("/{key}", status_code=204)
|
||||
def delete_incoterm(
|
||||
async def delete_incoterm(
|
||||
key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.incoterms.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_incoterms(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/incoterms/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_incoterm_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/incoterms/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_incoterm_forbidden():
|
||||
response = client.post("/incoterms/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_incoterm_forbidden():
|
||||
response = client.put("/incoterms/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_incoterm_forbidden():
|
||||
response = client.delete("/incoterms/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,4 +1,5 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
from typing import Optional
|
||||
|
||||
class InvoiceTypeDTO(BaseModel):
|
||||
@@ -7,5 +8,4 @@ class InvoiceTypeDTO(BaseModel):
|
||||
note: Optional[str] = None
|
||||
type: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import InvoiceType
|
||||
from .dto import InvoiceTypeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/invoice-types", tags=["Invoice Types"])
|
||||
|
||||
@router.get("/", response_model=list[InvoiceTypeDTO])
|
||||
def list_invoice_types(db: Session = Depends(get_core_db)):
|
||||
objs = db.query(InvoiceType).all()
|
||||
return [InvoiceTypeDTO.model_validate(obj) for obj in objs]
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_invoice_types(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(InvoiceType)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [InvoiceTypeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{key}", response_model=InvoiceTypeDTO)
|
||||
def get_invoice_type(key: str, db: Session = Depends(get_core_db)):
|
||||
def get_invoice_type(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(InvoiceType).filter(InvoiceType.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.invoice_types.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_invoice_types(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/invoice-types/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_invoice_type_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/invoice-types/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_invoice_type_forbidden():
|
||||
response = client.post("/invoice-types/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_invoice_type_forbidden():
|
||||
response = client.put("/invoice-types/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_invoice_type_forbidden():
|
||||
response = client.delete("/invoice-types/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,10 +1,10 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class MaterialTypeDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=10)
|
||||
type: str = Field(..., min_length=1, max_length=15)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,25 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import MaterialType
|
||||
from .dto import MaterialTypeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/material-types", tags=["Material Types"])
|
||||
|
||||
@router.get("/", response_model=list[MaterialTypeDTO])
|
||||
def list_material_types(db: Session = Depends(get_core_db)):
|
||||
return db.query(MaterialType).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_material_types(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(MaterialType)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [MaterialTypeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=MaterialTypeDTO)
|
||||
def get_material_type(key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_material_type(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(MaterialType).filter(MaterialType.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=MaterialTypeDTO, status_code=201)
|
||||
def create_material_type(
|
||||
async def create_material_type(
|
||||
data: MaterialTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -30,8 +51,9 @@ def create_material_type(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=MaterialTypeDTO)
|
||||
def update_material_type(
|
||||
async def update_material_type(
|
||||
key: str,
|
||||
data: MaterialTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -46,8 +68,9 @@ def update_material_type(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{key}", status_code=204)
|
||||
def delete_material_type(
|
||||
async def delete_material_type(
|
||||
key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.material_types.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_material_types(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/material-types/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_material_type_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/material-types/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_material_type_forbidden():
|
||||
response = client.post("/material-types/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_material_type_forbidden():
|
||||
response = client.put("/material-types/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_material_type_forbidden():
|
||||
response = client.delete("/material-types/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class PaymentMethodDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=2)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import PaymentMethod
|
||||
from .dto import PaymentMethodDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/payment-methods", tags=["Payment Methods"])
|
||||
|
||||
@router.get("/", response_model=list[PaymentMethodDTO])
|
||||
def list_payment_methods(db: Session = Depends(get_core_db)):
|
||||
return db.query(PaymentMethod).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_payment_methods(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(PaymentMethod)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [PaymentMethodDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{key}", response_model=PaymentMethodDTO)
|
||||
def get_payment_method(key: str, db: Session = Depends(get_core_db)):
|
||||
def get_payment_method(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(PaymentMethod).filter(PaymentMethod.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.payment_methods.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_payment_methods(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/payment-methods/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_payment_method_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/payment-methods/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_payment_method_forbidden():
|
||||
response = client.post("/payment-methods/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_payment_method_forbidden():
|
||||
response = client.put("/payment-methods/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_payment_method_forbidden():
|
||||
response = client.delete("/payment-methods/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,10 +1,10 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
from typing import Optional
|
||||
|
||||
class PedimentoCodeDTO(BaseModel):
|
||||
code: str = Field(..., min_length=1, max_length=3)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import PedimentoCode
|
||||
from .dto import PedimentoCodeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/pedimento-codes", tags=["Pedimento Codes"])
|
||||
|
||||
@router.get("/", response_model=list[PedimentoCodeDTO])
|
||||
def list_pedimento_codes(db: Session = Depends(get_core_db)):
|
||||
return db.query(PedimentoCode).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_pedimento_codes(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(PedimentoCode)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [PedimentoCodeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{code}", response_model=PedimentoCodeDTO)
|
||||
def get_pedimento_code(code: str, db: Session = Depends(get_core_db)):
|
||||
def get_pedimento_code(code: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(PedimentoCode).filter(PedimentoCode.code == code).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.pedimento_codes.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_pedimento_codes(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/pedimento-codes/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_pedimento_code_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/pedimento-codes/invalid_code", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_pedimento_code_forbidden():
|
||||
response = client.post("/pedimento-codes/", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_pedimento_code_forbidden():
|
||||
response = client.put("/pedimento-codes/TST", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_pedimento_code_forbidden():
|
||||
response = client.delete("/pedimento-codes/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
from typing import List
|
||||
|
||||
class RegimenPedimentoDTO(BaseModel):
|
||||
code: str = Field(..., min_length=1, max_length=3)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import RegimenPedimento
|
||||
from .dto import RegimenPedimentoDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/pedimento-regimens", tags=["Pedimento Regimens"])
|
||||
|
||||
@router.get("/", response_model=list[RegimenPedimentoDTO])
|
||||
def list_pedimento_regimens(db: Session = Depends(get_core_db)):
|
||||
objs = db.query(RegimenPedimento).all()
|
||||
return [RegimenPedimentoDTO.model_validate(obj) for obj in objs]
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_pedimento_regimens(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(RegimenPedimento)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [RegimenPedimentoDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{key}", response_model=RegimenPedimentoDTO)
|
||||
def get_pedimento_regimen(key: str, db: Session = Depends(get_core_db)):
|
||||
def get_pedimento_regimen(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(RegimenPedimento).filter(RegimenPedimento.code == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.pedimento_regimens.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_pedimento_regimens(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/pedimento-regimens/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_pedimento_regimen_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/pedimento-regimens/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_pedimento_regimen_forbidden():
|
||||
response = client.post("/pedimento-regimens/", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_pedimento_regimen_forbidden():
|
||||
response = client.put("/pedimento-regimens/TST", json={"code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_pedimento_regimen_forbidden():
|
||||
response = client.delete("/pedimento-regimens/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,10 +1,10 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class SectorDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=8)
|
||||
description: str
|
||||
authorized: int
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import Sector
|
||||
from .dto import SectorDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/sectors", tags=["Sectors"])
|
||||
|
||||
@router.get("/", response_model=list[SectorDTO])
|
||||
def list_sectors(db: Session = Depends(get_core_db)):
|
||||
return db.query(Sector).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_sectors(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(Sector)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [SectorDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{key}", response_model=SectorDTO)
|
||||
def get_sector(key: str, db: Session = Depends(get_core_db)):
|
||||
def get_sector(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(Sector).filter(Sector.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.sectors.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_sectors(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/sectors/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_sector_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/sectors/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_sector_forbidden():
|
||||
response = client.post("/sectors/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_sector_forbidden():
|
||||
response = client.put("/sectors/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_sector_forbidden():
|
||||
response = client.delete("/sectors/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,4 +1,5 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
from typing import Optional
|
||||
|
||||
class StateDTO(BaseModel):
|
||||
@@ -7,6 +8,5 @@ class StateDTO(BaseModel):
|
||||
mex_key: Optional[str] = None
|
||||
ame_key: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,42 +1,66 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import State
|
||||
from .dto import StateDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/states", tags=["States"])
|
||||
|
||||
@router.get("/", response_model=list[StateDTO])
|
||||
def list_states(db: Session = Depends(get_core_db)):
|
||||
return db.query(State).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_states(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(State)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [StateDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{m3_key}", response_model=StateDTO)
|
||||
def get_state(m3_key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_state(m3_key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(State).filter(State.m3_key == m3_key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=StateDTO, status_code=201)
|
||||
def create_state(
|
||||
async def create_state(
|
||||
data: StateDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
):
|
||||
|
||||
obj = State(**data.dict())
|
||||
db.add(obj)
|
||||
db.commit()
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{m3_key}", response_model=StateDTO)
|
||||
def update_state(
|
||||
async def update_state(
|
||||
m3_key: str,
|
||||
data: StateDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
):
|
||||
|
||||
obj = db.query(State).filter(State.m3_key == m3_key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
@@ -46,12 +70,14 @@ def update_state(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{m3_key}", status_code=204)
|
||||
def delete_state(
|
||||
async def delete_state(
|
||||
m3_key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
):
|
||||
|
||||
obj = db.query(State).filter(State.m3_key == m3_key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.states.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_states(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/states/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_state_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/states/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_state_forbidden():
|
||||
response = client.post("/states/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_state_forbidden():
|
||||
response = client.put("/states/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_state_forbidden():
|
||||
response = client.delete("/states/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class TransportModeDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=3)
|
||||
name: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,28 +1,48 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import has_role, get_current_user
|
||||
from .models import TransportMode
|
||||
from .dto import TransportModeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/transport-modes", tags=["Transport Modes"])
|
||||
|
||||
@router.get("/", response_model=list[TransportModeDTO])
|
||||
def list_transport_modes(db: Session = Depends(get_core_db)):
|
||||
return db.query(TransportMode).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_transport_modes(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(TransportMode)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [TransportModeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=TransportModeDTO)
|
||||
def get_transport_mode(key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_transport_mode(key: str, db: Session = Depends(get_core_db)):
|
||||
obj = db.query(TransportMode).filter(TransportMode.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=TransportModeDTO, status_code=201)
|
||||
def create_transport_mode(
|
||||
async def create_transport_mode(
|
||||
data: TransportModeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = TransportMode(**data.dict())
|
||||
db.add(obj)
|
||||
@@ -30,12 +50,13 @@ def create_transport_mode(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=TransportModeDTO)
|
||||
def update_transport_mode(
|
||||
async def update_transport_mode(
|
||||
key: str,
|
||||
data: TransportModeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = db.query(TransportMode).filter(TransportMode.key == key).first()
|
||||
if not obj:
|
||||
@@ -46,11 +67,12 @@ def update_transport_mode(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{key}", status_code=204)
|
||||
def delete_transport_mode(
|
||||
async def delete_transport_mode(
|
||||
key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = db.query(TransportMode).filter(TransportMode.key == key).first()
|
||||
if not obj:
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.transport_modes.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_transport_modes(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/transport-modes/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_transport_mode_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/transport-modes/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_transport_mode_forbidden():
|
||||
response = client.post("/transport-modes/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_transport_mode_forbidden():
|
||||
response = client.put("/transport-modes/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_transport_mode_forbidden():
|
||||
response = client.delete("/transport-modes/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class TransportTypeDTO(BaseModel):
|
||||
transport_code: str = Field(..., min_length=1, max_length=2)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import has_role, get_current_user
|
||||
from .models import TransportType
|
||||
from .dto import TransportTypeDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/transport-types", tags=["Transport Types"])
|
||||
|
||||
@router.get("/", response_model=list[TransportTypeDTO])
|
||||
def list_transport_types(db: Session = Depends(get_core_db)):
|
||||
return db.query(TransportType).all()
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
def list_transport_types(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(TransportType)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [TransportTypeDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
@router.get("/{transport_code}", response_model=TransportTypeDTO)
|
||||
def get_transport_type(transport_code: str, db: Session = Depends(get_core_db)):
|
||||
@@ -22,7 +39,7 @@ def get_transport_type(transport_code: str, db: Session = Depends(get_core_db)):
|
||||
def create_transport_type(
|
||||
data: TransportTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = TransportType(**data.dict())
|
||||
db.add(obj)
|
||||
@@ -35,7 +52,7 @@ def update_transport_type(
|
||||
transport_code: str,
|
||||
data: TransportTypeDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = db.query(TransportType).filter(TransportType.transport_code == transport_code).first()
|
||||
if not obj:
|
||||
@@ -50,7 +67,7 @@ def update_transport_type(
|
||||
def delete_transport_type(
|
||||
transport_code: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
user=Depends(get_current_user)
|
||||
):
|
||||
obj = db.query(TransportType).filter(TransportType.transport_code == transport_code).first()
|
||||
if not obj:
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.transport_types.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_transport_types(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/transport-types/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_transport_type_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/transport-types/invalid_code", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_transport_type_forbidden():
|
||||
response = client.post("/transport-types/", json={"transport_code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_transport_type_forbidden():
|
||||
response = client.put("/transport-types/TST", json={"transport_code": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_transport_type_forbidden():
|
||||
response = client.delete("/transport-types/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -1,9 +1,9 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import ConfigDict
|
||||
|
||||
class ValuationMethodDTO(BaseModel):
|
||||
key: str = Field(..., min_length=1, max_length=2)
|
||||
description: str
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@@ -1,25 +1,46 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from core.database import get_core_db
|
||||
from core.security import has_role
|
||||
from core.security import get_current_user, has_role
|
||||
from .models import ValuationMethod
|
||||
from .dto import ValuationMethodDTO
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
router = APIRouter(prefix="/valuation-methods", tags=["Valuation Methods"])
|
||||
|
||||
@router.get("/", response_model=list[ValuationMethodDTO])
|
||||
def list_valuation_methods(db: Session = Depends(get_core_db)):
|
||||
return db.query(ValuationMethod).all()
|
||||
|
||||
|
||||
@router.get("/", response_model=Dict[str, Any])
|
||||
async def list_valuation_methods(
|
||||
page: int = Query(1, ge=1, description="Número de página"),
|
||||
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
skip = (page - 1) * page_size
|
||||
query = db.query(ValuationMethod)
|
||||
items = query.offset(skip).limit(page_size).all()
|
||||
total = query.count()
|
||||
return {
|
||||
"items": [ValuationMethodDTO.model_validate(obj) for obj in items],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=ValuationMethodDTO)
|
||||
def get_valuation_method(key: str, db: Session = Depends(get_core_db)):
|
||||
async def get_valuation_method(key: str, db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user)):
|
||||
obj = db.query(ValuationMethod).filter(ValuationMethod.key == key).first()
|
||||
if not obj:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return obj
|
||||
|
||||
|
||||
@router.post("/", response_model=ValuationMethodDTO, status_code=201)
|
||||
def create_valuation_method(
|
||||
async def create_valuation_method(
|
||||
data: ValuationMethodDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
@@ -30,8 +51,9 @@ def create_valuation_method(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=ValuationMethodDTO)
|
||||
def update_valuation_method(
|
||||
async def update_valuation_method(
|
||||
key: str,
|
||||
data: ValuationMethodDTO,
|
||||
db: Session = Depends(get_core_db),
|
||||
@@ -46,8 +68,9 @@ def update_valuation_method(
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
@router.delete("/{key}", status_code=204)
|
||||
def delete_valuation_method(
|
||||
async def delete_valuation_method(
|
||||
key: str,
|
||||
db: Session = Depends(get_core_db),
|
||||
current_user: dict = Depends(has_role("admin"))
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from api.v1.modules.public.reference_data.valuation_methods.routes import router
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
app.include_router(router)
|
||||
client = TestClient(app)
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_list_valuation_methods(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/valuation-methods/", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert "items" in response.json()
|
||||
assert "page" in response.json()
|
||||
assert "page_size" in response.json()
|
||||
|
||||
@pytest.mark.usefixtures("client", "access_token")
|
||||
def test_get_valuation_method_not_found(client, access_token):
|
||||
headers = {"Authorization": f"Bearer {access_token}"}
|
||||
response = client.get("/valuation-methods/invalid_key", headers=headers)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_create_valuation_method_forbidden():
|
||||
response = client.post("/valuation-methods/", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_update_valuation_method_forbidden():
|
||||
response = client.put("/valuation-methods/TST", json={"key": "TST", "description": "Test"})
|
||||
assert response.status_code in (403, 405, 404)
|
||||
|
||||
def test_delete_valuation_method_forbidden():
|
||||
response = client.delete("/valuation-methods/TST")
|
||||
assert response.status_code in (403, 405, 404)
|
||||
@@ -4,7 +4,7 @@ Configuración de base de datos con soporte multi-tenant
|
||||
- Bases de datos dedicadas para clientes enterprise
|
||||
"""
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||
from typing import Generator, Dict, Optional, AsyncGenerator
|
||||
|
||||
@@ -25,26 +25,24 @@ class TenantMiddleware(BaseHTTPMiddleware):
|
||||
|
||||
async def dispatch(self, request: Request, call_next: Callable):
|
||||
# Rutas públicas que no requieren tenant
|
||||
public_paths = [
|
||||
"/api/docs",
|
||||
# Permitir acceso sin autenticación a rutas de documentación y salud
|
||||
doc_prefixes = [
|
||||
"/api/redoc",
|
||||
"/api/openapi.json",
|
||||
"/api/v1/auth",
|
||||
"/api/v1/auth",
|
||||
"/api/v1/status",
|
||||
"/api/openapi.json"
|
||||
]
|
||||
public_prefixes = [
|
||||
"/api/v1/auth",
|
||||
"/api/v1/status",
|
||||
"/api/health",
|
||||
"/api/"
|
||||
]
|
||||
|
||||
# Verificar si la ruta es pública (comparación exacta o prefijo)
|
||||
is_public = False
|
||||
for path in public_paths:
|
||||
if request.url.path == path or (path != "/" and request.url.path.startswith(path)):
|
||||
is_public = True
|
||||
break
|
||||
|
||||
if is_public:
|
||||
|
||||
path = request.url.path
|
||||
# Permitir cualquier subruta de docs/redoc/openapi.json (por ejemplo, /api/docs, /api/docs/, /api/docs/oauth2-redirect)
|
||||
if any(path == prefix or path.startswith(prefix + "/") for prefix in doc_prefixes):
|
||||
return await call_next(request)
|
||||
# Permitir rutas públicas exactas o con prefijo
|
||||
if any(path == prefix or (prefix != "/" and path.startswith(prefix)) for prefix in public_prefixes):
|
||||
return await call_next(request)
|
||||
|
||||
# Extraer token y obtener tenant
|
||||
|
||||
Reference in New Issue
Block a user