Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions api/src/bracc/routers/emendas.py

This file was deleted.

5 changes: 5 additions & 0 deletions api/src/bracc/routers/emendas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Emendas router package."""

from .routes import router

__all__ = ["router"]
68 changes: 68 additions & 0 deletions api/src/bracc/routers/emendas/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Orchestration layer for the emendas endpoint."""

from typing import cast

from neo4j import AsyncSession

from bracc.services.neo4j_service import execute_query, sanitize_props
from bracc.services.public_guard import sanitize_public_properties

from .model import (
EmendaRecord,
EmendasCountRow,
EmendasListResponse,
EmendasListRow,
EmendasQueryName,
EmendasRecordKey,
)


async def list_emendas_tesouro(
session: AsyncSession,
skip: int,
limit: int,
) -> EmendasListResponse:
"""List Tesouro emendas payments with pagination."""

count_records = cast(
"list[EmendasCountRow]",
await execute_query(session, EmendasQueryName.TESOURO_COUNT, {}),
)
total_count = (
count_records[0][EmendasRecordKey.TOTAL.value]
if count_records
else 0
)

records = cast(
"list[EmendasListRow]",
await execute_query(
session,
EmendasQueryName.TESOURO_LIST,
{"skip": skip, "limit": limit},
),
)

results: list[EmendaRecord] = []
for record in records:
payment_props = sanitize_public_properties(
sanitize_props(
dict(record[EmendasRecordKey.PAYMENT.value])
)
)
company_props = None
beneficiary_raw = record[EmendasRecordKey.BENEFICIARY.value]

if beneficiary_raw is not None:
company_props = sanitize_public_properties(
sanitize_props(dict(beneficiary_raw))
)

results.append(EmendaRecord(payment=payment_props, beneficiary=company_props))

return EmendasListResponse(
data=results,
total_count=total_count,
skip=skip,
limit=limit,
)
44 changes: 44 additions & 0 deletions api/src/bracc/routers/emendas/model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Types and contracts for the emendas module."""

from enum import StrEnum
from typing import Any, TypedDict

from bracc.models.emendas import EmendaRecord, EmendasListResponse


class EmendasQueryName(StrEnum):
"""Cypher query names used by the emendas endpoint."""

TESOURO_COUNT = "emendas_tesouro_count"
TESOURO_LIST = "emendas_tesouro_list"


class EmendasRecordKey(StrEnum):
"""Expected keys in Neo4j record payloads."""

TOTAL = "total"
PAYMENT = "p"
BENEFICIARY = "c"


class EmendasCountRow(TypedDict):
"""Shape of each row returned by the count query."""

total: int


class EmendasListRow(TypedDict):
"""Shape of each row returned by the list query."""

p: dict[str, Any]
c: dict[str, Any] | None


__all__ = [
"EmendaRecord",
"EmendasListResponse",
"EmendasCountRow",
"EmendasListRow",
"EmendasQueryName",
"EmendasRecordKey"
]
23 changes: 23 additions & 0 deletions api/src/bracc/routers/emendas/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Public HTTP routes for emendas."""

from typing import Annotated

from fastapi import APIRouter, Depends, Query
from neo4j import AsyncSession

from bracc.dependencies import get_session

from . import controller
from .model import EmendasListResponse

router = APIRouter(prefix="/api/v1/emendas", tags=["emendas"])


@router.get("/", response_model=EmendasListResponse)
async def list_emendas_tesouro(
session: Annotated[AsyncSession, Depends(get_session)],
skip: Annotated[int, Query(ge=0)] = 0,
limit: Annotated[int, Query(ge=1, le=100)] = 50,
) -> EmendasListResponse:
"""Expose Tesouro emendas listing with pagination."""
return await controller.list_emendas_tesouro(session, skip, limit)
Loading
Loading