|
| 1 | +from django.contrib.postgres.search import SearchVector, SearchQuery |
| 2 | +from django.db.models import Q |
| 3 | +from django_filters import rest_framework as filters |
| 4 | + |
| 5 | +from ..utils import parse_identifier_query |
| 6 | + |
| 7 | + |
| 8 | +class OrganizationAffiliationFilterSet(filters.FilterSet): |
| 9 | + org_name = filters.CharFilter(method="filter_name", help_text="Filter by organization name") |
| 10 | + participating_org_name = filters.CharFilter( |
| 11 | + method="filter_participating_name", help_text="Filter by pariticipating organization name" |
| 12 | + ) |
| 13 | + |
| 14 | + participating_organization_identifier = filters.CharFilter( |
| 15 | + method="filter_identifier", |
| 16 | + help_text="Filter by identifier (NPI, EIN, or other). Format: value or system|value", |
| 17 | + ) |
| 18 | + |
| 19 | + participating_organization_type = filters.CharFilter( |
| 20 | + method="filter_organization_type", help_text="Filter by organization type/taxonomy" |
| 21 | + ) |
| 22 | + |
| 23 | + address = filters.CharFilter( |
| 24 | + method="filter_location", help_text="Filter by any part of address" |
| 25 | + ) |
| 26 | + |
| 27 | + address_city = filters.CharFilter(method="filter_address_city", help_text="Filter by city name") |
| 28 | + |
| 29 | + address_state = filters.CharFilter( |
| 30 | + method="filter_address_state", help_text="Filter by state (2-letter abbreviation)" |
| 31 | + ) |
| 32 | + |
| 33 | + address_postalcode = filters.CharFilter( |
| 34 | + method="filter_address_postalcode", help_text="Filter by postal code/zip code" |
| 35 | + ) |
| 36 | + |
| 37 | + def filter_name(self, queryset, name, value): |
| 38 | + query = SearchQuery(f"{value}", search_type="phrase") |
| 39 | + return queryset.annotate(ehr_vendor_search=SearchVector("ehr_vendor_name")).filter( |
| 40 | + ehr_vendor_search=query |
| 41 | + ) |
| 42 | + |
| 43 | + def filter_participating_name(self, queryset, name, value): |
| 44 | + return queryset.filter(organization_name__icontains=value) |
| 45 | + |
| 46 | + def filter_identifier(self, queryset, name, value): |
| 47 | + from uuid import UUID |
| 48 | + |
| 49 | + system, identifier_id = parse_identifier_query(value) |
| 50 | + queries = Q(pk__isnull=True) |
| 51 | + |
| 52 | + if system: # specific identifier search requested |
| 53 | + if system.upper() == "NPI": |
| 54 | + try: |
| 55 | + queries = Q(organization__clinicalorganization__npi__npi=int(identifier_id)) |
| 56 | + except (ValueError, TypeError): |
| 57 | + pass # TODO: implement validationerror to show users that NPI must be an int |
| 58 | + else: # general identifier search requested |
| 59 | + try: |
| 60 | + queries |= Q(organization__clinicalorganization__npi__npi=int(identifier_id)) |
| 61 | + except (ValueError, TypeError): |
| 62 | + pass |
| 63 | + |
| 64 | + try: |
| 65 | + UUID(identifier_id) |
| 66 | + queries |= Q(ein__ein_id=identifier_id) |
| 67 | + except (ValueError, TypeError): |
| 68 | + pass |
| 69 | + |
| 70 | + queries |= Q( |
| 71 | + organization__clinicalorganization__organizationtootherid__other_id=identifier_id |
| 72 | + ) |
| 73 | + |
| 74 | + return queryset.filter(queries).distinct() |
| 75 | + |
| 76 | + def filter_organization_type(self, queryset, name, value): |
| 77 | + query = SearchQuery(value, search_type="phrase") |
| 78 | + |
| 79 | + return ( |
| 80 | + queryset.annotate( |
| 81 | + taxonomy_search=SearchVector( |
| 82 | + "clinicalorganization__organizationtotaxonomy__nucc_code__display_name" |
| 83 | + ) |
| 84 | + ) |
| 85 | + .filter(taxonomy_search=query) |
| 86 | + .distinct() |
| 87 | + ) |
| 88 | + |
| 89 | + def filter_location(self, queryset, name, value): |
| 90 | + return ( |
| 91 | + queryset.annotate( |
| 92 | + location_search=SearchVector( |
| 93 | + "location__name", |
| 94 | + "location__address__address_us__delivery_line_1", |
| 95 | + "location__address__address_us__delivery_line_2", |
| 96 | + "location__address__address_us__city_name", |
| 97 | + "location__address__address_us__state_code__abbreviation", |
| 98 | + "location__address__address_us__zipcode", |
| 99 | + ) |
| 100 | + ) |
| 101 | + .filter(location_search=SearchQuery(value, search_type="websearch")) |
| 102 | + .distinct() |
| 103 | + ) |
| 104 | + |
| 105 | + def filter_address_city(self, queryset, name, value): |
| 106 | + return queryset.annotate( |
| 107 | + search=SearchVector("location__address__address_us__city_name") |
| 108 | + ).filter(search=value) |
| 109 | + |
| 110 | + def filter_address_state(self, queryset, name, value): |
| 111 | + return queryset.annotate( |
| 112 | + search=SearchVector("location__address__address_us__state_code__abbreviation") |
| 113 | + ).filter(search=value) |
| 114 | + |
| 115 | + def filter_address_postalcode(self, queryset, name, value): |
| 116 | + return queryset.filter(location__address__address_us__zipcode=value) |
0 commit comments