Skip to content
Open
6 changes: 6 additions & 0 deletions gateway-api/src/gateway_api/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
# The alias is used to make intent clearer in function signatures.
type json_str = str

# Access record structured interaction ID from
# https://developer.nhs.uk/apis/gpconnect/accessrecord_structured_development.html#spine-interactions
ACCESS_RECORD_STRUCTURED_INTERACTION_ID = (
"urn:nhs:names:services:gpconnect:fhir:operation:gpc.getstructuredrecord-1"
)


@dataclass
class FlaskResponse:
Expand Down
63 changes: 4 additions & 59 deletions gateway-api/src/gateway_api/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from gateway_api.common.common import FlaskResponse
from gateway_api.pds_search import PdsClient, PdsSearchResults
from gateway_api.sds_search import SdsClient, SdsSearchResults


@dataclass
Expand All @@ -44,62 +45,6 @@ def __str__(self) -> str:
return self.message


@dataclass
class SdsSearchResults:
"""
Stub SDS search results dataclass.

Replace this with the real one once it's implemented.

:param asid: Accredited System ID.
:param endpoint: Endpoint URL associated with the organisation, if applicable.
"""

asid: str
endpoint: str | None


class SdsClient:
"""
Stub SDS client for obtaining ASID from ODS code.

Replace this with the real one once it's implemented.
"""

SANDBOX_URL = "https://example.invalid/sds"

def __init__(
self,
auth_token: str,
base_url: str = SANDBOX_URL,
timeout: int = 10,
) -> None:
"""
Create an SDS client.

:param auth_token: Authentication token to present to SDS.
:param base_url: Base URL for SDS.
:param timeout: Timeout in seconds for SDS calls.
"""
self.auth_token = auth_token
self.base_url = base_url
self.timeout = timeout

def get_org_details(self, ods_code: str) -> SdsSearchResults | None:
"""
Retrieve SDS org details for a given ODS code.

This is a placeholder implementation that always returns an ASID and endpoint.

:param ods_code: ODS code to look up.
:returns: SDS search results or ``None`` if not found.
"""
# Placeholder implementation
return SdsSearchResults(
asid=f"asid_{ods_code}", endpoint="https://example-provider.org/endpoint"
)


class Controller:
"""
Orchestrates calls to PDS -> SDS -> GP provider.
Expand All @@ -113,7 +58,7 @@ class Controller:
def __init__(
self,
pds_base_url: str = PdsClient.SANDBOX_URL,
sds_base_url: str = "https://example.invalid/sds",
sds_base_url: str = SdsClient.SANDBOX_URL,
nhsd_session_urid: str | None = None,
timeout: int = 10,
) -> None:
Expand Down Expand Up @@ -252,15 +197,15 @@ def _get_sds_details(
- provider details (ASID + endpoint)
- consumer details (ASID)

:param auth_token: Authorization token to use for SDS.
:param auth_token: Authorization token to use for SDS (used as API key).
:param consumer_ods: Consumer organisation ODS code (from request headers).
:param provider_ods: Provider organisation ODS code (from PDS).
:returns: Tuple of (consumer_asid, provider_asid, provider_endpoint).
:raises RequestError: If SDS data is missing or incomplete for provider/consumer
"""
# SDS: Get provider details (ASID + endpoint) for provider ODS
sds = SdsClient(
auth_token=auth_token,
api_key=auth_token,
base_url=self.sds_base_url,
timeout=self.timeout,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from fhir.operation_outcome import OperationOutcomeIssue
from flask.wrappers import Request, Response

from gateway_api.common.common import FlaskResponse
from gateway_api.common.common import (
ACCESS_RECORD_STRUCTURED_INTERACTION_ID,
FlaskResponse,
)

if TYPE_CHECKING:
from fhir.bundle import Bundle
Expand All @@ -16,7 +19,7 @@ class RequestValidationError(Exception):


class GetStructuredRecordRequest:
INTERACTION_ID: str = "urn:nhs:names:services:gpconnect:gpc.getstructuredrecord-1"
INTERACTION_ID: str = ACCESS_RECORD_STRUCTURED_INTERACTION_ID
RESOURCE: str = "patient"
FHIR_OPERATION: str = "$gpc.getstructuredrecord"

Expand Down
11 changes: 6 additions & 5 deletions gateway-api/src/gateway_api/provider_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
from urllib.parse import urljoin

from requests import HTTPError, Response, post
from stubs.stub_provider import stub_post
from stubs.stub_provider import GpProviderStub

ARS_INTERACTION_ID = (
"urn:nhs:names:services:gpconnect:structured"
":fhir:operation:gpc.getstructuredrecord-1"
from gateway_api.common.common import (
ACCESS_RECORD_STRUCTURED_INTERACTION_ID as ARS_INTERACTION_ID,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is now nicely defined in common, is it better to just rename in this module than alias?

)

ARS_FHIR_BASE = "FHIR/STU3"
FHIR_RESOURCE = "patient"
ARS_FHIR_OPERATION = "$gpc.getstructuredrecord"
Expand All @@ -43,7 +43,8 @@
# Direct all requests to the stub provider for steel threading in dev.
# Replace with `from requests import post` for real requests.
PostCallable = Callable[..., Response]
post: PostCallable = stub_post # type: ignore[no-redef]
_gp_provider_stub = GpProviderStub()
post: PostCallable = _gp_provider_stub.post # type: ignore[no-redef]


class ExternalServiceError(Exception):
Expand Down
Loading