Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7499852
refactor(services): expose public symbols via __init__.py and update …
rusiru-erandaka Jun 24, 2026
a28e2c2
refactor(core): expose public symbols via __init__.py
rusiru-erandaka Jun 24, 2026
0d9884b
refactor(exception): expose public symbols via __init__.py
rusiru-erandaka Jun 24, 2026
87f7643
refactor(middleware): expose public symbols via __init__.py and updat…
rusiru-erandaka Jun 24, 2026
776e8e3
refactor(models): expose public symbols via __init__.py
rusiru-erandaka Jun 24, 2026
08357db
refactor(utils): expose public symbols via __init__.py and update htt…
rusiru-erandaka Jun 24, 2026
ae0fcd0
refactor(routers): expose public symbols via __init__.py and update r…
rusiru-erandaka Jun 24, 2026
c470e1b
refactor(main): update imports to use package-level interface
rusiru-erandaka Jun 24, 2026
faaeeb5
test: update test imports to use package-level interface
rusiru-erandaka Jun 24, 2026
23c766f
chore: update .env.example with new service configuration
rusiru-erandaka Jun 24, 2026
591bf41
Update package import alphabetically src/services/__init__.py
rusiru-erandaka Jun 24, 2026
c734f1d
Update according to the alphabetical oder. src/services/__init__.py
rusiru-erandaka Jun 24, 2026
ece2c1e
Update importers according to alphabetical oder. src/models/__init__.py
rusiru-erandaka Jun 24, 2026
c869033
Return department ids for links of cabinet flow response
zaeema-n Jun 26, 2026
db52c27
Add endpoint to resolve entity IDs to display names
zaeema-n Jun 26, 2026
f8ad791
Refactor organisation_service to simplify department link aggregation…
zaeema-n Jun 26, 2026
9a38e5f
added relative imports instead of absolute imports in enums
rusiru-erandaka Jun 26, 2026
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
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BASE_URL_QUERY=base-url-query
BASE_URL_QUERY=BASE_URL_QUERY
# Comma-separated list of allowed origins for CORS (replace as needed)
ALLOWED_ORIGINS=http://localhost:3000

Expand Down
46 changes: 46 additions & 0 deletions gi_service/contract/rest/organisation_api_contract.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ paths:
- source
- target
- value
- departmentIds
properties:
source:
type: integer
Expand All @@ -196,6 +197,11 @@ paths:
value:
type: integer
description: Number of departments shared between the source and target ministry nodes.
departmentIds:
type: array
items:
type: string
description: IDs of the departments that moved along this link between consecutive dates.
dates:
type: array
items:
Expand Down Expand Up @@ -226,6 +232,9 @@ paths:
- source: 0
target: 1
value: 25
departmentIds:
- "2289-43_dep_1"
- "2289-43_dep_2"
dates:
- date: "2024-09-23"
status: "ok"
Expand Down Expand Up @@ -402,6 +411,43 @@ paths:
"500":
description: Server Error

/v1/organisation/entity-names:
post:
tags:
- Organization
summary: Resolve entity IDs to display names.
description: Returns a dictionary mapping each entity ID to its decoded display name. IDs that cannot be resolved are omitted from the response.
operationId: resolveEntityNames
requestBody:
required: true
description: List of entity IDs to resolve.
content:
application/json:
schema:
type: array
items:
type: string
example:
- "2289-43_min_1"
- "2289-43_dep_1"
responses:
"200":
description: Successfully returned
content:
application/json:
schema:
type: object
additionalProperties:
type: string
description: Map of entity ID to display name.
example:
"2289-43_min_1": "Minister of Defence"
"2289-43_dep_1": "Ministry of Health"
"400":
description: Bad request
"500":
description: Server Error

/v1/organisation/department-history/{department_id}:
get:
tags:
Expand Down
8 changes: 4 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
person_router,
document_router,
)
from src.core.config import settings
from src.core import settings
from fastapi.middleware.cors import CORSMiddleware
from src.middleware.throttling import ThrottlingMiddleware
from src.utils.http_client import http_client
from src.middleware import ThrottlingMiddleware
from src.utils import http_client
from contextlib import asynccontextmanager

@asynccontextmanager
Expand Down Expand Up @@ -46,4 +46,4 @@ async def lifespan(app: FastAPI):
app.include_router(data_router)
app.include_router(search_router)
app.include_router(person_router)
app.include_router(document_router)
app.include_router(document_router)
4 changes: 4 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""Top-level package for the GI Service application."""

# Intentionally avoid re-exporting subpackages here to keep imports explicit.
__all__: list[str] = []
6 changes: 6 additions & 0 deletions src/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .config import Settings, settings

__all__ = [
"Settings",
"settings",
]
6 changes: 3 additions & 3 deletions src/enums/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from src.enums.kindEnum import KindMajorEnum, KindMinorEnum
from src.enums.relationEnum import RelationNameEnum, RelationDirectionEnum
from src.enums.idEnum import EntityIdEnum
from .kindEnum import KindMajorEnum, KindMinorEnum
from .relationEnum import RelationNameEnum, RelationDirectionEnum
from .idEnum import EntityIdEnum

__all__ = [
"KindMajorEnum",
Expand Down
15 changes: 15 additions & 0 deletions src/exception/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .exceptions import (
BadRequestError,
GatewayTimeoutError,
InternalServerError,
NotFoundError,
ServiceUnavailableError,
)

__all__ = [
"BadRequestError",
"GatewayTimeoutError",
"InternalServerError",
"NotFoundError",
"ServiceUnavailableError",
]
5 changes: 5 additions & 0 deletions src/middleware/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .throttling import ThrottlingMiddleware

__all__ = [
"ThrottlingMiddleware",
]
2 changes: 1 addition & 1 deletion src/middleware/throttling.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import JSONResponse
from src.core.config import settings
from src.core import settings

logger = logging.getLogger(__name__)

Expand Down
30 changes: 28 additions & 2 deletions src/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
from .person_schemas import PersonSource, PersonResponse
from .data_requestbody import DataCatalogRequest, DatasetYearsRequest
from .organisation_schemas import (
AttributeFilterRecord,
AttributeFilterRecords,
Category,
Dataset,
Date,
Entity,
Kind,
Label,
Relation,
)
from .person_schemas import PersonResponse, PersonSource
from .search_schemas import SearchResponse, SearchResult

__all__ = [
"AttributeFilterRecord",
"AttributeFilterRecords",
"Category",
"DataCatalogRequest",
"Dataset",
"DatasetYearsRequest",
"Date",
"Entity",
"Kind",
"Label",
"PersonSource",
"PersonResponse"
"PersonResponse",
Comment thread
rusiru-erandaka marked this conversation as resolved.
"Relation",
"SearchResponse",
"SearchResult",
]
6 changes: 2 additions & 4 deletions src/routers/data_router.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from src.models.data_requestbody import DatasetYearsRequest
from src.models.data_requestbody import DataCatalogRequest
from fastapi.param_functions import Depends, Query, Body, Path
from src.services.data_service import DataService
from src.services.opengin_service import OpenGINService
from fastapi import APIRouter
from pydantic import BaseModel, Field
from src.models import DataCatalogRequest, DatasetYearsRequest
from src.services import DataService, OpenGINService

router = APIRouter(prefix="/v1/data", tags=["Data"])

Expand Down
13 changes: 12 additions & 1 deletion src/routers/organisation_router.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from fastapi import APIRouter, Depends, Query, Body, Path
from src.models.organisation_schemas import Date
from src.models import Date
from src.services import OpenGINService, OrganisationService
from typing import Sequence

Expand Down Expand Up @@ -44,6 +44,17 @@ async def cabinet_flow(
service_response = await service.fetch_cabinet_flow(president_id=president_id, dates=dates)
return service_response

@router.post("/entity-names", summary="Resolve entity IDs to display names.", description="Returns a dictionary mapping each entity ID to its decoded display name.")
async def entity_names(
entity_ids: list[str] = Body(
...,
description="List of entity IDs to resolve.",
example=["2153-12_dep_168", "2153-12_dep_171"],
),
service: OrganisationService = Depends(get_organisation_service),
):
return await service.resolve_entity_names(entity_ids)

@router.get('/department-history/{department_id}', summary="Get department history timeline.", description="Returns a timeline of a department including ministry relations and ministers.")
async def department_history_timeline(
department_id: str = Path(..., description="ID of the department"),
Expand Down
5 changes: 2 additions & 3 deletions src/routers/search_router.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from fastapi import APIRouter, Depends, Query
from typing import Optional, List
from datetime import datetime
from src.services.search_service import SearchService
from src.services.opengin_service import OpenGINService
from src.models.search_schemas import SearchResponse
from src.models import SearchResponse
from src.services import OpenGINService, SearchService

router = APIRouter(prefix="/v1/search", tags=["Search"])

Expand Down
14 changes: 9 additions & 5 deletions src/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from .organisation_service import OrganisationService
from .data_service import DataService
from .document_service import DocumentService
from .opengin_service import OpenGINService
from .organisation_service import OrganisationService
from .person_service import PersonService
from .document_service import DocumentService
from .search_service import SearchService
Comment thread
rusiru-erandaka marked this conversation as resolved.

__all__ = [
"OrganisationService",
"DataService",
"DocumentService",
"OpenGINService",
"OrganisationService",
"PersonService",
"DocumentService"
]
"SearchService",
]
10 changes: 3 additions & 7 deletions src/services/data_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@
import asyncio
from typing import Dict
from src.enums import KindMajorEnum, KindMinorEnum, RelationNameEnum, RelationDirectionEnum
from src.exception.exceptions import InternalServerError, NotFoundError
from src.exception.exceptions import BadRequestError
from src.models.organisation_schemas import Relation
from src.utils.util_functions import Util
from src.models.organisation_schemas import Kind
from src.models.organisation_schemas import Entity
from src.exception import BadRequestError, InternalServerError, NotFoundError
from src.models import Entity, Kind, Relation
from aiohttp import ClientSession
from src.utils import http_client
from src.utils import Util, http_client

logger = logging.getLogger(__name__)

Expand Down
11 changes: 5 additions & 6 deletions src/services/document_service.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from src.exception.exceptions import InternalServerError
import asyncio
from src.utils.util_functions import Util
from aiohttp import ClientSession
from src.utils import http_client
from src.models.organisation_schemas import Entity, Kind
from src.enums.kindEnum import KindMajorEnum, KindMinorEnum
from typing import Dict, List
from datetime import datetime
import logging
from typing import Dict, List
from src.enums import KindMajorEnum, KindMinorEnum
from src.exception import InternalServerError
from src.models import Entity, Kind
from src.utils import Util, http_client

logger = logging.getLogger(__name__)

Expand Down
17 changes: 5 additions & 12 deletions src/services/opengin_service.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
from asyncio import timeout
from google.api_core.exceptions import GoogleAPICallError
from google.api_core.retry import if_transient_error
from src.models.organisation_schemas import AttributeFilterRecords
from src.models.organisation_schemas import Entity, Relation
from src.exception.exceptions import BadRequestError
from src.exception.exceptions import InternalServerError
from src.exception.exceptions import NotFoundError
from google.api_core import retry_async
from google.api_core import exceptions
from aiohttp import ClientSession
from src.utils.http_client import http_client
from src.core.config import settings
import logging
from src.core import settings
from src.exception import BadRequestError, InternalServerError, NotFoundError
from src.models import AttributeFilterRecords, Entity, Relation
from src.utils import http_client

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -194,4 +187,4 @@ async def get_attributes(
raise InternalServerError("An unexpected error occurred") from e




Loading
Loading