Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rcra Site search class and validation #728

Merged
Merged
2 changes: 1 addition & 1 deletion server/apps/core/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .rcrainfo_service import RcrainfoService, get_rcrainfo_client
from .rcrainfo_service import RcraClient, get_rcra_client
from .task_service import TaskService, get_task_status, launch_example_task
16 changes: 8 additions & 8 deletions server/apps/core/services/rcrainfo_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
logger = logging.getLogger(__name__)


class RcrainfoService(RcrainfoClient):
class RcraClient(RcrainfoClient):
"""
RcrainfoService is our IO interface for communicating with the EPA RCRAInfo
RcraClient is our IO interface for communicating with the EPA RCRAInfo
web services.
"""

Expand Down Expand Up @@ -97,22 +97,22 @@ def sign_manifest(self, **sign_data):
def __bool__(self):
"""
This Overrides the RcrainfoClient bool
we use this to test a RcrainfoService instance is not None
we use this to test a RcraClient instance is not None
"""
return True


def get_rcrainfo_client(
def get_rcra_client(
*,
username: Optional[str] = None,
api_id: Optional[str] = None,
api_key: Optional[str] = None,
rcrainfo_env: Optional[Literal["preprod"] | Literal["prod"]] = None,
**kwargs,
) -> RcrainfoService:
"""RcrainfoService Constructor for interacting with RCRAInfo web services"""
) -> RcraClient:
"""RcraClient Constructor for interacting with RCRAInfo web services"""
if api_id is not None and api_key is not None:
return RcrainfoService(
return RcraClient(
api_id=api_id,
api_key=api_key,
rcrainfo_env=rcrainfo_env,
Expand All @@ -122,7 +122,7 @@ def get_rcrainfo_client(
org: Org = Org.objects.get_by_username(username)
if org.is_rcrainfo_integrated:
api_id, api_key = org.rcrainfo_api_id_key
return RcrainfoService(
return RcraClient(
api_id=api_id,
api_key=api_key,
rcrainfo_env=rcrainfo_env,
Expand Down
18 changes: 9 additions & 9 deletions server/apps/core/tests/test_rcrainfo_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@
from responses import matchers
from rest_framework import status

from apps.core.services import RcrainfoService, get_rcrainfo_client
from apps.core.services import RcraClient, get_rcra_client
from apps.handler.models import QuickerSign
from apps.handler.serializers import QuickerSignSerializer


class TestRcrainfoService:
"""Tests the for the RcrainfoService class"""
"""Tests the for the RcraClient class"""

def test_inits_to_correct_environment(self):
rcrainfo = RcrainfoService(rcrainfo_env="preprod")
rcrainfo = RcraClient(rcrainfo_env="preprod")
assert rcrainfo.rcrainfo_env == "preprod"

def test_inits_base_url_by_env(self):
rcrainfo_preprod = RcrainfoService(rcrainfo_env="preprod")
rcrainfo_preprod = RcraClient(rcrainfo_env="preprod")
assert rcrainfo_preprod.base_url == emanifest.RCRAINFO_PREPROD
rcrainfo_prod = RcrainfoService(rcrainfo_env="prod")
rcrainfo_prod = RcraClient(rcrainfo_env="prod")
assert rcrainfo_prod.base_url == emanifest.RCRAINFO_PROD

def test_uses_provided_rcra_profile_credentials(self, rcrainfo_profile_factory):
admin_rcrainfo_profile = rcrainfo_profile_factory()
rcrainfo = RcrainfoService(rcra_profile=admin_rcrainfo_profile, auto_renew=True)
rcrainfo = RcraClient(rcra_profile=admin_rcrainfo_profile, auto_renew=True)
assert rcrainfo.retrieve_key() == admin_rcrainfo_profile.rcra_api_key
assert rcrainfo.retrieve_id() == admin_rcrainfo_profile.rcra_api_id

Expand Down Expand Up @@ -52,7 +52,7 @@ def test_constructor_retrieves_org_api_credentials(
org_access_factory(user=my_user, org=my_org)
profile_factory(user=my_user)
# Act
rcrainfo: RcrainfoService = get_rcrainfo_client(username=my_user.username)
rcrainfo: RcraClient = get_rcra_client(username=my_user.username)
# Assert
assert rcrainfo.has_rcrainfo_credentials

Expand All @@ -63,7 +63,7 @@ def test_constructor_uses_provided_api_credentials(
mock_api_id = "my_mock_id"
mock_api_key = "my_mock_key"
# Act
rcrainfo: RcrainfoService = get_rcrainfo_client(api_id=mock_api_id, api_key=mock_api_key)
rcrainfo: RcraClient = get_rcra_client(api_id=mock_api_id, api_key=mock_api_key)
# Assert
assert rcrainfo.has_rcrainfo_credentials
assert rcrainfo.api_id == mock_api_id
Expand Down Expand Up @@ -94,7 +94,7 @@ def test_maps_keywords(
testuser1 = user_factory()
rcra_profile = rcrainfo_profile_factory()
profile_factory(user=testuser1, rcrainfo_profile=rcra_profile)
rcrainfo = RcrainfoService(auto_renew=False)
rcrainfo = RcraClient(auto_renew=False)
quicker_sign_response_factory(mtn=self.mtn, site_id=self.site_id, sign_date=self.sign_date)
quicker_sign_url = f"{rcrainfo.base_url}v1/emanifest/manifest/quicker-sign"
mock_responses.post(
Expand Down
8 changes: 4 additions & 4 deletions server/apps/handler/tests/test_handler_services.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from apps.core.services import RcrainfoService
from apps.core.services import RcraClient
from apps.rcrasite.models import RcraSite
from apps.rcrasite.services import RcraSiteService

Expand All @@ -17,17 +17,17 @@ def _setup(self, user_factory, rcrainfo_profile_factory, haztrak_json, profile_f
def test_rcrainfo_returns_true_when_instance(self):
"""
the e-Manifest PyPI package RcrainfoClient uses a __bool__ method we need to override
in order for self.rcrainfo = rcrainfo or RcrainfoService(...) to work.
in order for self.rcrainfo = rcrainfo or RcraClient(...) to work.
"""
# Arrange
rcrainfo = RcrainfoService(auto_renew=False)
rcrainfo = RcraClient(auto_renew=False)
# Act and Assert
assert rcrainfo # should return true

def test_pulls_site_details_from_rcrainfo(self, mock_responses):
"""test pulling a rcra_site's information from rcrainfo"""
# Arrange
rcrainfo = RcrainfoService(auto_renew=False)
rcrainfo = RcraClient(auto_renew=False)
handler_service = RcraSiteService(username=self.user.username, rcrainfo=rcrainfo)
rcrainfo_site_details_url = f"{rcrainfo.base_url}v1/site-details/{self.epa_id}"
# mock response from Rcrainfo
Expand Down
8 changes: 4 additions & 4 deletions server/apps/manifest/services/emanifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from emanifest import RcrainfoResponse
from requests import RequestException

from apps.core.services import RcrainfoService, get_rcrainfo_client
from apps.core.services import RcraClient, get_rcra_client
from apps.handler.models import QuickerSign
from apps.handler.serializers import QuickerSignSerializer
from apps.manifest.models import Manifest
Expand Down Expand Up @@ -65,9 +65,9 @@ class PullManifestsResult(TypedDict):
class EManifest:
"""IO interface with the e-Manifest system."""

def __init__(self, *, username: Optional[str], rcrainfo: Optional[RcrainfoService] = None):
def __init__(self, *, username: Optional[str], rcrainfo: Optional[RcraClient] = None):
self.username = username
self.rcrainfo = rcrainfo or get_rcrainfo_client(username=username)
self.rcrainfo = rcrainfo or get_rcra_client(username=username)

@property
def is_available(self) -> bool:
Expand Down Expand Up @@ -185,7 +185,7 @@ def get_updated_mtn(site_id: str, last_sync_date: datetime, rcra_client) -> list

@transaction.atomic
def sync_manifests(
*, site_id: str, last_sync_date: datetime, rcra_client: RcrainfoService
*, site_id: str, last_sync_date: datetime, rcra_client: RcraClient
) -> PullManifestsResult:
"""Pull manifests and update the last sync date for a site"""
updated_mtn = get_updated_mtn(
Expand Down
8 changes: 4 additions & 4 deletions server/apps/manifest/services/emanifest_search.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import UTC, datetime, timedelta, timezone
from typing import Literal, Optional, get_args

from apps.core.services import RcrainfoService
from apps.core.services import RcraClient

EmanifestStatus = Literal[
"Pending",
Expand All @@ -24,8 +24,8 @@


class EmanifestSearch:
def __init__(self, rcra_client: Optional[RcrainfoService] = None):
self._rcra_client = rcra_client or RcrainfoService()
def __init__(self, rcra_client: Optional[RcraClient] = None):
self._rcra_client = rcra_client or RcraClient()
self.state_code: Optional[str] = None
self.site_id: Optional[str] = None
self.status: Optional[EmanifestStatus] = None
Expand All @@ -38,7 +38,7 @@ def __init__(self, rcra_client: Optional[RcrainfoService] = None):
@property
def rcra_client(self):
if not self._rcra_client:
self._rcra_client = RcrainfoService()
self._rcra_client = RcraClient()
return self._rcra_client

@rcra_client.setter
Expand Down
4 changes: 2 additions & 2 deletions server/apps/manifest/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from celery import Task, shared_task, states
from celery.exceptions import Ignore, Reject

from apps.core.services import get_rcrainfo_client
from apps.core.services import get_rcra_client

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -64,7 +64,7 @@ def sync_site_manifests(self, *, site_id: str, username: str):
from apps.site.services import get_user_site, update_emanifest_sync_date

try:
client = get_rcrainfo_client(username=username)
client = get_rcra_client(username=username)
site = get_user_site(username=username, epa_id=site_id)
results = sync_manifests(
site_id=site_id, last_sync_date=site.last_rcrainfo_manifest_sync, rcra_client=client
Expand Down
15 changes: 14 additions & 1 deletion server/apps/manifest/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,20 @@ def create_manifest(
),
)
except IntegrityError:
mtn = None
return Manifest.objects.create(
mtn=fake.mtn(),
status=status or fake.status(),
created_date=datetime.now(UTC),
potential_ship_date=datetime.now(UTC),
generator=generator
or manifest_handler_factory(
rcra_site=rcra_site_factory(site_type=RcraSiteType.GENERATOR)
),
tsdf=tsdf
or manifest_handler_factory(
rcra_site=rcra_site_factory(site_type=RcraSiteType.TSDF)
),
)

return create_manifest

Expand Down
6 changes: 3 additions & 3 deletions server/apps/manifest/tests/test_emanifest_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest_mock
from rest_framework import status

from apps.core.services import RcrainfoService, get_rcrainfo_client
from apps.core.services import RcraClient, get_rcra_client
from apps.manifest.services import EManifest


Expand All @@ -16,7 +16,7 @@ def _setup(self, user_factory, site_factory, haztrak_json):

@pytest.fixture
def manifest_100033134elc_rcra_response(self, haztrak_json, mock_responses):
rcrainfo = get_rcrainfo_client(api_id="my_mock_id", api_key="my_mock_key")
rcrainfo = get_rcra_client(api_id="my_mock_id", api_key="my_mock_key")
manifest_json = haztrak_json.MANIFEST.value
mock_responses.get(
url=f'{rcrainfo.base_url}v1/emanifest/manifest/{manifest_json.get("manifestTrackingNumber")}',
Expand All @@ -29,7 +29,7 @@ def test_pull_manifests(
self, manifest_100033134elc_rcra_response, mocker: pytest_mock.MockerFixture
):
"""Test retrieves a manifest from RCRAInfo"""
rcrainfo = RcrainfoService(auto_renew=False)
rcrainfo = RcraClient(auto_renew=False)
emanifest = EManifest(username=self.user.username, rcrainfo=rcrainfo)
results = emanifest.pull(tracking_numbers=[self.tracking_number])
assert self.tracking_number in results["success"]
8 changes: 4 additions & 4 deletions server/apps/manifest/tests/test_search_emanifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from apps.core.services import RcrainfoService
from apps.core.services import RcraClient
from apps.manifest.services.emanifest_search import EmanifestSearch


Expand All @@ -17,7 +17,7 @@ def test_defaults_to_unauthenticated_rcra_client(self):
def test_execute_sends_a_request_to_rcrainfo(
self, mock_responses, mock_emanifest_auth_response
):
stub_rcra_client = RcrainfoService(rcrainfo_env="preprod", api_key="foo", api_id="foo")
stub_rcra_client = RcraClient(rcrainfo_env="preprod", api_key="foo", api_id="foo")
mock_responses.post(
"https://rcrainfopreprod.epa.gov/rcrainfo/rest/api/v1/emanifest/search"
)
Expand All @@ -26,7 +26,7 @@ def test_execute_sends_a_request_to_rcrainfo(

@pytest.mark.parametrize("mock_emanifest_auth_response", [["foo", "foo"]], indirect=True)
def test_search_builds_json(self, mock_responses, mock_emanifest_auth_response):
stub_rcra_client = RcrainfoService(rcrainfo_env="preprod", api_key="foo", api_id="foo")
stub_rcra_client = RcraClient(rcrainfo_env="preprod", api_key="foo", api_id="foo")
mock_responses.post(
"https://rcrainfopreprod.epa.gov/rcrainfo/rest/api/v1/emanifest/search"
)
Expand Down Expand Up @@ -103,7 +103,7 @@ def test_add_end_date(self):
def test_add_end_date_defaults_to_now(self):
now = datetime.now(UTC)
search = EmanifestSearch().add_end_date()
end_date = datetime.strptime(search.end_date, RcrainfoService.datetime_format)
end_date = datetime.strptime(search.end_date, RcraClient.datetime_format)
assert end_date.day == now.day
assert end_date.month == now.month
assert end_date.year == now.year
Expand Down
6 changes: 3 additions & 3 deletions server/apps/profile/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.db import transaction

from apps.core.models import TrakUser
from apps.core.services import RcrainfoService, get_rcrainfo_client
from apps.core.services import RcraClient, get_rcra_client
from apps.profile.models import Profile, RcrainfoProfile, RcrainfoSiteAccess
from apps.profile.serializers import RcrainfoSitePermissionsSerializer
from apps.rcrasite.models import RcraSite
Expand Down Expand Up @@ -61,11 +61,11 @@ class RcraProfileService:
of a and exposes method corresponding to use cases.
"""

def __init__(self, *, username: str, rcrainfo: Optional[RcrainfoService] = None):
def __init__(self, *, username: str, rcrainfo: Optional[RcraClient] = None):
self.username = username
profile, created = get_or_create_rcra_profile(username=username)
self.profile: RcrainfoProfile = profile
self.rcrainfo = rcrainfo or get_rcrainfo_client(username=username)
self.rcrainfo = rcrainfo or get_rcra_client(username=username)

def update_rcrainfo_profile(self, *, rcrainfo_username: Optional[str] = None) -> None:
"""
Expand Down
3 changes: 2 additions & 1 deletion server/apps/rcrasite/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .rcra_site_services import RcraSiteService
from .rcra_site import RcraSiteService, query_rcra_sites
from .rcra_site_search import RcraSiteSearch
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
from django.db.models import QuerySet
from rest_framework.exceptions import ValidationError

from apps.core.services import RcrainfoService, get_rcrainfo_client
from apps.core.services import RcraClient, get_rcra_client
from apps.rcrasite.models import RcraSite
from apps.rcrasite.serializers import RcraSiteSerializer

from .rcra_site_search import RcraSiteSearch


class HandlerSearchResults(TypedDict):
sites: list[RcraSite]
Expand Down Expand Up @@ -41,15 +43,9 @@ class RcraSiteService:
directly relate to use cases.
"""

def __init__(self, *, username: str, rcrainfo: Optional[RcrainfoService] = None):
def __init__(self, *, username: str, rcrainfo: Optional[RcraClient] = None):
self.username = username
self.rcrainfo = rcrainfo or get_rcrainfo_client(username=self.username)

def __repr__(self):
return (
f"<{self.__class__.__name__}(api_username='{self.username}', "
f"rcrainfo='{self.rcrainfo}')>"
)
self.rcrainfo = rcrainfo or get_rcra_client(username=self.username)

def pull_rcrainfo_site(self, *, site_id: str) -> RcraSite:
"""Retrieve a site/rcra_site from Rcrainfo and return RcraSiteSerializer"""
Expand Down Expand Up @@ -78,7 +74,12 @@ def search_rcrainfo_handlers(self, **search_parameters) -> HandlerSearchResults:
try:
data = cache.get(cache_key)
if not data:
response = self.rcrainfo.search_sites(**search_parameters)
response = (
RcraSiteSearch(rcra_client=self.rcrainfo)
.site_type(search_parameters.get("siteType"))
.epa_id(search_parameters.get("epaSiteId"))
.execute()
)
if response.ok:
data = response.json()
cache.set(cache_key, data, 60 * 60 * 24)
Expand Down
Loading
Loading