Example #1
0
def fhir_conformance(request, via_oauth=False, v2=False, *args):
    """ Pull and filter fhir Conformance statement

    BaseStu3 = "CapabilityStatement"

    :param request:
    :param via_oauth:
    :param args:
    :param kwargs:
    :return:
    """
    crosswalk = None
    resource_router = get_resourcerouter()
    parsed_url = urlparse(resource_router.fhir_url)
    call_to = None
    if parsed_url.path is not None:
        call_to = '{}://{}/{}/fhir/metadata'.format(parsed_url.scheme,
                                                    parsed_url.netloc,
                                                    'v2' if v2 else 'v1')
    else:
        # url with no path
        call_to = '{}/{}/fhir/metadata'.format(resource_router.fhir_url,
                                               'v2' if v2 else 'v1')

    pass_params = {'_format': 'json'}

    encoded_params = urlencode(pass_params)
    pass_params = prepend_q(encoded_params)

    r = request_call(request, call_to + pass_params, crosswalk)

    text_out = ''

    if r.status_code >= 300:
        logger.debug("We have an error code to deal with: %s" % r.status_code)
        return HttpResponse(json.dumps(r._content),
                            status=r.status_code,
                            content_type='application/json')

    text_in = get_response_text(fhir_response=r)

    text_out = json.loads(text_in, object_pairs_hook=OrderedDict)

    od = conformance_filter(text_out)

    # Append Security to ConformanceStatement
    security_endpoint = build_oauth_resource(request, v2, format_type="json")
    od['rest'][0]['security'] = security_endpoint
    # Fix format values
    od['format'] = ['application/json', 'application/fhir+json']

    return JsonResponse(od)
def fhir_conformance(request, via_oauth=False, *args, **kwargs):
    """ Pull and filter fhir Conformance statement

    BaseStu3 = "CapabilityStatement"

    :param request:
    :param via_oauth:
    :param args:
    :param kwargs:
    :return:
    """
    crosswalk = None
    resource_router = get_resourcerouter()
    call_to = FhirServerUrl()

    if call_to.endswith('/'):
        call_to += 'metadata'
    else:
        call_to += '/metadata'

    pass_params = {'_format': 'json'}

    encoded_params = urlencode(pass_params)
    pass_params = prepend_q(encoded_params)

    r = request_call(request, call_to + pass_params, crosswalk)

    text_out = ''
    host_path = get_host_url(request, '?')

    if r.status_code >= 300:
        logger.debug("We have an error code to deal with: %s" % r.status_code)
        return HttpResponse(json.dumps(r._content),
                            status=r.status_code,
                            content_type='application/json')

    rewrite_url_list = build_rewrite_list(crosswalk)
    text_in = get_response_text(fhir_response=r)

    text_out = post_process_request(request, host_path, text_in,
                                    rewrite_url_list)

    od = conformance_filter(text_out, resource_router)

    # Append Security to ConformanceStatement
    security_endpoint = build_oauth_resource(request, format_type="json")
    od['rest'][0]['security'] = security_endpoint
    # Fix format values
    od['format'] = ['application/json', 'application/fhir+json']

    return JsonResponse(od)
    def test_fetch(self, mock_requests):

        request = self.factory.get('http://someurl.com/test.text')
        mock_requests.get.return_value.status_code = 200
        mock_requests.get.return_value.text = CONFORMANCE
        mock_requests.get.return_value.json = pretty_json({"field": "My text "
                                                                    "is here"
                                                                    "!!!!"})

        resp = request_call(request,
                            "http://someurl.com/test.text")

        # print("\nResp.text:\n%s" % resp.text)
        # print("\nResp.json:\n%s" % resp.json)

        self.assertEqual(resp.text[:100],
                         CONFORMANCE[:100])
    def test_fetch(self, mock_requests):

        request = self.factory.get('http://someurl.com/test.text')
        mock_requests.get.return_value.status_code = 200
        mock_requests.get.return_value.text = CONFORMANCE
        mock_requests.get.return_value.json = pretty_json({"field": "My text "
                                                                    "is here"
                                                                    "!!!!"})

        resp = request_call(request,
                            "http://someurl.com/test.text",
                            cx=None)

        # print("\nResp.text:\n%s" % resp.text)
        # print("\nResp.json:\n%s" % resp.json)

        self.assertEqual(resp.text[:100],
                         CONFORMANCE[:100])
Example #5
0
    def test_fetch(self, mock_requests):

        # rr_id = self.resrtr.id
        # print("\nResRtr-testfetch:%s=%s\n" % (rr_id, self.resrtr))

        # rr = get_resourcerouter()
        # print("\nRR-testfetch:%s\n" % rr)

        request = self.factory.get('http://someurl.com/test.text')
        mock_requests.get.return_value.status_code = 200
        mock_requests.get.return_value.text = CONFORMANCE
        mock_requests.get.return_value.json = pretty_json(
            {"field": "My text "
             "is here"
             "!!!!"})

        resp = request_call(request, "http://someurl.com/test.text", cx=None)

        # print("\nResp.text:\n%s" % resp.text)
        # print("\nResp.json:\n%s" % resp.json)

        self.assertEqual(resp.text[:100], CONFORMANCE[:100])
Example #6
0
def rebuild_fhir_search(request):
    """ Rebuild the Search String

    We will start to use a session variable

    We received:
    http://localhost:8000/cmsblue/fhir/v1
    ?_getpages=61c6e2d1-2b7c-49c3-a083-3d5b3874d4ff&_getpagesoffset=10
    &_count=10&_format=json&_pretty=true&_bundletype=searchset

    Session Variables will be storing:
    - FHIR Target URL/Resource
    - _getpages value
    - expires datetime

    Construct FHIR_Target_URL + search parameters

    """

    # now = str(datetime.now())
    ikey = ''
    if '_getpages' in request.GET:
        ikey = request.GET['_getpages']
        sn_vr = read_session(request, ikey, skey=SESSION_KEY)
        # logger.debug("Session info:%s" % sn_vr)

        if sn_vr == {}:
            # Nothing returned from Session Variables
            # Key could be expired or not matched
            return authenticated_home(request)

        url_call = sn_vr['fhir_to']
        url_call += '/?' + request.META['QUERY_STRING']

        rewrite_url_list = sn_vr['rwrt_list']
        resource_type = sn_vr['res_type']
        interaction_type = sn_vr['intn_type']
        key = sn_vr['key']
        vid = sn_vr['vid']

        cx = get_crosswalk(request.user)

        # logger.debug("Calling:%s" % url_call)
        r = request_call(request, url_call, cx,
                         reverse_lazy('authenticated_home'))

        host_path = get_host_url(request, '?')

        # get 'xml' 'json' or ''
        fmt = get_search_param_format(request.META['QUERY_STRING'])

        text_out = post_process_request(request, fmt, host_path, r,
                                        rewrite_url_list)
        od = build_output_dict(request, OrderedDict(), resource_type, key, vid,
                               interaction_type, fmt, text_out)

        if fmt == 'xml':
            # logger.debug('We got xml back in od')
            return HttpResponse(r.text, content_type='application/%s' % fmt)
            # return HttpResponse( tostring(dict_to_xml('content', od)),
            #                      content_type='application/%s' % fmt)
        elif fmt == 'json':
            # logger.debug('We got json back in od')
            return HttpResponse(pretty_json(od),
                                content_type='application/%s' % fmt)

        # logger.debug('We got a different format:%s' % fmt)
        return render(
            request,
            'bluebutton/default.html',
            {
                'content': pretty_json(od),
                'output': od
            },
        )

    return authenticated_home(request)
Example #7
0
def fhir_conformance(request, *args, **kwargs):
    """ Pull and filter fhir Conformance statement

    BaseDstu2 = "Conformance"
    BaseStu3 = "CapabilityStatement"

    metadata call

    """
    if not request.user.is_authenticated():
        return authenticated_home(request)

    try:
        cx = Crosswalk.objects.get(user=request.user)
    except Crosswalk.DoesNotExist:
        cx = None
        # logger.debug('Crosswalk for %s does not exist' % request.user)

    if cx:
        call_to = cx.fhir_source.fhir_url
    else:
        call_to = FhirServerUrl()

    resource_type = conformance_or_capability(call_to)

    if call_to.endswith('/'):
        call_to += 'metadata'
    else:
        call_to += '/metadata'

    pass_params = strip_oauth(request.GET)
    # pass_params should be an OrderedDict after strip_auth
    # logger.debug("result from strip_oauth:%s" % pass_params)

    # Let's store the inbound requested format
    # We need to simplify the format call to the backend
    # so that we get data we can manipulate
    requested_format = request_format(pass_params)

    # now we simplify the format/_format request for the back-end
    pass_params = strip_format_for_back_end(pass_params)
    back_end_format = pass_params['_format']

    encoded_params = urlencode(pass_params)
    #
    # Add ? to front of parameters if needed
    pass_params = prepend_q(encoded_params)

    # logger.debug("Calling:%s" % call_to + pass_params)

    ####################################################
    ####################################################

    r = request_call(request, call_to + pass_params, cx,
                     reverse_lazy('authenticated_home'))

    ####################################################
    ####################################################

    text_out = ''
    host_path = get_host_url(request, '?')

    # get 'xml' 'json' or ''
    # fmt = get_search_param_format(request.META['QUERY_STRING'])
    # force to json

    # logger.debug("Format:%s" % back_end_format)

    rewrite_url_list = settings.FHIR_SERVER_CONF['REWRITE_FROM']
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    text_out = post_process_request(request, back_end_format, host_path,
                                    r.text, rewrite_url_list)

    query_string = build_querystring(request.GET.copy())
    # logger.debug("Query:%s" % query_string)

    if 'xml' in requested_format:
        # logger.debug('We got xml back in od')

        # logger.debug("is xml filtered?%s" % requested_format)
        xml_dom = xml_to_dom(text_out)
        text_out = dom_conformance_filter(xml_dom)
        # logger.debug("Text from XML function:\n%s\n=========" % text_out)
        if 'html' not in requested_format:
            return HttpResponse(text_out,
                                content_type='application'
                                '/%s' % requested_format)
        else:
            # logger.debug("Sending text_out for display: %s" % text_out[0:100])
            return render(
                request, 'bluebutton/default_xml.html', {
                    'output': text_out,
                    'content': {
                        'parameters': query_string,
                        'resource_type': resource_type,
                        'request_method': "GET",
                        'interaction_type': "metadata",
                        'source': cx.fhir_source.name
                    }
                })

            # return HttpResponse( tostring(dict_to_xml('content', od)),
        #                      content_type='application/%s' % fmt)
    elif back_end_format == 'json':
        # logger.debug('We got json back in od')
        od = conformance_filter(text_out, back_end_format)
        text_out = pretty_json(od)
        if 'html' not in requested_format:
            return HttpResponse(text_out,
                                content_type='application/'
                                '%s' % requested_format)
    else:
        # let's make sure we have json to deliver:
        od = conformance_filter(text_out, back_end_format)
        text_out = pretty_json(od)

    # logger.debug('We got a different format:%s' % back_end_format)

    return render(
        request, 'bluebutton/default.html', {
            'output': text_out,
            'content': {
                'parameters': query_string,
                'resource_type': resource_type,
                'request_method': "GET",
                'interaction_type': "metadata",
                'source': cx.fhir_source.name
            }
        })
Example #8
0
def get_fhir_claim(request, claim_number):
    """ Search for Claim Number in FHIR Backend

    Sample Search Specification:
     http://bluebuttonhapi-test.hhsdevcloud.us/baseDstu2/
     ExplanationOfBenefit
     ?identifier=CCW_PTA_FACT.CLM_ID|542612281109054

    Nothing found result:
     {"resourceType":"Bundle",
      "id":"62fe7fe3-9dca-4114-b753-6d7e874c34c5",
      "meta":{"lastUpdated":"2016-07-07T13:43:55.066+00:00"},
      "type":"searchset",
      "total":0,
      "link":[{"relation":"self",
               "url":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/
               ExplanationOfBenefit
               ?identifier=CCW_PTA_FACT.CLM_ID%7C542612281109055"}]}

    Sample EOB Records
    {
            "fullUrl":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/ExplanationOfBenefit/10",
            "resource":{
                "resourceType":"ExplanationOfBenefit",
                "id":"10",
                "extension":[
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#claimType",
                        "valueCoding":{
                            "system":"http://bluebutton.cms.hhs.gov/coding#claimType",
                            "code":"40",
                            "display":"Outpatient claim"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#attendingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/12"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#operatingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/13"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#otherPhysician",
                        "valueReference":{
                            "reference":"Practitioner/14"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#admittingDiagnosis",
                        "valueCoding":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis"
                        }
                    }
                ],
                "meta":{
                    "versionId":"1",
                    "lastUpdated":"2016-03-28T03:14:40.898+00:00"
                },
                "identifier":[
                    {
                        "system":"CCW_PTA_FACT.CLM_ID",
                        "value":"542612281109054"
                    }
                ],
                "billablePeriod":{
                    "start":"2008-11-15T00:00:00+00:00",
                    "end":"2008-11-15T00:00:00+00:00"
                },
                "provider":{
                    "reference":"Practitioner/11"
                },
                "diagnosis":[
                    {
                        "sequence":0,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"7137"
                        }
                    },
                    {
                        "sequence":1,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"72190"
                        }
                    }
                ],
                "patient":{
                    "reference":"Patient/1"
                },
                "coverage":{
                    "coverage":{
                        "reference":"Coverage/4"
                    }
                },
                "item":[
                    {
                        "type":{
                            "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                            "code":"CSPINV"
                        },
                        "adjudication":[
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"Line NCH Payment Amount"
                                },
                                "amount":{
                                    "value":10.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Primary Payer Claim Paid Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Blood Deductible Liability Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Deductible Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Coinsurance Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            }
                        ],
                        "detail":[
                            {
                                "extension":[
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":0
                                    },
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":1
                                    }
                                ],
                                "sequence":1,
                                "type":{
                                    "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                                    "code":"CSPINV"
                                },
                                "service":{
                                    "system":"HCPCS",
                                    "code":"73564"
                                }
                            }
                        ]
                    }
                ]
            },
            "search":{
                "mode":"match"
            }
        },
        {
            "fullUrl":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/ExplanationOfBenefit/15",
            "resource":{
                "resourceType":"ExplanationOfBenefit",
                "id":"15",
                "extension":[
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#claimType",
                        "valueCoding":{
                            "system":"http://bluebutton.cms.hhs.gov/coding#claimType",
                            "code":"40",
                            "display":"Outpatient claim"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#attendingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/17"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#operatingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/18"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#otherPhysician",
                        "valueReference":{
                            "reference":"Practitioner/19"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#admittingDiagnosis",
                        "valueCoding":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis"
                        }
                    }
                ],
                "meta":{
                    "versionId":"1",
                    "lastUpdated":"2016-03-28T03:14:40.898+00:00"
                },
                "identifier":[
                    {
                        "system":"CCW_PTA_FACT.CLM_ID",
                        "value":"542062281310767"
                    }
                ],
                "billablePeriod":{
                    "start":"2009-02-02T00:00:00+00:00",
                    "end":"2009-02-02T00:00:00+00:00"
                },
                "provider":{
                    "reference":"Practitioner/16"
                },
                "diagnosis":[
                    {
                        "sequence":0,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"49321"
                        }
                    }
                ],
                "patient":{
                    "reference":"Patient/1"
                },
                "coverage":{
                    "coverage":{
                        "reference":"Coverage/4"
                    }
                },
                "item":[
                    {
                        "type":{
                            "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                            "code":"CSPINV"
                        },
                        "adjudication":[
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"Line NCH Payment Amount"
                                },
                                "amount":{
                                    "value":900.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Primary Payer Claim Paid Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Blood Deductible Liability Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Deductible Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Coinsurance Amount"
                                },
                                "amount":{
                                    "value":20.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            }
                        ],
                        "detail":[
                            {
                                "extension":[
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":0
                                    }
                                ],
                                "sequence":1,
                                "type":{
                                    "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                                    "code":"CSPINV"
                                },
                                "service":{
                                    "system":"HCPCS",
                                    "code":"99214"
                                }
                            }
                        ]
                    }
                ]
            },
            "search":{
                "mode":"match"
            }
        },


    """

    # We need the crosswalk to check client auth for the server
    cx = get_crosswalk(request.user)
    # Get the FHIR Server URL
    # Construct the Search for ExplanationOfBenefit / PatientClaimSummary
    search_base = FhirServerUrl() + "ExplanationOfBenefit"

    # FHIR_URL + PATH + RELEASE + ExplanationOfBenefit?
    # claimIdentifier=claim_number
    # &_format=json

    # http://bluebuttonhapi-test.hhsdevcloud.us/baseDstu2/
    # ExplanationOfBenefit?identifier=CCW_PTA_FACT.CLM_ID|542882280967266

    search_base += "?_format=json&identifier="  # CCW_PTA_FACT.CLM_ID|"

    fhir_claim = {}
    fhir_claim['claimNumber'] = claim_number
    fhir_claim['found'] = False

    search_base += claim_number

    # logger.debug('Calling request_call with %s' % search_base)
    r = request_call(request, search_base, cx)
    # logger.debug("returned with %s" % r.text)
    bundle = json.loads(r.text, object_pairs_hook=OrderedDict)
    resource = {}
    if bundle['total'] > 0:
        resource = bundle['entry'][0]['resource']
        # If claim is found:
        fhir_claim['found'] = True
        fhir_claim['claimIdentifier'] = resource['identifier'][0]['value']
        fhir_claim['identifier'] = resource['id']
        fhir_claim['provider'] = resource['provider']['reference']
        fhir_claim['patient'] = resource['patient']['reference']
        if 'billablePeriod' in resource:
            if isinstance(resource['billablePeriod'], dict):
                fhir_claim['timingPeriod'] = dict(resource['billablePeriod'])
            else:
                fhir_claim['timingPeriod'] = resource['billablePeriod']
    # fhir_claim['claimIdentifier'] = ExplanationOfBenefit.claimIdentifier
    # fhir_claim['identifier'] = ExplanationOfBenefit.identifier
    # fhir_claim['provider'] = ExplanationOfBenefit.providerIdentifier
    # fhir_claim['patient'] = ExplanationOfBenefit.patientIdentifier
    # fhir_claim['timingPeriod'] = ExplanationOfBenefit.timingPeriod
    print("\nSearch for claim:", claim_number)
    print("\Resources:", resource)
    print("\nFound:", fhir_claim)
    # logger.debug('fhir_claim: %s' % fhir_claim)

    return fhir_claim
Example #9
0
def generic_read(request,
                 interaction_type,
                 resource_type,
                 id=None,
                 vid=None,
                 *args,
                 **kwargs):
    """
    Read from remote FHIR Server

    :param request:
    :param interaction_type:
    :param resource_type:
    :param id:
    :param vid:
    :param args:
    :param kwargs:
    :return:

    # Example client use in curl:
    # curl  -X GET http://127.0.0.1:8000/fhir/Practitioner/1234

    Process flow:

    Is it a valid request?

    Get the target server info

    Get the request modifiers

    Construct the call

    Make the call

    Check result for errors

    Deliver the formatted result


    """
    # DONE: Fix to allow url_id in url for non-key resources.
    # eg. Patient is key resource so replace url if override_url_id is True
    # if override_url_id is not set allow url_id to be applied and check
    # if search_override is True.
    # interaction_type = 'read' or '_history' or 'vread' or 'search'
    logger.debug('\n========================\n'
                 'INTERACTION_TYPE: %s' % interaction_type)

    # Get the users crosswalk
    cx = get_crosswalk(request.user)

    # cx will be the crosswalk record or None
    rr = get_resourcerouter(cx)

    # Check if this interaction type and resource type combo is allowed.
    deny = check_access_interaction_and_resource_type(resource_type,
                                                      interaction_type, rr)
    if deny:
        # if not allowed, return a 4xx error.
        return deny

    srtc = check_rt_controls(resource_type, rr)
    # We get back a Supported ResourceType Control record or None
    # with earlier if deny step we should have a valid srtc.

    if srtc.secure_access and request.user.is_anonymous():
        return kickout_403('Error 403: %s Resource access is controlled.'
                           ' Login is required:'
                           '%s' % (resource_type, request.user.is_anonymous()))
    # logger.debug('srtc: %s' % srtc)

    if cx is None:
        logger.debug('Crosswalk for %s does not exist' % request.user)

    if (cx is None and srtc is not None):
        # There is a srtc record so we need to check override_search
        if srtc.override_search:
            # If user is not in Crosswalk and srtc has search_override = True
            # We need to prevent search to avoid data leakage.
            return kickout_403('Error 403: %s Resource is access controlled.'
                               ' No records are linked to user:'******'%s' % (resource_type, request.user))

    # Need to check if user is logged in.
    # request.user.is_anonymous()
    #
    # if request.user.is_anonymous():

    # Request.user = user
    # interaction_type = read | _history | vread
    # resource_type = 'Patient | Practitioner | ExplanationOfBenefit ...'
    # id = fhir_id (potentially masked)
    # vid = Version Id

    # Check the resource_type to see if it has a url
    # Check the resource_type to see if masking is required
    # Get the FHIR_Server (from crosswalk via request.user)
    # if masked get the fhir_id from crosswalk
    # if search_override strip search items (search_block)
    # if search_override add search keys

    fhir_url = ''
    # change source of default_url to ResourceRouter

    default_path = get_default_path(srtc.resource_name, cx=cx)
    # get the default path for resource with ending "/"
    # You need to add resource_type + "/" for full url

    if srtc:
        # logger.debug('SRTC:%s' % srtc)

        fhir_url = default_path + resource_type + '/'

        if srtc.override_url_id:
            fhir_url += cx.fhir_id + "/"

        # logger.debug('fhir_url:%s' % fhir_url)
    else:
        logger.debug('CX:%s' % cx)
        if cx:
            fhir_url = cx.get_fhir_resource_url(resource_type)
        else:
            # logger.debug('FHIRServer:%s' % FhirServerUrl())
            fhir_url = FhirServerUrl() + resource_type + '/'

    # #### SEARCH

    if interaction_type == 'search':
        key = None
    else:
        key = masked_id(resource_type, cx, srtc, id, slash=False)

        print("\nMasked_id-key:%s from r_id:%s "
              "and cx-fhir_id:%s\n" % (key, id, cx.fhir_id))

        # add key to fhir_url unless already in place.
        fhir_url = add_key_to_fhir_url(fhir_url, key)

    logger.debug('FHIR URL with key:%s' % fhir_url)

    ###########################

    # Now we get to process the API Call.

    # Internal handling format is json
    # Remove the oauth elements from the GET
    pass_params = strip_oauth(request.GET)

    # Let's store the inbound requested format
    # We need to simplify the format call to the backend
    # so that we get data we can manipulate
    requested_format = request_format(pass_params)

    # now we simplify the format/_format request for the back-end
    pass_params = strip_format_for_back_end(pass_params)
    if "_format" in pass_params:
        back_end_format = pass_params['_format']
    else:
        back_end_format = "json"

    # #### SEARCH

    if interaction_type == 'search':
        if cx is not None:
            # logger.debug("cx.fhir_id=%s" % cx.fhir_id)
            if cx.fhir_id.__contains__('/'):
                id = cx.fhir_id.split('/')[1]
            else:
                id = cx.fhir_id
            # logger.debug("Patient Id:%s" % r_id)

    if resource_type.lower() == "patient":
        key = cx.fhir_id
    else:
        key = id

    pass_params = build_params(pass_params, srtc, key, patient_id=cx.fhir_id)

    # Add the call type ( READ = nothing, VREAD, _HISTORY)
    # Before we add an identifier key
    pass_to = fhir_call_type(interaction_type, fhir_url, vid)

    logger.debug('\nHere is the URL to send, %s now add '
                 'GET parameters %s' % (pass_to, pass_params))

    if pass_params is not '':
        pass_to += pass_params

    logger.debug("\nMaking request:%s" % pass_to)

    ###############################################
    ###############################################
    # Now make the call to the backend API

    if interaction_type == "search":
        r = request_call(request,
                         pass_to,
                         cx,
                         reverse_lazy('home'),
                         timeout=settings.REQUEST_CALL_TIMEOUT)
    else:
        r = request_call(request, pass_to, cx, reverse_lazy('home'))

    # BACK FROM THE CALL TO BACKEND
    ###############################################
    ###############################################

    # logger.debug("r returned: %s" % r)

    # Check for Error here
    try:
        error_check = r.text
        logger.debug("We got r.text back:%s" % r.text[:200] + "...")
    except:
        error_check = "HttpResponse status_code=502"
        logger.debug("Something went wrong with call to %s" % pass_to)
    logger.debug("Checking for errors:%s" % error_check[:200] + "...")
    if 'status_code' in error_check:
        # logger.debug("We have a status code to check: %s" % r)
        if r.status_code in ERROR_CODE_LIST:
            logger.debug("\nError Status Code:%s" % r.status_code)
            return error_status(r, r.status_code)
    elif 'status_code=302' in error_check:
        return error_status(r, 302)
    elif 'status_code=502' in error_check:
        return error_status(r, 502)
    else:
        logger.debug("Status Code:%s " "in:%s" % (r.status_code, r))

    # We should have a 200 - good record to deal with
    # We can occasionaly get a 200 with a Connection Error. eg. Timeout
    try:
        if "ConnectionError" in r.text:
            logger.debug("Error:%s" % r.text)
            return error_status(r, 502)
    except:
        pass

    text_out = ''
    # if 'text' in r:
    #     logger.debug('r:%s' % r.text)
    #     logger_debug.debug('r:%s' % r.text)
    # else:
    #     logger.debug("r not returning text:%s" % r)
    #     logger_debug.debug("r not returning text:%s" % r)
    #     logger.debug("r.json: %s" % json.dumps(r.json))

    # logger.debug('Rewrite List:%s' % rewrite_url_list)

    host_path = get_host_url(request, resource_type)[:-1]
    # logger.debug('host path:%s' % host_path)

    # Add default FHIR Server URL to re-write
    rewrite_url_list = build_rewrite_list(cx)
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    # ct_detail = get_content_type(r)
    # logger.debug('Content-Type:%s \n work with %s' % (ct_detail,
    #                                                   back_end_format))

    try:
        text_in = r.text
    except:
        text_in = ""

    text_out = post_process_request(request, back_end_format, host_path,
                                    text_in, rewrite_url_list)

    od = build_output_dict(request, OrderedDict(), resource_type, key, vid,
                           interaction_type, requested_format, text_out)

    # write session variables if _getpages was found
    ikey = ''
    try:
        ikey = find_ikey(r.text)
    except:
        ikey = ''

    if ikey is not '':

        save_url = get_target_url(fhir_url, resource_type)
        # print("Store fhir_url:%s but only: %s" % (fhir_url,save_url))
        content = {
            'fhir_to': save_url,
            'rwrt_list': rewrite_url_list,
            'res_type': resource_type,
            'intn_type': interaction_type,
            'key': key,
            'vid': vid,
            'resource_router': rr.id
        }
        sesn_var = write_session(request, ikey, content, skey=SESSION_KEY)
        if sesn_var:
            logger.debug("Problem writing session variables."
                         " Returned %s" % sesn_var)
    if requested_format == 'xml':
        # logger.debug('We got xml back in od')
        return HttpResponse(r.text,
                            content_type='application/%s' % requested_format)
        # return HttpResponse(tostring(dict_to_xml('content', od)),
        #                     content_type='application/%s' % requested_format)

    elif requested_format == 'json':
        # logger.debug('We got json back in od')
        return HttpResponse(pretty_json(od['bundle']),
                            content_type='application/%s' % requested_format)

    query_string = build_querystring(request.GET.copy())
    if "xml" in requested_format:
        # logger.debug("Sending text_out for display: %s" % text_out[0:100])
        div_text = get_div_from_xml(text_out)
        # print("DIV TEXT returned:[%s]%s" % (type(div_text), div_text))
        return render(
            request, 'bluebutton/default_xml.html', {
                'output': text_out,
                'content': {
                    'parameters': query_string,
                    'resource_type': resource_type,
                    'request_method': "GET",
                    'interaction_type': interaction_type,
                    'div_texts': [
                        div_text,
                    ],
                    'source': cx.fhir_source.name
                }
            })

    else:
        text_out = pretty_json(od['bundle'])
        div_text = get_div_from_json(od['bundle'])

    # logger.debug('We got a different format:%s' % requested_format)
    return render(
        request, 'bluebutton/default.html', {
            'output': text_out,
            'content': {
                'parameters': query_string,
                'resource_type': resource_type,
                'request_method': "GET",
                'interaction_type': interaction_type,
                'div_texts': div_text,
                'source': cx.fhir_source.name
            }
        })
Example #10
0
def generic_read(request,
                 interaction_type,
                 resource_type,
                 id=None,
                 via_oauth=False,
                 vid=None,
                 *args,
                 **kwargs):
    """
    Read from remote FHIR Server

    :param request:
    :param interaction_type:
    :param resource_type:
    :param id:
    :param vid:
    :param args:
    :param kwargs:
    :return:

    # Example client use in curl:
    # curl  -X GET http://127.0.0.1:8000/fhir/Practitioner/1234

    Process flow:

    Is it a valid request?

    Get the target server info

    Get the request modifiers
    - change url_id
    - remove unwanted search parameters
    - add search parameters

    Construct the call

    Make the call

    Check result for errors

    Deliver the formatted result


    """
    # DONE: Fix to allow url_id in url for non-key resources.
    # eg. Patient is key resource so replace url if override_url_id is True
    # if override_url_id is not set allow id to be applied and check
    # if search_override is True.
    # interaction_type = 'read' or '_history' or 'vread' or 'search'
    logger.debug('\n========================\n'
                 'INTERACTION_TYPE: %s - Via Oauth:%s' %
                 (interaction_type, via_oauth))

    # if via_oauth we need to call crosswalk with
    if via_oauth:
        # get crosswalk from the resource_owner
        cx = get_crosswalk(request.resource_owner)
    else:
        # Get the users crosswalk
        cx = get_crosswalk(request.user)

    # cx will be the crosswalk record or None
    rr = get_resourcerouter(cx)

    # Check if this interaction type and resource type combo is allowed.
    deny = check_access_interaction_and_resource_type(resource_type,
                                                      interaction_type, rr)
    if deny:
        # if not allowed, return a 4xx error.
        return deny

    srtc = check_rt_controls(resource_type, rr)
    # We get back a Supported ResourceType Control record or None
    # with earlier if deny step we should have a valid srtc.

    if not via_oauth:
        # we don't need to check if user is anonymous if coming via_oauth
        if srtc.secure_access and request.user.is_anonymous():
            return kickout_403('Error 403: %s Resource access is controlled.'
                               ' Login is required:'
                               '%s' %
                               (resource_type, request.user.is_anonymous()))
        # logger.debug('srtc: %s' % srtc)

    if cx is None:
        logger.debug('Crosswalk for %s does not exist' % request.user)

    if (cx is None and srtc is not None):
        # There is a srtc record so we need to check override_search
        if srtc.override_search:
            # If user is not in Crosswalk and srtc has search_override = True
            # We need to prevent search to avoid data leakage.
            return kickout_403('Error 403: %s Resource is access controlled.'
                               ' No records are linked to user:'******'%s' % (resource_type, request.user))

    # TODO: Compare id to cx.fhir_id and return 403 if they don't match for
    # Resource Type - Patient
    fhir_url = ''
    # change source of default_url to ResourceRouter

    default_path = get_default_path(srtc.resource_name, cx=cx)
    # get the default path for resource with ending "/"
    # You need to add resource_type + "/" for full url

    if srtc:
        # logger.debug('SRTC:%s' % srtc)

        fhir_url = default_path + resource_type + '/'

        if srtc.override_url_id:
            fhir_url += get_fhir_id(cx) + "/"

        # logger.debug('fhir_url:%s' % fhir_url)
        else:
            fhir_url += id + "/"

    else:
        logger.debug('CX:%s' % cx)
        if cx:
            fhir_url = cx.get_fhir_resource_url(resource_type)
        else:
            # logger.debug('FHIRServer:%s' % FhirServerUrl())
            fhir_url = FhirServerUrl() + resource_type + '/'

    # #### SEARCH

    if interaction_type == 'search':
        key = None
    else:
        key = masked_id(resource_type, cx, srtc, id, slash=False)

        # print("\nMasked_id-key:%s from r_id:%s "
        #       "and cx-fhir_id:%s\n" % (key, id, cx.fhir_id))

        # add key to fhir_url unless already in place.
        fhir_url = add_key_to_fhir_url(fhir_url, key)

    logger.debug('FHIR URL with key:%s' % fhir_url)

    ###########################

    # Now we get to process the API Call.

    # Internal handling format is json
    # Remove the oauth elements from the GET

    pass_params = request.GET

    # Let's store the inbound requested format
    # We need to simplify the format call to the backend
    # so that we get data we can manipulate

    # if format is not defined and we come in via_oauth
    # then default to json for format
    requested_format = request_format(pass_params)
    if requested_format == "html" and via_oauth:
        requested_format = "json"

    # now we simplify the format/_format request for the back-end
    pass_params = strip_format_for_back_end(pass_params)
    if "_format" in pass_params:
        back_end_format = pass_params['_format']
    else:
        back_end_format = "json"

    # #### SEARCH

    if interaction_type == 'search':
        if cx is not None:
            # logger.debug("cx.fhir_id=%s" % cx.fhir_id)
            if cx.fhir_id.__contains__('/'):
                id = get_fhir_id(cx).split('/')[1]
            else:
                id = get_fhir_id(cx)
            # logger.debug("Patient Id:%s" % r_id)

    if resource_type.lower() == "patient":
        key = get_fhir_id(cx)
    else:
        key = id

    pass_params = build_params(pass_params,
                               srtc,
                               key,
                               patient_id=get_fhir_id(cx))

    # Add the call type ( READ = nothing, VREAD, _HISTORY)
    # Before we add an identifier key
    pass_to = fhir_call_type(interaction_type, fhir_url, vid)

    logger.debug('\nHere is the URL to send, %s now add '
                 'GET parameters %s' % (pass_to, pass_params))

    if pass_params is not '':
        pass_to += pass_params

    logger.debug("\nMaking request:%s" % pass_to)
    query_string = build_querystring(request.GET.copy())

    ###############################################
    ###############################################
    # Now make the call to the backend API

    if interaction_type == "search":
        r = request_call(request,
                         pass_to,
                         cx,
                         reverse_lazy('home'),
                         timeout=rr.wait_time)
    else:
        r = request_call(request, pass_to, cx, reverse_lazy('home'))

    # BACK FROM THE CALL TO BACKEND
    ###############################################
    ###############################################

    # logger.debug("r returned: %s" % r)

    # Check for Error here
    # logger.debug("what is in r:\n#######\n%s\n##########\n" % dir(r))
    logger.debug("status: %s/%s" % (r.status_code, r._status_code))
    # logger.debug("text: %s\n#############\n" % (r.text))

    if r.status_code in ERROR_CODE_LIST:
        logger.debug("We have an error code to deal with: %s" % r.status_code)
        if 'html' in requested_format.lower():
            return render(
                request, 'bluebutton/default.html', {
                    'output': pretty_json(r._content, indent=4),
                    'fhir_id': get_fhir_id(cx),
                    'content': {
                        'parameters': query_string,
                        'resource_type': resource_type,
                        'id': id,
                        'request_method': "GET",
                        'interaction_type': interaction_type,
                        'div_texts': "",
                        'source': get_fhir_source_name(cx)
                    }
                })
        else:
            return HttpResponse(json.dumps(r._content, indent=4),
                                status=r.status_code,
                                content_type='application/json')

    text_out = ''
    host_path = get_host_url(request, resource_type)[:-1]
    # logger.debug('host path:%s' % host_path)

    # Add default FHIR Server URL to re-write
    rewrite_url_list = build_rewrite_list(cx)
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    # ct_detail = get_content_type(r)
    # logger.debug('Content-Type:%s \n work with %s' % (ct_detail,
    #                                                   back_end_format))

    text_in = get_response_text(fhir_response=r)

    text_out = post_process_request(request, back_end_format, host_path,
                                    text_in, rewrite_url_list)

    od = build_output_dict(request, OrderedDict(), resource_type, key, vid,
                           interaction_type, requested_format, text_out)

    # write session variables if _getpages was found
    ikey = ''
    try:
        ikey = find_ikey(r.text)
    except Exception:
        ikey = ''

    if ikey is not '':

        save_url = get_target_url(fhir_url, resource_type)
        # print("Store fhir_url:%s but only: %s" % (fhir_url,save_url))
        content = {
            'fhir_to': save_url,
            'rwrt_list': rewrite_url_list,
            'res_type': resource_type,
            'intn_type': interaction_type,
            'key': key,
            'vid': vid,
            'resource_router': rr.id
        }
        sesn_var = write_session(request, ikey, content, skey=SESSION_KEY)
        if sesn_var:
            logger.debug("Problem writing session variables."
                         " Returned %s" % sesn_var)
    if requested_format == 'xml':
        # logger.debug('We got xml back in od')
        return HttpResponse(r.text,
                            content_type='application/%s' % requested_format)
        # return HttpResponse(tostring(dict_to_xml('content', od)),
        #                     content_type='application/%s' % requested_format)

    elif requested_format == 'json':
        # logger.debug('We got json back in od')
        return HttpResponse(pretty_json(od['bundle']),
                            content_type='application/%s' % requested_format)

    # define query string further up before request_call
    # query_string = build_querystring(request.GET.copy())
    if "xml" in requested_format:
        # logger.debug("Sending text_out for display: %s" % text_out[0:100])
        div_text = get_div_from_xml(text_out)
        # print("DIV TEXT returned:[%s]%s" % (type(div_text), div_text))
        return render(
            request, 'bluebutton/default_xml.html', {
                'output': text_out,
                'fhir_id': get_fhir_id(cx),
                'content': {
                    'parameters': query_string,
                    'resource_type': resource_type,
                    'id': id,
                    'request_method': "GET",
                    'interaction_type': interaction_type,
                    'div_texts': [
                        div_text,
                    ],
                    'source': get_fhir_source_name(cx)
                }
            })

    else:
        text_out = pretty_json(od['bundle'])
        div_text = get_div_from_json(od['bundle'])

    # logger.debug('We got a different format:%s' % requested_format)
    logger.debug('id or key: %s/%s' % (id, key))

    return render(
        request, 'bluebutton/default.html', {
            'output': text_out,
            'fhir_id': cx.fhir_id,
            'content': {
                'parameters': query_string,
                'resource_type': resource_type,
                'id': id,
                'request_method': "GET",
                'interaction_type': interaction_type,
                'div_texts': div_text,
                'source': get_fhir_source_name(cx)
            }
        })
def rebuild_fhir_search(request):
    """ Rebuild the Search String

    We will start to use a session variable

    We received:
    http://localhost:8000/cmsblue/fhir/v1
    ?_getpages=61c6e2d1-2b7c-49c3-a083-3d5b3874d4ff&_getpagesoffset=10
    &_count=10&_format=json&_pretty=true&_bundletype=searchset

    Session Variables will be storing:
    - FHIR Target URL/Resource
    - _getpages value
    - expires datetime

    Construct FHIR_Target_URL + search parameters

    """

    # now = str(datetime.now())
    ikey = ""
    if "_getpages" in request.GET:
        ikey = request.GET["_getpages"]
        sn_vr = read_session(request, ikey, skey=SESSION_KEY)
        # logger.debug("Session info:%s" % sn_vr)

        if sn_vr == {}:
            # Nothing returned from Session Variables
            # Key could be expired or not matched
            return authenticated_home(request)

        url_call = sn_vr["fhir_to"]
        url_call += "/?" + request.META["QUERY_STRING"]

        rewrite_url_list = sn_vr["rwrt_list"]
        resource_type = sn_vr["res_type"]
        interaction_type = sn_vr["intn_type"]
        key = sn_vr["key"]
        vid = sn_vr["vid"]

        logger.debug("Calling:%s" % url_call)
        r = request_call(request, url_call, reverse_lazy("authenticated_home"))

        host_path = get_host_url(request, "?")

        # get 'xml' 'json' or ''
        fmt = get_search_param_format(request.META["QUERY_STRING"])

        text_out = post_process_request(request, fmt, host_path, r, rewrite_url_list)
        od = build_output_dict(request, OrderedDict(), resource_type, key, vid, interaction_type, fmt, text_out)

        if fmt == "xml":
            # logger.debug('We got xml back in od')
            return HttpResponse(r.text, content_type="application/%s" % fmt)
            # return HttpResponse( tostring(dict_to_xml('content', od)),
            #                      content_type='application/%s' % fmt)
        elif fmt == "json":
            # logger.debug('We got json back in od')
            return HttpResponse(pretty_json(od), content_type="application/%s" % fmt)

        # logger.debug('We got a different format:%s' % fmt)
        return render(request, "bluebutton/default.html", {"content": pretty_json(od), "output": od})

    return authenticated_home(request)
def fhir_conformance(request, *args, **kwargs):
    """ Pull and filter fhir Conformance statement

    metadata call

    """
    if not request.user.is_authenticated():
        return authenticated_home(request)

    resource_type = "Conformance"
    call_to = FhirServerUrl()
    if call_to.endswith("/"):
        call_to += "metadata"
    else:
        call_to += "/metadata"

    pass_params = urlencode(strip_oauth(request.GET))

    # Add ? to front of parameters if needed
    pass_params = prepend_q(pass_params)

    logger.debug("Calling:%s" % call_to + pass_params)

    r = request_call(request, call_to + pass_params, reverse_lazy("authenticated_home"))

    text_out = ""
    host_path = get_host_url(request, "?")

    # get 'xml' 'json' or ''
    fmt = get_search_param_format(request.META["QUERY_STRING"])

    rewrite_url_list = settings.FHIR_SERVER_CONF["REWRITE_FROM"]
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    text_out = post_process_request(request, fmt, host_path, r.text, rewrite_url_list)

    od = conformance_filter(text_out, fmt)

    if fmt == "xml":
        # logger.debug('We got xml back in od')
        return HttpResponse(text_out, content_type="application/%s" % fmt)
        # return HttpResponse( tostring(dict_to_xml('content', od)),
        #                      content_type='application/%s' % fmt)
    elif fmt == "json":
        # logger.debug('We got json back in od')
        return HttpResponse(pretty_json(od), content_type="application/%s" % fmt)

    # logger.debug('We got a different format:%s' % fmt)

    return render(
        request,
        "bluebutton/default.html",
        {
            "output": pretty_json(od),
            "content": {
                "parameters": request.GET.urlencode(),
                "resource_type": resource_type,
                "request_method": "GET",
                "interaction_type": "metadata",
            },
        },
    )
def get_fhir_claim(request, claim_number):
    """ Search for Claim Number in FHIR Backend

    Sample Search Specification:
     http://bluebuttonhapi-test.hhsdevcloud.us/baseDstu2/
     ExplanationOfBenefit
     ?identifier=CCW_PTA_FACT.CLM_ID|542612281109054

    Nothing found result:
     {"resourceType":"Bundle",
      "id":"62fe7fe3-9dca-4114-b753-6d7e874c34c5",
      "meta":{"lastUpdated":"2016-07-07T13:43:55.066+00:00"},
      "type":"searchset",
      "total":0,
      "link":[{"relation":"self",
               "url":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/
               ExplanationOfBenefit
               ?identifier=CCW_PTA_FACT.CLM_ID%7C542612281109055"}]}

    Sample EOB Records
    {
            "fullUrl":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/ExplanationOfBenefit/10",
            "resource":{
                "resourceType":"ExplanationOfBenefit",
                "id":"10",
                "extension":[
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#claimType",
                        "valueCoding":{
                            "system":"http://bluebutton.cms.hhs.gov/coding#claimType",
                            "code":"40",
                            "display":"Outpatient claim"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#attendingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/12"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#operatingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/13"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#otherPhysician",
                        "valueReference":{
                            "reference":"Practitioner/14"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#admittingDiagnosis",
                        "valueCoding":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis"
                        }
                    }
                ],
                "meta":{
                    "versionId":"1",
                    "lastUpdated":"2016-03-28T03:14:40.898+00:00"
                },
                "identifier":[
                    {
                        "system":"CCW_PTA_FACT.CLM_ID",
                        "value":"542612281109054"
                    }
                ],
                "billablePeriod":{
                    "start":"2008-11-15T00:00:00+00:00",
                    "end":"2008-11-15T00:00:00+00:00"
                },
                "provider":{
                    "reference":"Practitioner/11"
                },
                "diagnosis":[
                    {
                        "sequence":0,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"7137"
                        }
                    },
                    {
                        "sequence":1,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"72190"
                        }
                    }
                ],
                "patient":{
                    "reference":"Patient/1"
                },
                "coverage":{
                    "coverage":{
                        "reference":"Coverage/4"
                    }
                },
                "item":[
                    {
                        "type":{
                            "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                            "code":"CSPINV"
                        },
                        "adjudication":[
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"Line NCH Payment Amount"
                                },
                                "amount":{
                                    "value":10.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Primary Payer Claim Paid Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Blood Deductible Liability Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Deductible Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Coinsurance Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            }
                        ],
                        "detail":[
                            {
                                "extension":[
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":0
                                    },
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":1
                                    }
                                ],
                                "sequence":1,
                                "type":{
                                    "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                                    "code":"CSPINV"
                                },
                                "service":{
                                    "system":"HCPCS",
                                    "code":"73564"
                                }
                            }
                        ]
                    }
                ]
            },
            "search":{
                "mode":"match"
            }
        },
        {
            "fullUrl":"http://bluebuttonhapi-test.hhsdevcloud.us:80/baseDstu2/ExplanationOfBenefit/15",
            "resource":{
                "resourceType":"ExplanationOfBenefit",
                "id":"15",
                "extension":[
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#claimType",
                        "valueCoding":{
                            "system":"http://bluebutton.cms.hhs.gov/coding#claimType",
                            "code":"40",
                            "display":"Outpatient claim"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#attendingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/17"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#operatingPhysician",
                        "valueReference":{
                            "reference":"Practitioner/18"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#otherPhysician",
                        "valueReference":{
                            "reference":"Practitioner/19"
                        }
                    },
                    {
                        "url":"http://bluebutton.cms.hhs.gov/extensions#admittingDiagnosis",
                        "valueCoding":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis"
                        }
                    }
                ],
                "meta":{
                    "versionId":"1",
                    "lastUpdated":"2016-03-28T03:14:40.898+00:00"
                },
                "identifier":[
                    {
                        "system":"CCW_PTA_FACT.CLM_ID",
                        "value":"542062281310767"
                    }
                ],
                "billablePeriod":{
                    "start":"2009-02-02T00:00:00+00:00",
                    "end":"2009-02-02T00:00:00+00:00"
                },
                "provider":{
                    "reference":"Practitioner/16"
                },
                "diagnosis":[
                    {
                        "sequence":0,
                        "diagnosis":{
                            "system":"http://hl7.org/fhir/sid/icd-9-cm/diagnosis",
                            "code":"49321"
                        }
                    }
                ],
                "patient":{
                    "reference":"Patient/1"
                },
                "coverage":{
                    "coverage":{
                        "reference":"Coverage/4"
                    }
                },
                "item":[
                    {
                        "type":{
                            "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                            "code":"CSPINV"
                        },
                        "adjudication":[
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"Line NCH Payment Amount"
                                },
                                "amount":{
                                    "value":900.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Primary Payer Claim Paid Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Blood Deductible Liability Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Deductible Amount"
                                },
                                "amount":{
                                    "value":0.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            },
                            {
                                "category":{
                                    "system":"CMS Adjudications",
                                    "code":"NCH Beneficiary Part B Coinsurance Amount"
                                },
                                "amount":{
                                    "value":20.00,
                                    "system":"urn:std:iso:4217",
                                    "code":"USD"
                                }
                            }
                        ],
                        "detail":[
                            {
                                "extension":[
                                    {
                                        "url":"http://bluebutton.cms.hhs.gov/extensions#diagnosisLinkId",
                                        "valueInteger":0
                                    }
                                ],
                                "sequence":1,
                                "type":{
                                    "system":"http://hl7.org/fhir/ValueSet/v3-ActInvoiceGroupCode",
                                    "code":"CSPINV"
                                },
                                "service":{
                                    "system":"HCPCS",
                                    "code":"99214"
                                }
                            }
                        ]
                    }
                ]
            },
            "search":{
                "mode":"match"
            }
        },


    """

    # Get the FHIR Server URL
    # Construct the Search for ExplanationOfBenefit / PatientClaimSummary
    search_base = FhirServerUrl() + "ExplanationOfBenefit"

    # FHIR_URL + PATH + RELEASE + ExplanationOfBenefit?
    # claimIdentifier=claim_number
    # &_format=json

    # http://bluebuttonhapi-test.hhsdevcloud.us/baseDstu2/
    # ExplanationOfBenefit?identifier=CCW_PTA_FACT.CLM_ID|542882280967266

    search_base += "?_format=json&identifier="  # CCW_PTA_FACT.CLM_ID|"

    fhir_claim = {}
    fhir_claim["claimNumber"] = claim_number
    fhir_claim["found"] = False

    search_base += claim_number

    # logger.debug('Calling request_call with %s' % search_base)
    r = request_call(request, search_base)
    # logger.debug("returned with %s" % r.text)
    bundle = json.loads(r.text, object_pairs_hook=OrderedDict)
    resource = {}
    if bundle["total"] > 0:
        resource = bundle["entry"][0]["resource"]
        # If claim is found:
        fhir_claim["found"] = True
        fhir_claim["claimIdentifier"] = resource["identifier"][0]["value"]
        fhir_claim["identifier"] = resource["id"]
        fhir_claim["provider"] = resource["provider"]["reference"]
        fhir_claim["patient"] = resource["patient"]["reference"]
        if "billablePeriod" in resource:
            if isinstance(resource["billablePeriod"], dict):
                fhir_claim["timingPeriod"] = dict(resource["billablePeriod"])
            else:
                fhir_claim["timingPeriod"] = resource["billablePeriod"]
    # fhir_claim['claimIdentifier'] = ExplanationOfBenefit.claimIdentifier
    # fhir_claim['identifier'] = ExplanationOfBenefit.identifier
    # fhir_claim['provider'] = ExplanationOfBenefit.providerIdentifier
    # fhir_claim['patient'] = ExplanationOfBenefit.patientIdentifier
    # fhir_claim['timingPeriod'] = ExplanationOfBenefit.timingPeriod
    print("\nSearch for claim:", claim_number)
    print("\Resources:", resource)
    print("\nFound:", fhir_claim)
    # logger.debug('fhir_claim: %s' % fhir_claim)

    return fhir_claim
Example #14
0
def metadata(request, via_oauth=False, *args, **kwargs):
    """
    Arrive here to do capabilityStatement or Conformance
    aka metadata

    oauth_fhir_conformance sets via_oauth=True
    fhir_conformance sets via_oauth=False

    :param request:
    :param via_oauth:
    :param args:
    :param kwargs:
    :return:
    """
    cx = None
    rr = get_resourcerouter()
    call_to = FhirServerUrl()

    resource_type = conformance_or_capability(call_to)

    if call_to.endswith('/'):
        call_to += 'metadata'
    else:
        call_to += '/metadata'

    pass_params = request.GET
    # pass_params should be an OrderedDict after strip_auth
    # logger.debug("result from strip_oauth:%s" % pass_params)

    # Let's store the inbound requested format
    # We need to simplify the format call to the backend
    # so that we get data we can manipulate
    requested_format = request_format(pass_params)

    # now we simplify the format/_format request for the back-end
    pass_params = strip_format_for_back_end(pass_params)
    back_end_format = pass_params['_format']

    encoded_params = urlencode(pass_params)
    #
    # Add ? to front of parameters if needed
    pass_params = prepend_q(encoded_params)

    # logger.debug("Calling:%s" % call_to + pass_params)

    query_string = build_querystring(request.GET.copy())

    ####################################################
    ####################################################

    r = request_call(request,
                     call_to + pass_params,
                     cx,
                     reverse_lazy('authenticated_home'))

    ####################################################
    ####################################################

    text_out = ''
    host_path = get_host_url(request, '?')

    if r.status_code in ERROR_CODE_LIST:
        logger.debug("We have an error code to deal with: %s" % r.status_code)
        if 'html' in requested_format.lower():
            return render(
                request,
                'bluebutton/default.html',
                {'output': pretty_json(r._content, indent=4),
                 'fhir_id': get_fhir_id(cx),
                 'content': {'parameters': query_string,
                             'resource_type': resource_type,
                             'id': id,
                             'request_method': "GET",
                             'interaction_type': "search",
                             'div_texts': "",
                             'source': get_fhir_source_name(cx)}})
        else:
            return HttpResponse(json.dumps(r._content, indent=4),
                                status=r.status_code,
                                content_type='application/json')

    # get 'xml' 'json' or ''
    # fmt = get_search_param_format(request.META['QUERY_STRING'])
    # force to json

    # logger.debug("Format:%s" % back_end_format)

    rewrite_url_list = build_rewrite_list(cx)
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    text_in = get_response_text(fhir_response=r)
    # print("Capability text: %s\n" % r.text)
    # print("Capability _text: %s\n" % r._text)

    # text_in = r.text
    # if text_in == "":
    #     print("Capability assigning _text: %s\n" % r._text[:100])
    #
    #     text_in = r._text

    text_out = post_process_request(request,
                                    back_end_format,
                                    host_path,
                                    text_in,
                                    rewrite_url_list)
    # define query string further up before request_call
    # query_string = build_querystring(request.GET.copy())

    # logger.debug("Query:%s" % query_string)

    if 'xml' in requested_format:
        # logger.debug('We got xml back in od')

        # logger.debug("is xml filtered?%s" % requested_format)
        xml_dom = xml_to_dom(text_out)

        text_out = dom_conformance_filter(xml_dom, rr)

        # Append Security to ConformanceStatement
        security_endpoint = build_oauth_resource(request,
                                                 format_type="xml")
        text_out = append_security(text_out,
                                   security_endpoint)

        # logger.debug("Text from XML function:\n%s\n=========" % text_out)
        if 'html' not in requested_format:
            return HttpResponse(text_out,
                                content_type='application'
                                             '/%s' % requested_format)
        else:
            # logger.debug("Sending text_out for display: %s" % text_out[0:100])
            return render(
                request,
                'bluebutton/default_xml.html',
                {'output': text_out,
                 'content': {'parameters': query_string,
                             'resource_type': resource_type,
                             'request_method': "GET",
                             'interaction_type': "metadata",
                             'source': get_fhir_source_name(cx)}})

            # return HttpResponse( tostring(dict_to_xml('content', od)),
        #                      content_type='application/%s' % fmt)
    else:
        # back_end_format == 'json'
        # logger.debug('We got json back in od')
        od = conformance_filter(text_out, back_end_format, rr)

        # Append Security to ConformanceStatement
        security_endpoint = build_oauth_resource(request,
                                                 format_type="json")
        print("OD:\n%s" % od['rest'])
        od['rest'][0]['security'] = security_endpoint
        print("OD+Security:\n%s" % od)

        text_out = pretty_json(od)
        if 'html' not in requested_format:
            return HttpResponse(text_out,
                                content_type='application/'
                                             '%s' % requested_format)
        if 'security' in od:
            print("%s" % pretty_json(od['security'], indent=4))
        else:
            print("No security content in Conformance")
            print("od: %s" % pretty_json(od, indent=4))

    # logger.debug('We got a different format:%s' % back_end_format)

    return render(
        request,
        'bluebutton/default.html',
        {'output': text_out,
         'content': {'parameters': query_string,
                     'resource_type': resource_type,
                     'request_method': "GET",
                     'interaction_type': "metadata"}})
def generic_read(request,
                 interaction_type,
                 resource_type,
                 r_id=None,
                 vid=None,
                 *args,
                 **kwargs):
    """
    Read from remote FHIR Server

    :param request:
    :param interaction_type:
    :param resource_type:
    :param id:
    :param vid:
    :param args:
    :param kwargs:
    :return:

    # Example client use in curl:
    # curl  -X GET http://127.0.0.1:8000/fhir/Practitioner/1234

    """
    # interaction_type = 'read' or '_history' or 'vread' or 'search'
    logger.debug('interaction_type: %s' % interaction_type)

    # Check if this interaction type and resource type combo is allowed.
    deny = check_access_interaction_and_resource_type(resource_type,
                                                      interaction_type)
    if deny:
        # if not allowed, return a 4xx error.
        return deny

    srtc = check_rt_controls(resource_type)
    # We get back a Supported ResourceType Control record or None
    # with earlier if deny step we should have a valid srtc.

    default_path = get_default_path(srtc.resource_name)
    # get the default path for resource with ending "/"
    # You need to add resource_type + "/" for full url

    logger.debug('srtc: %s' % srtc)

    try:
        cx = Crosswalk.objects.get(user=request.user)
    except Crosswalk.DoesNotExist:
        cx = None
        # logger.debug('Crosswalk for %s does not exist' % request.user)

    if (cx is None and srtc is not None):
        # There is a srtc record so we need to check override_search
        if srtc.override_search:
            # If user is not in Crosswalk and srtc has search_override = True
            # We need to prevent search to avoid data leakage.
            return kickout_403('Error 403: %s Resource is access controlled.'
                               ' No records are linked to user:'******'%s' % (resource_type, request.user))

    # Request.user = user
    # interaction_type = read | _history | vread
    # resource_type = 'Patient | Practitioner | ExplanationOfBenefit ...'
    # id = fhir_id (potentially masked)
    # vid = Version Id

    # Check the resource_type to see if it has a url
    # Check the resource_type to see if masking is required
    # Get the FHIR_Server (from crosswalk via request.user)
    # if masked get the fhir_id from crosswalk
    # if search_override strip search items (search_block)
    # if search_override add search keys

    fhir_url = ''
    # change source of default_url to ResourceRouter

    # Add default FHIR Server URL to re-write

    rewrite_url_list = settings.FHIR_SERVER_CONF['REWRITE_FROM']
    # print("Starting Rewrite_list:%s" % rewrite_url_list)

    if srtc:
        logger.debug('SRTC:%s' % srtc)

        fhir_url = default_path + resource_type + '/'
        # Add to the rewrite_url list
        rewrite_url_list.append(default_path)

    else:
        logger.debug('CX:%s' % cx)
        if cx:
            fhir_url = cx.get_fhir_resource_url(resource_type)
            rewrite_url_list.append(fhir_url.replace(resource_type + '/', ''))
        else:
            # logger.debug('FHIRServer:%s' % FhirServerUrl())
            fhir_url = FhirServerUrl() + resource_type + '/'

    if FhirServerUrl()[:-1] not in rewrite_url_list:
        rewrite_url_list.append(FhirServerUrl()[:-1])

    logger.debug('FHIR URL:%s' % fhir_url)
    logger.debug('Rewrite List:%s' % rewrite_url_list)

    if interaction_type == 'search':
        key = None
    else:
        key = masked_id(resource_type, cx, srtc, r_id, slash=False)
        if fhir_url.endswith(resource_type + '/'):
            # we need to make sure we don't specify resource_type twice in URL
            if key.startswith(resource_type + '/'):
                key = key.replace(resource_type + '/', '')

        fhir_url += key + '/'

    logger.debug('FHIR URL with key:%s' % fhir_url)

    ###########################

    # Now we get to process the API Call.

    # Internal handling format is json
    # Remove the oauth elements from the GET
    pass_params = strip_oauth(request.GET)

    if interaction_type == 'search':
        if cx is not None:
            logger.debug("cx.fhir_id=%s" % cx.fhir_id)
            r_id = cx.fhir_id.split('/')[1]
            logger.debug("Patient Id:%s" % r_id)

    if resource_type == "Patient":
        key = r_id

    pass_params = build_params(pass_params,
                               srtc,
                               # key,
                               r_id,
                               )

    if interaction_type == 'vread':
        pass_to = fhir_url + '_history' + '/' + vid
    elif interaction_type == '_history':
        pass_to = fhir_url + '_history'
    else:  # interaction_type == 'read':
        pass_to = fhir_url

    logger.debug('Here is the URL to send, %s now add '
                 'GET parameters %s' % (pass_to, pass_params))

    if pass_params is not '':
        pass_to += pass_params

    logger.debug("Making request:%s" % pass_to)
    # Now make the call to the backend API
    r = request_call(request, pass_to, reverse_lazy('api:v1:home'))

    text_out = ''
    if 'text' in r:
        logger.debug('r:%s' % r.text)
    else:
        logger.debug("r not returning text:%s" % r)

    # logger.debug('Rewrite List:%s' % rewrite_url_list)

    host_path = get_host_url(request, resource_type)[:-1]
    logger.debug('host path:%s' % host_path)

    # get 'xml' 'json' or ''
    fmt = get_search_param_format(pass_params)

    text_out = post_process_request(request,
                                    fmt,
                                    host_path,
                                    r.text,
                                    rewrite_url_list)

    od = build_output_dict(request,
                           OrderedDict(),
                           resource_type,
                           key,
                           vid,
                           interaction_type,
                           fmt,
                           text_out)

    # write session variables if _getpages was found
    ikey = find_ikey(r.text)
    if ikey is not '':

        save_url = get_target_url(fhir_url, resource_type)
        # print("Store fhir_url:%s but only: %s" % (fhir_url,save_url))
        content = {
            'fhir_to': save_url,
            'rwrt_list': rewrite_url_list,
            'res_type': resource_type,
            'intn_type': interaction_type,
            'key': key,
            'vid': vid
        }
        sesn_var = write_session(request, ikey, content, skey=SESSION_KEY)
        if sesn_var:
            logger.debug("Problem writing session variables."
                         " Returned %s" % sesn_var)
    if fmt == 'xml':
        # logger.debug('We got xml back in od')
        return HttpResponse(r.text, content_type='application/%s' % fmt)
        # return HttpResponse( tostring(dict_to_xml('content', od)),
        #                      content_type='application/%s' % fmt)
    elif fmt == 'json':
        # logger.debug('We got json back in od')
        return HttpResponse(pretty_json(od),
                            content_type='application/%s' % fmt)

    # logger.debug('We got a different format:%s' % fmt)
    return render(
        request,
        'bluebutton/default.html',
        {'content': pretty_json(od), 'output': od},
    )