From 26d75eca0139354373d7e7c1a5f3597e9e8c1173 Mon Sep 17 00:00:00 2001 From: Beau Gunderson Date: Mon, 2 Mar 2026 10:26:32 -0800 Subject: [PATCH] flesh out pharmacy search with the fields the backend supports --- canvas_sdk/tests/utils/test_http.py | 60 ++++++++++++++++++++++++++++- canvas_sdk/utils/http.py | 47 ++++++++++++++++++---- 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/canvas_sdk/tests/utils/test_http.py b/canvas_sdk/tests/utils/test_http.py index 18eda67d1..8fdf578c1 100644 --- a/canvas_sdk/tests/utils/test_http.py +++ b/canvas_sdk/tests/utils/test_http.py @@ -164,7 +164,7 @@ def test_search_pharmacies_default_search_term(mock_get: MagicMock) -> None: pharmacy_http.search_pharmacies() mock_get.assert_called_once_with( - "https://pharmacy-2017071.canvasmedical.com/surescripts/pharmacy/?search=+", + "https://pharmacy-2017071.canvasmedical.com/surescripts/pharmacy/", headers={}, timeout=30, ) @@ -176,3 +176,61 @@ def test_search_pharmacies_default_search_term(mock_get: MagicMock) -> None: headers={}, timeout=30, ) + + +@patch("requests.Session.get") +def test_search_pharmacies_with_filter_fields(mock_get: MagicMock) -> None: + """Test that search_pharmacies passes filter fields as query parameters.""" + mock_get.return_value = FakeResponse() + + pharmacy_http.search_pharmacies( + search_term=None, + ncpdp_id="1234567", + organization_name="CVS", + state="CA", + zip_code_prefix="902", + specialty_type="retail", + ) + + call_url = mock_get.call_args[0][0] + assert "ncpdp_id=1234567" in call_url + assert "organization_name__icontains=CVS" in call_url + assert "state__iexact=CA" in call_url + assert "zip_code_prefix=902" in call_url + assert "specialty_type__icontains=retail" in call_url + assert "search=" not in call_url + + +@patch("requests.Session.get") +def test_search_pharmacies_with_id(mock_get: MagicMock) -> None: + """Test that search_pharmacies passes an exact id filter.""" + mock_get.return_value = FakeResponse() + + pharmacy_http.search_pharmacies(search_term=None, id=42) + + call_url = mock_get.call_args[0][0] + assert "id=42" in call_url + + +@patch("requests.Session.get") +def test_search_pharmacies_with_zip_code_prefix(mock_get: MagicMock) -> None: + """Test that search_pharmacies passes zip_code_prefix.""" + mock_get.return_value = FakeResponse() + + pharmacy_http.search_pharmacies(search_term=None, zip_code_prefix="902,100,945") + + call_url = mock_get.call_args[0][0] + assert "zip_code_prefix=902%2C100%2C945" in call_url + + +@patch("requests.Session.get") +def test_search_pharmacies_with_location(mock_get: MagicMock) -> None: + """Test that latitude and longitude are passed when provided.""" + mock_get.return_value = FakeResponse() + + pharmacy_http.search_pharmacies("walgreens", latitude="34.05", longitude="-118.24") + + call_url = mock_get.call_args[0][0] + assert "search=walgreens" in call_url + assert "latitude=34.05" in call_url + assert "longitude=-118.24" in call_url diff --git a/canvas_sdk/utils/http.py b/canvas_sdk/utils/http.py index 93bd73af2..f166bd806 100644 --- a/canvas_sdk/utils/http.py +++ b/canvas_sdk/utils/http.py @@ -333,16 +333,47 @@ def search_pharmacies( search_term: str | None = " ", latitude: str | None = None, longitude: str | None = None, + id: int | None = None, + ncpdp_id: str | None = None, + organization_name: str | None = None, + specialty_type: str | None = None, + state: str | None = None, + zip_code_prefix: str | None = None, ) -> list[dict]: - """Search for pharmacies by term and optional location.""" - params = {"search": search_term} + """Search for pharmacies by term and optional location. + + Args: + search_term: Full-text search across multiple fields. + latitude: Latitude for location-based ordering. + longitude: Longitude for location-based ordering. + id: Exact pharmacy ID match. + ncpdp_id: Exact NCPDP ID match. + organization_name: Case-insensitive contains match on organization name. + specialty_type: Case-insensitive contains match on specialty type. + state: Case-insensitive exact match on state. + zip_code_prefix: One or more comma/space-separated zip code prefixes. + """ + params: dict[str, str | int] = {} + + if search_term and search_term.strip(): + params["search"] = search_term + if latitude and longitude: - params.update( - { - "latitude": latitude, - "longitude": longitude, - } - ) + params["latitude"] = latitude + params["longitude"] = longitude + + if id is not None: + params["id"] = id + if ncpdp_id is not None: + params["ncpdp_id"] = ncpdp_id + if organization_name is not None: + params["organization_name__icontains"] = organization_name + if specialty_type is not None: + params["specialty_type__icontains"] = specialty_type + if state is not None: + params["state__iexact"] = state + if zip_code_prefix is not None: + params["zip_code_prefix"] = zip_code_prefix query_string = urllib.parse.urlencode(params) response = self._http_client.get_json(f"/surescripts/pharmacy/?{query_string}")