Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
9 changes: 5 additions & 4 deletions backend/npdfhir/filters/endpoint_filter_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ class EndpointFilterSet(filters.FilterSet):

status = filters.CharFilter(method="filter_status", help_text="Filter by status")

organization = filters.CharFilter(
method="filter_organization", help_text="Filter by organization"
)
# We don't have a concept of endpoint organization at the moment
# organization = filters.CharFilter(
# method="filter_organization", help_text="Filter by organization"
# )

class Meta:
model = EndpointInstance
fields = ["name", "connection_type", "payload_type", "status", "organization"]
fields = ["name", "connection_type", "payload_type", "status"]

def filter_status(self, queryset, name, value):
# needs to be implemented
Expand Down
50 changes: 23 additions & 27 deletions backend/npdfhir/filters/practitioner_role_filter_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,30 +68,30 @@ class PractitionerRoleFilterSet(filters.FilterSet):
endpoint_status = filters.CharFilter(
method="filter_endpoint_status", help_text="Filter providers by endpoint status"
)

endpoint_organization_id = filters.UUIDFilter(
method="filter_endpoint_organization_id",
help_text="Filter by the UUID of the organization associated with endpoints",
)

endpoint_organization_name = filters.CharFilter(
method="filter_endpoint_organization_name",
help_text="Filter by the name of the organization associated with endpoints",
)
# We don't have a concept of endpoint organizations at the moment
# endpoint_organization_id = filters.UUIDFilter(
# method="filter_endpoint_organization_id",
# help_text="Filter by the UUID of the organization associated with endpoints",
# )
#
# endpoint_organization_name = filters.CharFilter(
# method="filter_endpoint_organization_name",
# help_text="Filter by the name of the organization associated with endpoints",
# )

location_address = filters.CharFilter(
method="filter_address", help_text="Filter by the location address"
)

location_city = filters.CharFilter(
location_address_city = filters.CharFilter(
method="filter_address_city", help_text="Filter by the location city"
)

location_state = filters.CharFilter(
location_address_state = filters.CharFilter(
method="filter_address_state", help_text="Filter by the location state"
)

location_zip_code = filters.CharFilter(
location_address_postalcode = filters.CharFilter(
method="filter_address_postalcode", help_text="Filter by the location postal code"
)

Expand All @@ -110,12 +110,10 @@ class Meta:
"specialty",
"endpoint_connection_type",
"endpoint_payload_type",
"endpoint_organization_id",
"endpoint_organization_name",
"location_address",
"location_city",
"location_state",
"location_zip_code",
"location_address_city",
"location_address_state",
"location_address_postalcode",
]

def filter_practitioner_name(self, queryset, name, value):
Expand Down Expand Up @@ -169,7 +167,7 @@ def filter_distance(self, queryset, name, value):
def filter_organization_type(self, queryset, name, value):
return queryset.filter(
Q(
provider_to_organization__organization__clinicalorganization__organizationtotaxonomy__nucc_code__code=value
provider_to_organization__organization__clinicalorganization__organizationtotaxonomy__nucc_code__display_name=value
)
).distinct()

Expand Down Expand Up @@ -199,16 +197,14 @@ def filter_specialty(self, queryset, name, value):
return queryset.filter(Q(specialty_id__iexact=value)).distinct()

def filter_connection_type(self, queryset, name, value):
return queryset.annotate(
search=SearchVector(
"location__locationtoendpointinstance__endpoint_instance__endpoint_connection_type_id"
)
).filter(search=value)
return queryset.filter(
location__locationtoendpointinstance__endpoint_instance__endpoint_connection_type_id=value
)

def filter_endpoint_status(self, queryset, name, value):
return queryset.annotate(
search=SearchVector("location__locationtoendpointinstance__endpoint_instance__status")
).filter(search=value)
return queryset.filter(
location__locationtoendpointinstance__endpoint_instance__status=value
)

def filter_payload_type(self, queryset, name, value):
return queryset.filter(
Expand Down
4 changes: 2 additions & 2 deletions backend/npdfhir/management/commands/seedsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.db import IntegrityError
from faker import Faker

from npdfhir.tests.fixtures.endpoint import create_endpoint
from npdfhir.tests.fixtures.endpoint import create_endpoint_instance
from npdfhir.tests.fixtures.organization import create_organization
from npdfhir.tests.fixtures.practitioner import create_practitioner

Expand Down Expand Up @@ -124,7 +124,7 @@ def handle(self, *args, **options):
self.stdout.write("(organization with other_id 1234567893 already exists)")

if organization:
endpoint = create_endpoint(organization=organization)
endpoint = create_endpoint_instance(organization=organization)
self.stdout.write(f"created Endpoint: {self.to_json(id=endpoint.id)}")

self.generate_sample_organizations(25)
Expand Down
26 changes: 24 additions & 2 deletions backend/npdfhir/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,9 +621,29 @@ def to_representation(self, instance):
practitioner_role.organization = genReference(
"fhir-organization-detail", instance.provider_to_organization.organization_id, request
)
if hasattr(instance, "specialty_id") and instance.specialty_id is not None:
practitioner_role.specialty = (
CodeableConcept(
coding=[
Coding(
system="http://snomed.info/sct",
code=str(instance.specialty_id),
)
]
),
)
practitioner_role.location = [
genReference("fhir-location-detail", instance.location.id, request)
]
if len(instance.location.locationtoendpointinstance_set.all()) > 0:
endpoints = []
for loc_to_endpoint in instance.location.locationtoendpointinstance_set.all():
endpoints.append(
genReference(
"fhir-endpoint-detail", loc_to_endpoint.endpoint_instance_id, request
)
)
practitioner_role.endpoint = endpoints
# These lines rely on the fhir.resources.R4B representation of PractitionerRole to be expanded to match the ndh FHIR definition. This is a TODO with an open ticket.
# if 'other_phone' in representation.keys():
# practitioner_role.telecom = representation['other_phone']
Expand Down Expand Up @@ -651,7 +671,6 @@ class Meta:
]

def to_representation(self, instance):
# request = self.context.get("request")
representation = super().to_representation(instance)

if instance.endpoint_connection_type:
Expand Down Expand Up @@ -690,8 +709,11 @@ def to_representation(self, instance):
name=instance.name,
# TODO extend base fhir spec to ndh spec description=instance.description,
# TODO extend base fhir spec to ndh spec environmentType=environment_type,
# We don't currently have a concept of managing organization for endpoint_instance
# request = self.context.get("request")
# managingOrganization=genReference(
# 'fhir-organization-detail', instance.location.organization_id, request),
# "fhir-organization-detail", representation['location_to_endpoint_instance'][0]['organization_id'], request
# ),
# contact=ContactPoint(contact),
# period=Period(period),
payloadType=representation["payload"],
Expand Down
43 changes: 7 additions & 36 deletions backend/npdfhir/tests/fixtures/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,25 @@

from ...models import (
EhrVendor,
Endpoint,
EndpointConnectionType,
EndpointInstance,
EndpointInstanceToPayload,
EndpointType,
PayloadType,
)
from .organization import create_organization


def _ensure_endpoint_base_types():
"""
Flyway inserts some reference values, but ensure minimal ones exist.
"""
etype, _ = EndpointType.objects.get_or_create(value="rest")
ctype, _ = EndpointConnectionType.objects.get_or_create(
id="hl7-fhir-rest",
defaults={"display": "FHIR REST", "definition": "FHIR REST endpoint"},
)
payload, _ = PayloadType.objects.get_or_create(
id="fhir-json",
defaults={"value": "application/fhir+json", "description": "FHIR JSON"},
)
return etype, ctype, payload


def create_endpoint(
def create_endpoint_instance(
organization=None,
url="https://example.org/fhir",
name="Test Endpoint",
ehr=None,
payload_type=None,
payload_type="any",
endpoint_connection_type="hl7-fhir-rest",
):
"""
Creates EndpointType, EndpointConnectionType, EndpointInstance, Endpoint.
"""
organization = organization or create_organization()

etype, ctype, payload = _ensure_endpoint_base_types()

if not ehr:
new_vendor_id = uuid.uuid4()
ehr_vendor = EhrVendor.objects.create(
Expand All @@ -50,25 +29,17 @@ def create_endpoint(
else:
ehr_vendor = ehr

pt = PayloadType.objects.get(pk=payload_type or "urn:hl7-org:sdwg:ccda-structuredBody:1.1")

instance = EndpointInstance.objects.create(
id=uuid.uuid4(),
ehr_vendor_id=ehr_vendor.id,
address=url,
endpoint_connection_type=ctype,
endpoint_connection_type_id=endpoint_connection_type,
name=name,
environment_type_id="prod",
)

EndpointInstanceToPayload.objects.create(endpoint_instance=instance, payload_type=pt)

ep = Endpoint.objects.create(
id=uuid.uuid4(),
address=url,
endpoint_type=etype,
endpoint_instance=instance,
name=name,
EndpointInstanceToPayload.objects.create(
endpoint_instance=instance, payload_type_id=payload_type
)

return ep
return instance
14 changes: 5 additions & 9 deletions backend/npdfhir/tests/fixtures/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
IndividualToName,
LegalEntity,
Npi,
Nucc,
Organization,
OrganizationToName,
OrganizationToOtherId,
OrganizationToTaxonomy,
)
from .utils import _ensure_name_use


def create_legal_entity(dba_name="Sample Legal Entity"):
Expand All @@ -35,7 +33,7 @@ def create_organization(
other_id_name="testMBI",
other_state_code="NY",
other_issuer="New York State Medicaid",
organization_type=None,
organization_type="193200000X",
aliases=None
):
"""
Expand All @@ -52,7 +50,7 @@ def create_organization(
individual=ind,
first_name=authorized_official_first_name,
last_name=authorized_official_last_name,
name_use=_ensure_name_use(),
name_use_id=1,
)

if id is None:
Expand Down Expand Up @@ -80,11 +78,9 @@ def create_organization(
state_code=other_state_code,
issuer=other_issuer,
)

if organization_type:
code = Nucc.objects.get(pk=organization_type)

OrganizationToTaxonomy.objects.create(npi=clinical_organization, nucc_code=code)
OrganizationToTaxonomy.objects.create(
npi=clinical_organization, nucc_code_id=organization_type
)

OrganizationToName.objects.create(
organization=org,
Expand Down
34 changes: 29 additions & 5 deletions backend/npdfhir/tests/fixtures/practitioner.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Individual,
IndividualToAddress,
IndividualToName,
LocationToEndpointInstance,
Npi,
Nucc,
OtherIdType,
Expand All @@ -19,6 +20,7 @@
ProviderToTaxonomy,
RelationshipType,
)
from .endpoint import create_endpoint_instance
from .location import create_location
from .organization import create_organization
from .utils import _ensure_name_use
Expand Down Expand Up @@ -128,7 +130,14 @@ def create_full_practitionerrole(
location_id=None,
role_code="PRV",
role_display="Provider Role",
nucc_types=None,
practitioner_nucc_types=None,
organization_nucc_type=None,
location_city=None,
location_state=None,
location_zip=None,
endpoint_payload_type="any",
endpoint_connection_type=None,
specialty_id=None,
):
"""
Creates:
Expand All @@ -143,12 +152,13 @@ def create_full_practitionerrole(
last_name=last_name,
gender=gender,
npi_value=npi_value,
practitioner_types=nucc_types,
practitioner_types=practitioner_nucc_types,
)

org = create_organization(name=org_name)
org = create_organization(name=org_name, organization_type=organization_nucc_type)
if location_id is None:
loc = create_location()
loc = create_location(
city=location_city, zipcode=location_zip, state=location_state, organization=org
)
location_id = loc.id

# Ensure relationship + role codes exist
Expand All @@ -163,12 +173,26 @@ def create_full_practitionerrole(
active=True,
)

endpoint_instance = create_endpoint_instance(
organization=org,
url="https://example.org/fhir",
name="Test Endpoint",
ehr=None,
payload_type=endpoint_payload_type,
endpoint_connection_type=endpoint_connection_type,
)

LocationToEndpointInstance.objects.create(
location_id=location_id, endpoint_instance_id=endpoint_instance.id
)

pr = ProviderToLocation.objects.create(
id=uuid.uuid4(),
provider_to_organization=pto_org,
location_id=location_id,
provider_role_code=role_code,
active=True,
specialty_id=specialty_id,
)

return pr
Loading