Skip to content

Commit 2aa4b40

Browse files
authored
jimfuqian/BB2-3280-C4DIC POC: Enrich c4dic coverage w supporting image (#1241)
* back end changes: enrich c4dic coverage w supporting image * fix linting * fix deps * fix linting * fix typos
1 parent 38a4999 commit 2aa4b40

File tree

9 files changed

+12631
-103
lines changed

9 files changed

+12631
-103
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ ENV PATH="/tmp/venv/bin:${PATH}"
1010
RUN pip install --upgrade pip
1111
RUN pip install --upgrade pip-tools
1212
RUN pip install --upgrade setuptools
13+
RUN pip install jsonpath-ng
1314
RUN pip install -r requirements/requirements.dev.txt --no-index --find-links ./vendor/

Dockerfiles/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Build, Tag, and Publish integration and selenium tests ECR iamge
1+
# Build, Tag, and Publish integration and selenium tests ECR image
22

33
Go to BB2 local repo base directory and do the followings (assume aws cli installed and configured properly):
44

apps/fhir/bluebutton/views/b64card.py

Lines changed: 12432 additions & 0 deletions
Large diffs are not rendered by default.

apps/fhir/bluebutton/views/search.py

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import copy
2+
from jsonpath_ng.ext import parse as ext_parse
3+
from rest_framework import (permissions)
4+
from rest_framework.response import Response
15
from voluptuous import (
26
Required,
37
All,
@@ -7,15 +11,86 @@
711
Schema,
812
REMOVE_EXTRA,
913
)
10-
from rest_framework import (permissions)
11-
from rest_framework.response import Response
1214

1315
from apps.fhir.bluebutton.constants import DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE
1416
from apps.fhir.bluebutton.views.generic import FhirDataView
1517
from apps.fhir.bluebutton.views.home import get_response_json
1618
from apps.authorization.permissions import DataAccessGrantPermission
1719
from apps.capabilities.permissions import TokenHasProtectedCapability
1820
from ..permissions import (SearchCrosswalkPermission, ResourcePermission, ApplicationActivePermission)
21+
from apps.fhir.bluebutton.views.b64card import B64_BLU_CARD, B64_RED_BLU_CARD, B64_BLU_CARD_BG, B64_HUMANA_PTD
22+
23+
24+
# image mapping to part A, B, C, D
25+
# A: B64_BLU_CARD_BG large vertical figma card as background
26+
# B: B64_RED_BLU_CARD classic medicare card image
27+
# C: B64_BLU_CARD horizontal figma card
28+
# D: B64_HUMANA_PTD medicare RX humana part D card
29+
INS_TYPE2CARD = {
30+
"Part A": ''.join(B64_BLU_CARD_BG.splitlines()),
31+
"Part B": ''.join(B64_RED_BLU_CARD.splitlines()),
32+
"Part C": ''.join(B64_BLU_CARD.splitlines()),
33+
"Part D": ''.join(B64_HUMANA_PTD.splitlines())
34+
}
35+
36+
C4BB_COVERAGE_PROFILE_URL = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Coverage"
37+
38+
C4DIC_COVERAGE_PROFILE_URL = "http://hl7.org/fhir/us/insurance-card/StructureDefinition/C4DIC-Coverage"
39+
40+
C4DIC_SUPPORTING_IMAGE_EXT = {
41+
"extension": [
42+
{
43+
"url": "description",
44+
"valueString": "Beneficiary's proof of insurance"
45+
},
46+
{
47+
"url": "image",
48+
"valueAttachment": {
49+
"contentType": "image/png",
50+
"data": "<replace with base64 encoded image png here>"
51+
}
52+
},
53+
{
54+
"url": "label",
55+
"valueString": "CMS Insurance card"
56+
}
57+
],
58+
"url": "http://hl7.org/fhir/us/insurance-card/StructureDefinition/C4DIC-SupportingImage-extension"
59+
}
60+
61+
62+
# POC helper
63+
def lookup_by_path(expr, json_obj):
64+
jsonpath_expr = ext_parse(expr)
65+
return jsonpath_expr.find(json_obj)
66+
67+
68+
# POC helper
69+
def lookup_1_and_get(expr, attribute, json_obj):
70+
r = lookup_by_path(expr, json_obj)
71+
if r and isinstance(r, list):
72+
return r[0].value[attribute]
73+
74+
75+
# POC helper: generate supporting image extension per coverage class type
76+
def get_supporting_image_extension(b64encoded: str):
77+
ext = copy.deepcopy(C4DIC_SUPPORTING_IMAGE_EXT)
78+
for e in ext['extension']:
79+
if e['url'] == 'image':
80+
e['valueAttachment']['data'] = b64encoded
81+
break
82+
return ext
83+
84+
85+
# POC helper
86+
def enrich_supporting_image(resp: Response):
87+
for e in resp.data['entry']:
88+
extensions = e['resource']['extension']
89+
class_type = lookup_1_and_get("$.resource.class[?(@.type.coding[0].code=='plan')]", "value", e)
90+
class_type = "Part A" if class_type is None else class_type
91+
extensions.append(get_supporting_image_extension(INS_TYPE2CARD[class_type]))
92+
93+
return resp
1994

2095

2196
class SearchView(FhirDataView):
@@ -41,7 +116,8 @@ class SearchView(FhirDataView):
41116
QUERY_SCHEMA = {
42117
Required('startIndex', default=0): Coerce(int),
43118
Required('_count', default=DEFAULT_PAGE_SIZE): All(Coerce(int), Range(min=0, max=MAX_PAGE_SIZE)),
44-
'_lastUpdated': [Match(REGEX_LASTUPDATED_VALUE, msg="the _lastUpdated operator is not valid")]
119+
'_lastUpdated': [Match(REGEX_LASTUPDATED_VALUE, msg="the _lastUpdated operator is not valid")],
120+
'_profile': Match('.+', msg="_profile value takes a non empty url like string")
45121
}
46122

47123
def __init__(self, version=1):
@@ -100,10 +176,12 @@ def build_parameters(self, request, *args, **kwargs):
100176
def get(self, request, *args, **kwargs):
101177
profile = request.query_params.get('_profile', '')
102178
return_c4dic = False
103-
if return_c4dic and profile == "http://hl7.org/fhir/us/insurance-card/StructureDefinition/C4DIC-Coverage":
179+
if return_c4dic and profile == C4DIC_COVERAGE_PROFILE_URL:
104180
return Response(get_response_json("bfd-c4dic-coverage-search"))
105181
else:
106-
return super().get(request, *args, **kwargs)
182+
resp = super().get(request, *args, **kwargs)
183+
# C4DIC POC: inject c4dic supportingImage extension if the _profile indicate C4DIC Coverage search
184+
return enrich_supporting_image(resp) if profile == C4DIC_COVERAGE_PROFILE_URL else resp
107185

108186

109187
class SearchViewExplanationOfBenefit(SearchView):

0 commit comments

Comments
 (0)