From 902e298f0fe05793181396ea4983d28593a852be Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 15:05:45 +0000 Subject: [PATCH] Release 8.2.0-beta --- pyproject.toml | 2 +- src/metriport/core/client_wrapper.py | 2 +- src/metriport/medical/__init__.py | 2 + src/metriport/medical/patient/__init__.py | 2 + src/metriport/medical/patient/client.py | 149 ++++++++++++++++++ .../medical/patient/types/__init__.py | 2 + .../medical/patient/types/base_patient.py | 27 +--- .../medical/patient/types/demographics.py | 52 ++++++ 8 files changed, 211 insertions(+), 27 deletions(-) create mode 100644 src/metriport/medical/patient/types/demographics.py diff --git a/pyproject.toml b/pyproject.toml index 6ea66ba..f5df76f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "metriport" -version = "8.1.0-beta" +version = "8.2.0-beta" description = "" readme = "README.md" authors = [] diff --git a/src/metriport/core/client_wrapper.py b/src/metriport/core/client_wrapper.py index 6d4cbe0..6128dee 100644 --- a/src/metriport/core/client_wrapper.py +++ b/src/metriport/core/client_wrapper.py @@ -14,7 +14,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "metriport", - "X-Fern-SDK-Version": "8.1.0-beta", + "X-Fern-SDK-Version": "8.2.0-beta", } headers["X-API-Key"] = self.api_key return headers diff --git a/src/metriport/medical/__init__.py b/src/metriport/medical/__init__.py index e735dde..6a7b458 100644 --- a/src/metriport/medical/__init__.py +++ b/src/metriport/medical/__init__.py @@ -24,6 +24,7 @@ from .patient import ( BasePatient, Contact, + Demographics, DriversLicense, FacilityId, ListPatientsResponse, @@ -54,6 +55,7 @@ "ConsolidatedWebhookStatus", "Contact", "ConversionType", + "Demographics", "DocumentQuery", "DocumentQueryStatus", "DocumentUrl", diff --git a/src/metriport/medical/patient/__init__.py b/src/metriport/medical/patient/__init__.py index 76c0b95..cbccddb 100644 --- a/src/metriport/medical/patient/__init__.py +++ b/src/metriport/medical/patient/__init__.py @@ -3,6 +3,7 @@ from .types import ( BasePatient, Contact, + Demographics, DriversLicense, FacilityId, ListPatientsResponse, @@ -16,6 +17,7 @@ __all__ = [ "BasePatient", "Contact", + "Demographics", "DriversLicense", "FacilityId", "ListPatientsResponse", diff --git a/src/metriport/medical/patient/client.py b/src/metriport/medical/patient/client.py index 5d53465..43ef87f 100644 --- a/src/metriport/medical/patient/client.py +++ b/src/metriport/medical/patient/client.py @@ -10,6 +10,7 @@ from ...core.remove_none_from_dict import remove_none_from_dict from ...core.request_options import RequestOptions from .types.base_patient import BasePatient +from .types.demographics import Demographics from .types.list_patients_response import ListPatientsResponse from .types.medical_record_status import MedicalRecordStatus from .types.patient import Patient @@ -411,6 +412,80 @@ def get_medical_record_summary_status( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def match(self, *, request: Demographics, request_options: typing.Optional[RequestOptions] = None) -> Patient: + """ + Searches for a Patient previously created in Metriport, based on demographic data. + + Parameters: + - request: Demographics. + + - request_options: typing.Optional[RequestOptions]. Request-specific configuration. + --- + from metriport import Address, UsState + from metriport.client import Metriport + from metriport.medical import Demographics, PersonalIdentifier_DriversLicense + + client = Metriport( + api_key="YOUR_API_KEY", + ) + client.medical.patient.match( + request=Demographics( + first_name="Karen", + last_name="Lynch", + dob="1963-12-30", + gender_at_birth="F", + personal_identifiers=[ + PersonalIdentifier_DriversLicense( + type="driversLicense", + state=UsState.CA, + value="51227265", + ) + ], + address=[ + Address( + address_line_1="2261 Market Street", + address_line_2="#4818", + city="San Francisco", + state=UsState.CA, + zip="94114", + country="USA", + ) + ], + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/patient/match"), + params=jsonable_encoder( + request_options.get("additional_query_parameters") if request_options is not None else None + ), + json=jsonable_encoder(request) + if request_options is None or request_options.get("additional_body_parameters") is None + else { + **jsonable_encoder(request), + **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + }, + headers=jsonable_encoder( + remove_none_from_dict( + { + **self._client_wrapper.get_headers(), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + timeout=request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else 60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncPatientClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -799,3 +874,77 @@ async def get_medical_record_summary_status( except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + + async def match(self, *, request: Demographics, request_options: typing.Optional[RequestOptions] = None) -> Patient: + """ + Searches for a Patient previously created in Metriport, based on demographic data. + + Parameters: + - request: Demographics. + + - request_options: typing.Optional[RequestOptions]. Request-specific configuration. + --- + from metriport import Address, UsState + from metriport.client import AsyncMetriport + from metriport.medical import Demographics, PersonalIdentifier_DriversLicense + + client = AsyncMetriport( + api_key="YOUR_API_KEY", + ) + await client.medical.patient.match( + request=Demographics( + first_name="Karen", + last_name="Lynch", + dob="1963-12-30", + gender_at_birth="F", + personal_identifiers=[ + PersonalIdentifier_DriversLicense( + type="driversLicense", + state=UsState.CA, + value="51227265", + ) + ], + address=[ + Address( + address_line_1="2261 Market Street", + address_line_2="#4818", + city="San Francisco", + state=UsState.CA, + zip="94114", + country="USA", + ) + ], + ), + ) + """ + _response = await self._client_wrapper.httpx_client.request( + "POST", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "medical/v1/patient/match"), + params=jsonable_encoder( + request_options.get("additional_query_parameters") if request_options is not None else None + ), + json=jsonable_encoder(request) + if request_options is None or request_options.get("additional_body_parameters") is None + else { + **jsonable_encoder(request), + **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + }, + headers=jsonable_encoder( + remove_none_from_dict( + { + **self._client_wrapper.get_headers(), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + timeout=request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else 60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(Patient, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/metriport/medical/patient/types/__init__.py b/src/metriport/medical/patient/types/__init__.py index a8fc2fe..b9e9cb8 100644 --- a/src/metriport/medical/patient/types/__init__.py +++ b/src/metriport/medical/patient/types/__init__.py @@ -2,6 +2,7 @@ from .base_patient import BasePatient from .contact import Contact +from .demographics import Demographics from .drivers_license import DriversLicense from .facility_id import FacilityId from .list_patients_response import ListPatientsResponse @@ -13,6 +14,7 @@ __all__ = [ "BasePatient", "Contact", + "Demographics", "DriversLicense", "FacilityId", "ListPatientsResponse", diff --git a/src/metriport/medical/patient/types/base_patient.py b/src/metriport/medical/patient/types/base_patient.py index 91e8453..b671a28 100644 --- a/src/metriport/medical/patient/types/base_patient.py +++ b/src/metriport/medical/patient/types/base_patient.py @@ -3,10 +3,8 @@ import datetime as dt import typing -from ....commons.types.address import Address from ....core.datetime_utils import serialize_datetime -from .contact import Contact -from .personal_identifier import PersonalIdentifier +from .demographics import Demographics try: import pydantic.v1 as pydantic # type: ignore @@ -14,28 +12,7 @@ import pydantic # type: ignore -class BasePatient(pydantic.BaseModel): - first_name: str = pydantic.Field( - alias="firstName", - description=( - "The Patient's first name(s).\n" - "You may provide a comma/space delimited string to specify\n" - "multiple first and last names. For example, the following inputs\n" - 'would be equivalent: "John,Jonathan" & "John Jonathan"\n' - ), - ) - last_name: str = pydantic.Field(alias="lastName", description="The Patient's last name(s).") - dob: str = pydantic.Field(description="The Patient's date of birth (DOB), formatted `YYYY-MM-DD` as per ISO 8601.") - gender_at_birth: str = pydantic.Field( - alias="genderAtBirth", description="The Patient's gender at birth, can be one of `M` or `F`." - ) - personal_identifiers: typing.Optional[typing.List[PersonalIdentifier]] = pydantic.Field( - alias="personalIdentifiers", - default=None, - description=("An array of the Patient's personal IDs, such as a driver's license.\n" "May be empty.\n"), - ) - address: typing.List[Address] - contact: typing.Optional[typing.List[Contact]] = None +class BasePatient(Demographics): external_id: typing.Optional[str] = pydantic.Field( alias="externalId", default=None, description="An external Patient ID to associate to a Patient in Metriport." ) diff --git a/src/metriport/medical/patient/types/demographics.py b/src/metriport/medical/patient/types/demographics.py new file mode 100644 index 0000000..9996b95 --- /dev/null +++ b/src/metriport/medical/patient/types/demographics.py @@ -0,0 +1,52 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....commons.types.address import Address +from ....core.datetime_utils import serialize_datetime +from .contact import Contact +from .personal_identifier import PersonalIdentifier + +try: + import pydantic.v1 as pydantic # type: ignore +except ImportError: + import pydantic # type: ignore + + +class Demographics(pydantic.BaseModel): + first_name: str = pydantic.Field( + alias="firstName", + description=( + "The Patient's first name(s).\n" + "You may provide a comma/space delimited string to specify\n" + "multiple first and last names. For example, the following inputs\n" + 'would be equivalent: "John,Jonathan" & "John Jonathan"\n' + ), + ) + last_name: str = pydantic.Field(alias="lastName", description="The Patient's last name(s).") + dob: str = pydantic.Field(description="The Patient's date of birth (DOB), formatted `YYYY-MM-DD` as per ISO 8601.") + gender_at_birth: str = pydantic.Field( + alias="genderAtBirth", description="The Patient's gender at birth, can be one of `M` or `F`." + ) + personal_identifiers: typing.Optional[typing.List[PersonalIdentifier]] = pydantic.Field( + alias="personalIdentifiers", + default=None, + description=("An array of the Patient's personal IDs, such as a driver's license.\n" "May be empty.\n"), + ) + address: typing.List[Address] + contact: typing.Optional[typing.List[Contact]] = None + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime}