-
Notifications
You must be signed in to change notification settings - Fork 13
/
Factors_to_Consider_in_Managing_Chronic_Pain_FHIRv400.cql
1094 lines (925 loc) · 49.5 KB
/
Factors_to_Consider_in_Managing_Chronic_Pain_FHIRv400.cql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// # Introduction
// The Pain Management Summary artifact provides relevant information to consider when managing a patient’s pain.
// This CDS logic was informed by the Centers for Disease Control and Prevention (CDC) Guideline for Opioid Prescribing
// for Chronic Pain. The CDS is not a direct representation of any one recommendation statement within the guideline.
// Instead, the CDS compiles clinical concepts mentioned throughout the guideline in one consolidated summary for
// clinician review.
//
// In the process of authoring the logic, certain assumptions were made and details developed when the guideline did
// not provide enough specificity. These decisions were made in the context of the CDS Connect Workgroup and CDC
// stakeholders, and are documented in the logic and/or in the CDS Connect artifact metadata.
//
// NOTE: This is a FHIR R4 port of the original FHIR DSTU2 CQL piloted for CDS Connect. In addition to the changes
// to support FHIR R4, it contains the following additional changes from the artifact that was piloted:
// - Added the following value sets for identifying Risk Factors for Opiod-Related Harms (in addition to existing ones)
// - Depression Diagnosis ICD9 (2.16.840.1.113883.3.600.143)
// - Anxiety Disorders ICD9 (2.16.840.1.113883.3.1240.2017.3.2.1015)
// - Substance Abuse (2.16.840.1.113883.3.464.1003.106.11.1010)
// - Pregnancy (New ICD10 codes published in 2018 and 2019)": '2.16.840.1.113762.1.4.1032.80'
// - Changed the Suicide Attempt value set to 2.16.840.1.113762.1.4.1032.102
// - Removed specific inclusion of SNOMED-CT 86849004 since it is now in the Suicide Attempt value set
// - Added LOINC codes for the Pain intensity, Enjoyment of life, General activity scale [PEG]
// - Previous local codes are still supported (but discouraged)
// - Added logic to normalize long LOINC display text for PEG codes to shorter names
// - Added LOINC code for the STarT Back Screening Tool
// - Previous local code is still supported (but discouraged)
// - Added logic to display range for Opioid Risk Tool (ORT)
// - Updated QuantityText logic to not include '{score}' units (since scalar number is enough in those cases)
//
// ##Source guideline: [CDC Guideline for Opioid Prescribing for Chronic Pain](https://www.cdc.gov/drugoverdose/prescribing/guideline.html)
library Factors_to_Consider_in_Managing_Chronic_Pain_FHIRv400 version '1.0.0'
// # Data model #
// The FHIR R4 model is used for testing purposes only. It has not been piloted.
using FHIR version '4.0.0'
// # Referenced libraries #
// The CDS Connect Commons for FHIRv400 library provides functions representing commonly used CDS logic and patterns.
include CDS_Connect_Commons_for_FHIRv400 version '1.0.1' called C3F
// The FHIRHelpers library provides common functions for simplifying interaction w/ the FHIR R4 data model.
include FHIRHelpers version '4.0.0' called FHIRHelpers
// # Value sets and codes #
// ## Code Systems ##
codesystem "LOINC": 'http://loinc.org'
codesystem "SNOMED-CT": 'http://snomed.info/sct'
// Several concepts needed by the Pain Management Summary CDS do not yet have standardized codes associated with them.
// The CDS logic authors have registered new Logical Object Identifier Names and Codes (LOINC) codes, but they are
// not yet available. Once available, the CDS will be updated. Until then, CDS implementors will need to map to
// local codes (signified by the LOCAL code system below) or replace them with their own codes.
codesystem "LOCAL": 'http://cds.ahrq.gov/cdsconnect/pms'
// ## Value sets ##
// List value sets used by the artifact. The links to the Value Set Authority Center (VSAC) point to the latest
// expansion of each value set available.
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.37/expansion)
valueset "Conditions associated with chronic pain": '2.16.840.1.113762.1.4.1032.37'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.34/expansion)
valueset "Opioid Pain Medications": '2.16.840.1.113762.1.4.1032.34'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.54/expansion)
valueset "Adjuvant Analgesic Medications": '2.16.840.1.113762.1.4.1032.54'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.464.1003.105.12.1007/expansion)
valueset "Major Depression": '2.16.840.1.113883.3.464.1003.105.12.1007'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.600.143/expansion)
valueset "Depression Diagnosis ICD9": '2.16.840.1.113883.3.600.143'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.52/expansion)
valueset "Anxiety": '2.16.840.1.113762.1.4.1032.52'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.1240.2017.3.2.1015/expansion)
valueset "Anxiety Disorders ICD9": '2.16.840.1.113883.3.1240.2017.3.2.1015'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.464.1003.106.12.1004/expansion)
valueset "Substance use disorder": '2.16.840.1.113883.3.464.1003.106.12.1004'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.464.1003.106.11.1010/expansion)
valueset "Substance Abuse": '2.16.840.1.113883.3.464.1003.106.11.1010'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.102/expansion)
valueset "Suicide Attempt": '2.16.840.1.113762.1.4.1032.102'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.53/expansion)
valueset "Sleep-disordered breathing": '2.16.840.1.113762.1.4.1032.53'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.464.1003.109.12.1028/expansion)
valueset "Kidney Failure": '2.16.840.1.113883.3.464.1003.109.12.1028'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.464.1003.199.12.1035/expansion)
valueset "Chronic Liver Disease": '2.16.840.1.113883.3.464.1003.199.12.1035'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1047.42/expansion)
valueset "Liver Disease": '2.16.840.1.113762.1.4.1047.42'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113883.3.526.3.378/expansion)
valueset "Pregnancy": '2.16.840.1.113883.3.526.3.378'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.80/expansion)
valueset "Pregnancy (New ICD10 codes published in 2018 and 2019)": '2.16.840.1.113762.1.4.1032.80'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.26/expansion)
valueset "Non opiod pain medications": '2.16.840.1.113762.1.4.1032.26'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.36/expansion)
valueset "Non pharmacologic treatments for chronic pain": '2.16.840.1.113762.1.4.1032.36'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.55/expansion)
valueset "Risk assessments relevant to pain management": '2.16.840.1.113762.1.4.1032.55'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.43/expansion)
valueset "Benzodiazepine medications": '2.16.840.1.113762.1.4.1032.43'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.42/expansion)
valueset "Naloxone medications": '2.16.840.1.113762.1.4.1032.42'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.28/expansion)
valueset "Urine drug screen for pain management": '2.16.840.1.113762.1.4.1032.28'
// [See value set in VSAC](https://vsac.nlm.nih.gov/valueset/2.16.840.1.113762.1.4.1032.44/expansion)
valueset "Stool softeners and laxatives": '2.16.840.1.113762.1.4.1032.44'
// ## Individual codes ##
// list individual codes from code systems used directly in the CQL logic. Individual codes are used when there is
// a single code from a particular vocabulary standard used to represent a clinical concept. It is considered
// best-practice not to create value sets containing a single code.
code "Pregnancy status code": '82810-3' from "LOINC" display 'Pregnancy status'
code "Pregnant code": '77386006' from "SNOMED-CT" display 'Patient currently pregnant (finding)'
code "Patient Health Questionnaire 2 item (PHQ-2) total score [Reported] code":
'55758-7' from "LOINC" display 'Patient Health Questionnaire 2 item (PHQ-2) total score [Reported]'
code "Patient Health Questionnaire 9 item (PHQ-9) total score [Reported] code":
'44261-6' from "LOINC" display 'Patient Health Questionnaire 9 item (PHQ-9) total score [Reported]'
code "Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ] code":
'70274-6' from "LOINC" display 'Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ]'
code "Total score [AUDIT] code": '75624-7' from "LOINC" display 'Total score [AUDIT]'
code "Total score [AUDIT-C] code": '75626-2' from "LOINC" display 'Total score [AUDIT-C]'
code "Total score [DAST-10] code": '82667-7' from "LOINC" display 'Total score [DAST-10]'
code "Total score ORT code": '91392-1' from "LOINC" display 'Total score ORT'
code "Pain severity Wong-Baker FACES Scale code": '38221-8' from "LOINC" display 'Pain severity Wong-Baker FACES Scale'
// The Pain intensity, Enjoyment of life, General activity scale [PEG] now has standardized LOINC codes available.
// These LOINC codes were not available when the initial version of the Pain Management Summary was developed.
// New systems implementing the Pain Management Summary should use the standardized codes, but the legacy local codes
// are also retained in order to allow existing systems to continue to function. Existing systems, however, are
// strongly encouraged to adopt the standardized LOINC codes.
code "Mean score [PEG] code": '91147-9' from "LOINC" display 'Mean score [PEG]'
code "Pain severity in the past week - 0-10 numeric rating [Reported] code":
'75893-8' from "LOINC" display 'Pain severity in the past week - 0-10 numeric rating [Reported]'
code "What number best describes how pain has interfered with your enjoyment of life during the past week code":
'91145-3' from "LOINC" display 'What number best describes how pain has interfered with your enjoyment of life during the past week'
code "What number best describes how pain has interfered with your general activity during the past week code":
'91146-1' from "LOINC" display 'What number best describes how pain has interfered with your general activity during the past week'
// Legacy local codes for the Pain intensity, Enjoyment of life, General activity scale [PEG].
// New systems should use the LOINC codes above instead.
code "Pain Enjoyment General Activity (PEG) Assessment LEGACY code":
'PEGASSESSMENT' from "LOCAL" display 'Pain Enjoyment General Activity (PEG) Assessment'
code "Pain LEGACY code": 'PEGPAIN' from "LOCAL" display 'Pain'
code "Enjoyment of life LEGACY code": 'PEGENJOYMENT' from "LOCAL" display 'Enjoyment of life'
code "General activity LEGACY code": 'PEGGENERALACTIVITY' from "LOCAL" display 'General activity'
// The STarT Back Screening Tool now has a standardized LOINC code available. This LOINC code was not available
// when the initial version of the Pain Management Summary was developed. New systems implementing the Pain Management
// Summary should use the standardized code, but the legacy local code is also retained in order to allow existing
// systems to continue to function. Existing systems, however, are strongly encouraged to adopt the standardized LOINC
// code.
code "Total score [STarT Back] code": '91351-7' from "LOINC" display 'Total score [STarT Back]'
// Legacy local code for the STarT Back Screening Tool. New systems should use the LOINC codes above instead.
code "STarT Back Screening Tool LEGACY code": 'STARTBACK' from "LOCAL" display 'STarT Back Screening Tool'
// The following codes do not yet have standardized codes associated with them so are expressed as LOCAL codes.
// As standardized codes become available, this CDS will be updated to use standard codes rather than LOCAL codes.
code "Single question r/t ETOH use code": 'SQETOHUSE' from "LOCAL" display 'Single question r/t ETOH use'
code "Single question r/t drug use code": 'SQDRUGUSE' from "LOCAL" display 'Single question r/t drug use'
code "Morphine Milligram Equivalent (MME) code": 'MME' from "LOCAL" display 'Morphine Milligram Equivalent (MME)'
// CQL currently requires concept declarations to contain references to code declarations.
concept "Pregnancy status": { "Pregnancy status code" } display 'Pregnancy status'
concept "Pregnant": { "Pregnant code" } display 'Patient currently pregnant (finding)'
concept "Patient Health Questionnaire 2 item (PHQ-2) total score [Reported]":
{ "Patient Health Questionnaire 2 item (PHQ-2) total score [Reported] code" }
display 'Patient Health Questionnaire 2 item (PHQ-2) total score [Reported]'
concept "Patient Health Questionnaire 9 item (PHQ-9) total score [Reported]":
{ "Patient Health Questionnaire 9 item (PHQ-9) total score [Reported] code" }
display 'Patient Health Questionnaire 9 item (PHQ-9) total score [Reported]'
concept "Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ]":
{ "Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ] code" }
display 'Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ]'
concept "Total score [AUDIT]": { "Total score [AUDIT] code" } display 'Total score [AUDIT]'
concept "Total score [AUDIT-C]": { "Total score [AUDIT-C] code" } display 'Total score [AUDIT-C]'
concept "Total score [DAST-10]": { "Total score [DAST-10] code" } display 'Total score [DAST-10]'
concept "Total score ORT": { "Total score ORT code" } display 'Total score ORT'
concept "Pain severity Wong-Baker FACES Scale":
{ "Pain severity Wong-Baker FACES Scale code" } display 'Pain severity Wong-Baker FACES Scale'
concept "Pain severity in the past week - 0-10 numeric rating [Reported]":
{ "Pain severity in the past week - 0-10 numeric rating [Reported] code" }
display 'Pain severity in the past week - 0-10 numeric rating [Reported]'
concept "What number best describes how pain has interfered with your enjoyment of life during the past week":
{ "What number best describes how pain has interfered with your enjoyment of life during the past week code" }
display 'What number best describes how pain has interfered with your enjoyment of life during the past week'
concept "What number best describes how pain has interfered with your general activity during the past week":
{ "What number best describes how pain has interfered with your general activity during the past week code" }
display 'What number best describes how pain has interfered with your general activity during the past week'
concept "Mean score [PEG]": { "Mean score [PEG] code" } display 'Mean score [PEG]'
concept "Pain Enjoyment General Activity (PEG) Assessment LEGACY":
{ "Pain Enjoyment General Activity (PEG) Assessment LEGACY code" } display 'Pain Enjoyment General Activity (PEG) Assessment'
concept "Pain LEGACY": { "Pain LEGACY code" } display 'Pain'
concept "Enjoyment of life LEGACY": { "Enjoyment of life LEGACY code" } display 'Enjoyment of life'
concept "General activity LEGACY": { "General activity LEGACY code" } display 'General activity'
concept "Total score [STarT Back]": { "Total score [STarT Back] code" } display 'Total score [STarT Back]'
concept "STarT Back Screening Tool LEGACY": { "STarT Back Screening Tool LEGACY code" } display 'STarT Back Screening Tool'
concept "Single question r/t ETOH use": { "Single question r/t ETOH use code" } display 'Single question r/t ETOH use'
concept "Single question r/t drug use": { "Single question r/t drug use code" } display 'Single question r/t drug use'
concept "Morphine Milligram Equivalent (MME)":
{ "Morphine Milligram Equivalent (MME) code" } display 'Morphine Milligram Equivalent (MME)'
// # Parameters #
// The InclusionMedicationsLookbackPeriod allows CDS implementors to specify how far the inclusion logic should look
// back for qualifying active medications. By default, the inclusion logic will look back 180 days.
parameter InclusionMedicationsLookbackPeriod default 180 days
// # CDS logic #
context Patient
// ## Re-usable functions ##
// The summary logic contains many constructs that are needed throughout the logic. Where possible, these constructs
// have been developed as re-usable functions that can be invoked wherever they are needed.
// Returns the first-found display text for a CodeableConcept, looking first at the `text` attribute, then the
// `display` on each `coding` until it finds a non-null value. Some PEG codes are normalized due to length.
// @param c - a FHIR CodeableConcept to get text from
// @returns {System.String} the display text or null if none is found
define function ConceptText(c FHIR.CodeableConcept):
if c ~ "Mean score [PEG]" or c ~ "Pain Enjoyment General Activity (PEG) Assessment LEGACY"
then 'Mean score [PEG]'
else if c ~ "Pain severity in the past week - 0-10 numeric rating [Reported]" or c ~ "Pain LEGACY"
then 'Pain'
else if c ~ "What number best describes how pain has interfered with your enjoyment of life during the past week"
or c ~ "Enjoyment of life LEGACY"
then 'Enjoyment of life'
else if c ~ "What number best describes how pain has interfered with your general activity during the past week"
or c ~ "General activity LEGACY"
then 'General activity'
else
Coalesce(c.text.value, Coalesce((c.coding) c2 return c2.display.value))
// We do not reliably get ranges back from EHR data, but ranges are important to understanding assessment scores in
// the summary. This function adds ranges to the name for known assessments.
// @param c - a FHIR CodeableConcept to get the updated text for
// @returns {System.String} the display text with range information appended
define function ConceptTextWithRange(c FHIR.CodeableConcept):
if c ~ "Patient Health Questionnaire 2 item (PHQ-2) total score [Reported]"
then ConceptText(c) + ' [Range: 0-6]'
else if c ~ "Patient Health Questionnaire 9 item (PHQ-9) total score [Reported]"
then ConceptText(c) + ' [Range: 0-27]'
else if c ~ "Generalized anxiety disorder 7 item (GAD-7) total score [Reported.PHQ]"
then ConceptText(c) + ' [Range: 0-21]'
else if c ~ "Total score [AUDIT]"
then ConceptText(c) + ' [Range: 0-40]'
else if c ~ "Total score [AUDIT-C]"
then ConceptText(c) + ' [Range: 0-12]'
else if c ~ "Total score [DAST-10]"
then ConceptText(c) + ' [Range: 0-10]'
else if c ~ "Total score ORT"
then ConceptText(c) + ' [Range: 0-26]'
else if c ~ "Pain severity Wong-Baker FACES Scale"
then ConceptText(c) + ' [Range: 0-10]'
else if c ~ "Mean score [PEG]"
or c ~ "Pain Enjoyment General Activity (PEG) Assessment LEGACY"
then ConceptText(c) + ' [Range: 0-10]'
else if c ~ "Total score [STarT Back]"
or c ~ "STarT Back Screening Tool LEGACY"
then ConceptText(c) + ' [Range: 0-9]'
else
ConceptText(c)
// Returns a text representation of a date using the CQL `ToString` function.
// @param d - a FHIR date to get text for
// @returns {System.String} the text representation of the date
define function DateText(d FHIR.date):
ToString(d.value)
// Returns a text representation of a dateTime using the CQL `ToString` function.
// @param d - a FHIR dateTime to get text for
// @returns {System.String} the text representation of the dateTime
define function DateTimeText(d FHIR.dateTime):
ToString(d.value)
// Returns a text representation of an instant using the CQL `ToString` function.
// @param i - a FHIR instant to get text for
// @returns {System.String} the text representation of the instant
define function InstantText(i FHIR.instant):
ToString(i.value)
// Returns a text representation of a Quantity with the Quantity's value and unit.
// If the unit is {score}, then omit it (as it is not useful to display)
// @param q - a FHIR Quantity to get text for
// @returns {System.String} the text representation of the Quantity
define function QuantityText(q FHIR.Quantity):
if (q is null) then null
else if (q.unit is not null and q.unit.value != '{score}') then ToString(q.value.value) + ' ' + q.unit.value
else if (q.code is not null and q.code.value != '{score}') then ToString(q.value.value) + ' ' + q.code.value
else ToString(q.value.value)
// Returns a tuple containing a Period's start and end as text representations.
// @param p - a FHIR Period to get a tuple for
// @returns {Tuple<Start System.String, End System.String>} the tuple representation of the Period
define function PeriodObject(p FHIR.Period):
if p is null then null
else
{
Start: DateTimeText(p."start"),
End: DateTimeText(p."end")
}
// Returns a tuple containing a Range's low and high as text representations.
// @param r - a FHIR Range to get a tuple for
// @returns {Tuple<Low System.String, High System.String>} the tuple representation of the Range
define function RangeObject(r FHIR.Range):
if r is null then null
else
{
Low: QuantityText(r.low),
High: QuantityText(r.high)
}
// Returns a text representation of a date associated with an Observation, preferring `effectiveDateTime`, then
// `effectivePeriod.start`, then `issued`.
// @param o - a FHIR Observation to get the text date from
// @returns {System.String} the text representation of a relevant date from the Observation
define function ObservationDate(o FHIR.Observation):
Coalesce(
DateTimeText(o.effective as FHIR.dateTime),
InstantText(o.effective as FHIR.instant),
DateTimeText((o.effective as FHIR.Period)."start"),
InstantText(o.issued)
)
// Returns a text representation of a date associated with a MedicationStatement, preferring `effectiveDateTime`, then
// `.start`.
// @param s - a FHIR MedicationStatement to get the text date from
// @returns {System.String} the text representation of a relevant date from the MedicationStatement
define function MedicationStatementDate(s FHIR.MedicationStatement):
Coalesce(
DateTimeText(s.effective as FHIR.dateTime),
DateTimeText((s.effective as FHIR.Period)."start")
)
// Returns a text representation of a Condition's onset, whether represented as a dateTime, Period, Quantity (Age),
// Range (Age), or string.
// @param c - a FHIR Condition to get the text representation of the onset from
// @returns {System.String} the text representation of the Condition's onset
define function Onset(c FHIR.Condition):
Coalesce( List{
DateTimeText(c.onset as FHIR.dateTime),
QuantityText(c.onset as FHIR.Age),
PeriodObject(c.onset as FHIR.Period),
RangeObject(c.onset as FHIR.Range),
(c.onset as FHIR.string).value
})
// Returns a text representation of a Condition's abatement, whether represented as a dateTime, Period, Quantity (Age),
// Range (Age), string, or boolean.
// @param c - a FHIR Condition to get the text representation of the abatement from
// @returns {System.String} the text representation of the Condition's abatement
define function Abatement(c FHIR.Condition):
Coalesce( List{
DateTimeText(c.abatement as FHIR.dateTime),
QuantityText(c.abatement as FHIR.Age),
PeriodObject(c.abatement as FHIR.Period),
RangeObject(c.abatement as FHIR.Range),
(c.abatement as FHIR.string).value
})
// ## Target population ##
// INCLUSIONS
// Determines if patient's age, in years, at the time CQL is run, is at least 18 years old
define Is18orOlder:
AgeInYears() >= 18
// Conditions associated with chronic pain
define ConditionsAssociatedWithChronicPain:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Conditions associated with chronic pain"]))
// Determines if the patient has any of the conditions associated with chronic pain
define HasConditionAssociatedWithChronicPain:
exists(ConditionsAssociatedWithChronicPain)
// Determines if the patient has any record of opioid pain medications in the lookback period
// - Medication Request within past 180 days (lookback can be made a parameter)
// - Medication Statement by patient within past 180 days (lookback can be made a parameter)
define HasRecentOpioidPainMedication:
exists(C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Opioid Pain Medications"],
InclusionMedicationsLookbackPeriod)
))
or exists(C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Opioid Pain Medications"],
InclusionMedicationsLookbackPeriod)
))
// Determines if the patient has any record of adjuvant analgesic medications in the lookback period
// - Medication Request within past 180 days (lookback can be made a parameter)
// - Medication Statement by patient within past 180 days (lookback can be made a parameter)
define HasRecentAdjuvantAnalgesicMedication:
exists(C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Adjuvant Analgesic Medications"],
InclusionMedicationsLookbackPeriod)
))
or exists(C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Adjuvant Analgesic Medications"],
InclusionMedicationsLookbackPeriod)
))
// Determines if the patient meets the inclusion criteria for the CDS. Inclusion criteria is:
// - Age >=18 years
// - AND
// - OR Conditions associated with chronic pain
// - OR Opioid pain medication
// - OR Adjuvant analgesic medication
define MeetsInclusionCriteria:
Is18orOlder
and (
HasConditionAssociatedWithChronicPain
or HasRecentOpioidPainMedication
or HasRecentAdjuvantAnalgesicMedication
)
// EXCLUSIONS
// TAKE NOTICE: This CDS is not intended for patients who meet any of the following criteria:
// 1. Younger than 18 years of age
// 2. Undergoing end-of-life care (hospice or palliative)
// 3. Undergoing active cancer treatment
//
// The first exclusion is explicitly accounted for under INCLUSIONS.
// The second and third exclusions cannot be realiably detected for all patients using just EHR data. For that reason
// they are not implemented in this CDS. Care providers should use their judgement when applying this CDS to their
// patients.
// ## Intervention(s) ##
// DISPLAY and POPULATE a Pain Management Summary of the following items:
// PERTINENT MEDICAL HISTORY
// Conditions associated with chronic pain and their dates of onset
define ReportConditionsAssociatedWithChronicPain:
(ConditionsAssociatedWithChronicPain) C
return {
Name: ConceptText(C.code),
Status: C.clinicalStatus.coding[0].code.value,
Onset: Onset(C),
DateRecorded: DateTimeText(C.recordedDate)
}
sort by (Onset as String) desc
// Conditions that are risk factors for opioid-related harms and their dates of onset
// This is a union of nine value sets (w/ different filtering criteria)
define DepressionConditions:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Major Depression"]))
union C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Depression Diagnosis ICD9"]))
define AnxietyConditions:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Anxiety"]))
union C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Anxiety Disorders ICD9"]))
define SubstanceUseDisorderConditions:
C3F.Confirmed([Condition: "Substance use disorder"])
union C3F.Confirmed([Condition: "Substance Abuse"])
define SuicideAttemptConditions:
C3F.Confirmed([Condition: "Suicide Attempt"])
define SleepDisorderedBreathingConditions:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Sleep-disordered breathing"]))
define RenalDysfunctionConditions:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Kidney Failure"]))
define HepaticDysfunctionConditions:
C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Chronic Liver Disease"]))
union C3F.Confirmed(C3F.ActiveOrRecurring([Condition: "Liver Disease"]))
define PregnancyConditions:
C3F.Confirmed(C3F.ConditionLookBack(C3F.ActiveOrRecurring(
[Condition: "Pregnancy"])
union [Condition: "Pregnancy (New ICD10 codes published in 2018 and 2019)"],
42 weeks
))
define PregnancyObservations:
C3F.Verified(C3F.ObservationLookBack([Observation: "Pregnancy status"], 42 weeks))
define MostRecentPregnancyObservation:
C3F.MostRecent(PregnancyObservations)
define MostRecentPregnancyObservationIsPositive:
C3F.ConceptValue(MostRecentPregnancyObservation) ~ "Pregnant"
define Is65orOlder:
AgeInYears() >= 65
define ConditionRiskFactorsForOpioidRelatedHarms:
DepressionConditions
union AnxietyConditions
union SubstanceUseDisorderConditions
union SuicideAttemptConditions
union SleepDisorderedBreathingConditions
union RenalDysfunctionConditions
union HepaticDysfunctionConditions
union PregnancyConditions
// Encounter diagnoses that are risk factors for opioid-related harms and their dates of onset. Some risk factors may
// not exist on the problem list, and therefore may not be represented as Conditions (depending on EHR implementation).
// For this, the logic also looks at the patient's encounters, trying to find risk factors recorded as encounter
// diagnosis codes. We do not look at the reasonReference field because the Conditions referred to would already be
// reflected in the expression that queries over Conditions.
define EncounterRiskFactorsForOpioidRelatedHarms:
[Encounter] E where exists(
E.reasonCode R where
FHIRHelpers.ToConcept(R) in "Major Depression"
or FHIRHelpers.ToConcept(R) in "Depression Diagnosis ICD9"
or FHIRHelpers.ToConcept(R) in "Anxiety"
or FHIRHelpers.ToConcept(R) in "Anxiety Disorders ICD9"
or FHIRHelpers.ToConcept(R) in "Substance use disorder"
or FHIRHelpers.ToConcept(R) in "Substance Abuse"
or FHIRHelpers.ToConcept(R) in "Suicide Attempt"
or FHIRHelpers.ToConcept(R) in "Sleep-disordered breathing"
or FHIRHelpers.ToConcept(R) in "Kidney Failure"
or FHIRHelpers.ToConcept(R) in "Chronic Liver Disease"
or FHIRHelpers.ToConcept(R) in "Liver Disease"
// Pregnancy not considered in Encounter diagnoses because this is an unrestricted lookback.
)
// NOTE: As a convention, if an expression's name starts with "Report", its purpose is to format data for the purpose
// of building the final summary object.
// Format the risk factors in a uniform way despite the different sources of the data (conditions, encounter diagnoses,
// etc.). Note that conditions do not have a "Visit" date and encounter diagnoses do not have a status, onset date,
// recorded date, or abatement date.
define ReportConditionRiskFactorsForOpioidRelatedHarms:
(ConditionRiskFactorsForOpioidRelatedHarms) C
return {
Name: ConceptText(C.code),
Status: C.clinicalStatus.coding[0].code.value,
Onset: Onset(C),
DateRecorded: DateTimeText(C.recordedDate),
Abatement: Abatement(C),
Visit: null as Tuple{ Start String, End String }
}
sort by (Onset as String) desc, (Abatement as String) desc
define function GetEncounterDiagnosesRiskFactorsForOpioidRelatedHarms(enc Encounter):
(enc.reasonCode) R
where FHIRHelpers.ToConcept(R) in "Major Depression"
or FHIRHelpers.ToConcept(R) in "Depression Diagnosis ICD9"
or FHIRHelpers.ToConcept(R) in "Anxiety"
or FHIRHelpers.ToConcept(R) in "Anxiety Disorders ICD9"
or FHIRHelpers.ToConcept(R) in "Substance use disorder"
or FHIRHelpers.ToConcept(R) in "Substance Abuse"
or FHIRHelpers.ToConcept(R) in "Suicide Attempt"
or FHIRHelpers.ToConcept(R) in "Sleep-disordered breathing"
or FHIRHelpers.ToConcept(R) in "Kidney Failure"
or FHIRHelpers.ToConcept(R) in "Chronic Liver Disease"
or FHIRHelpers.ToConcept(R) in "Liver Disease"
// Pregnancy not considered in Encounter diagnoses because this is an unrestricted lookback.
return {
Name: ConceptText(R),
Status: null as String,
Onset: null as String,
DateRecorded: null as String,
Abatement: null as String,
Visit: PeriodObject(enc.period)
}
define ReportEncounterRiskFactorsForOpioidRelatedHarms:
(flatten((EncounterRiskFactorsForOpioidRelatedHarms) E
return GetEncounterDiagnosesRiskFactorsForOpioidRelatedHarms(E))) D
sort by Visit.Start desc, Visit.End desc
// Shape the pregnancy Observation as a Condition, since this is the backup approach for detecting a pregnancy in case
// there are no active Conditions found.
define ReportMostRecentPositivePregnancyObservation:
if MostRecentPregnancyObservationIsPositive then
{
Name: ConceptText(MostRecentPregnancyObservation.code),
Status: ConceptText(MostRecentPregnancyObservation.value as FHIR.CodeableConcept),
Onset: ToString(Coalesce(
(MostRecentPregnancyObservation.effective as FHIR.dateTime).value,
(MostRecentPregnancyObservation.effective as FHIR.instant).value,
(MostRecentPregnancyObservation.effective as FHIR.Period)."start".value
)),
DateRecorded: ToString(MostRecentPregnancyObservation.issued.value),
Abatement: null as String,
Visit: null as Tuple{ Start String, End String }
}
else
null
// Shape the case of being 65 or older as a Condition for the purposes of building the summary.
define ReportOlderThan65:
if Is65orOlder then
{
Name: '65 years or older',
Status: 'active',
Onset: null as String,
DateRecorded: null as String,
Abatement: null as String,
Visit: null as Tuple{ Start String, End String }
}
else
null
define ReportRiskFactorsForOpioidRelatedHarms:
// If a pregnancy Condition is present, use that.
if Exists(PregnancyConditions) then
(ReportConditionRiskFactorsForOpioidRelatedHarms
union ReportEncounterRiskFactorsForOpioidRelatedHarms
union ReportOlderThan65) C
// Otherwise, try to find a positive pregnancy status in an Observation.
else
(ReportConditionRiskFactorsForOpioidRelatedHarms
union ReportEncounterRiskFactorsForOpioidRelatedHarms
union ReportOlderThan65
union ReportMostRecentPositivePregnancyObservation) C
sort by (if Onset is not null then Onset as String else Visit.Start) desc, Visit.End desc, (Abatement as String) desc
// PAIN ASSESSMENT
// Numeric pain intensity assessment - scores and dates (lookback 2 years)
define NumericPainIntensityAssessments:
C3F.Verified(C3F.ObservationLookBack([Observation: "Pain severity Wong-Baker FACES Scale"], 2 years))
define ReportNumericPainIntensityAssessments:
(NumericPainIntensityAssessments) A
return {
Name: ConceptTextWithRange(A.code),
Score: QuantityText(A.value as FHIR.Quantity),
Interpretation: Coalesce( ConceptText(First(A.interpretation)), ConceptText(A.value as FHIR.CodeableConcept) ),
Date: ObservationDate(A)
}
sort by Date desc
// Pain Enjoyment General Activity (PEG) Assessment - scores and dates (lookback 2 years)
// Note: this includes listing the response to each of the 3 questions, plus the total score. The Pain Management
// Sumnmary currently supports both the LOINC representations and the legacy local code representations.
//
// 1. Observation w/ LOINC mean score as primary code and mean score as valueQuantity
// * code: LOINC 91147-9 "Mean score [PEG]"
// * valueQuantity: (mean score)
// * component:
// -
// * code: LOINC 75893-8 "What number best describes your pain on average in the past week?"
// * valueQuantity: (pain score)
// -
// * code: LOINC 91145-3 "What number best describes how, during the past week, pain has interfered with your enjoyment of life?"
// * valueQuantity: (enjoyment of life score)
// -
// * code: LOINC 91146-1 "What number best describes how, during the past week, pain has interfered with your general activity?"
// * valueQuantity: (general activity score)
//
// 2. LEGACY: Observation w/ LOCAL code as primary code and mean score as valueQuantity
// * code: LOCAL PEGASSESSMENT "Pain Enjoyment General Activity (PEG) Assessment"
// * valueQuantity: (mean score)
// * component:
// -
// * code: LOCAL PEGPAIN "Pain"
// * valueQuantity: (pain score)
// -
// * code: LOCAL PEGENJOYMENT "Enjoyment of life"
// * valueQuantity: (enjoyment of life score)
// -
// * code: LOCAL PEGGENERALACTIVITY "General activity"
// * valueQuantity: (general activity score)
define PainEnjoymentGeneralActivityAssessments:
C3F.Verified(C3F.ObservationLookBack(
[Observation: "Mean score [PEG]"]
union [Observation: "Pain Enjoyment General Activity (PEG) Assessment LEGACY"],
2 years
))
define ReportPainEnjoymentGeneralActivityAssessments:
(PainEnjoymentGeneralActivityAssessments) A
let
Pain: (A.component) C
where C.code ~ "Pain severity in the past week - 0-10 numeric rating [Reported]"
or C.code ~ "Pain LEGACY",
Enjoyment: (A.component) C
where C.code ~ "What number best describes how pain has interfered with your enjoyment of life during the past week"
or C.code ~ "Enjoyment of life LEGACY",
GeneralActivity: (A.component) C
where C.code ~ "What number best describes how pain has interfered with your general activity during the past week"
or C.code ~ "General activity LEGACY"
where true // grammar needs a where statement to separate the "let" from the "return"
return {
// NOTE: Hard-code in names because the real LOINC code displays are quite long
Name: ConceptTextWithRange(A.code),
Score: QuantityText(A.value as FHIR.Quantity),
Interpretation: Coalesce( ConceptText(First(A.interpretation)), ConceptText(A.value as FHIR.CodeableConcept) ),
Questions: ({ First(Pain), First(Enjoyment), First(GeneralActivity) }) C
where C is not null
return { "Name": ConceptText(C.code), "Score": QuantityText(C.value as FHIR.Quantity) },
Date: ObservationDate(A)
}
sort by Date desc
// STarT Back Screening Tool - Overall score and dates (lookback 2 years)
define STarTBackAssessments:
C3F.Verified(C3F.ObservationLookBack(
[Observation: "Total score [STarT Back]"]
union [Observation: "STarT Back Screening Tool LEGACY"],
2 years
))
define ReportSTarTBackAssessments:
(STarTBackAssessments) A
return {
Name: ConceptTextWithRange(A.code),
Score: QuantityText(A.value as FHIR.Quantity),
Interpretation: Coalesce( ConceptText(First(A.interpretation)), ConceptText(A.value as FHIR.CodeableConcept) ),
Date: ObservationDate(A)
}
sort by Date desc
// HISTORICAL TREATMENTS
// Opioid medication orders and statements with dates (lookback 2 years)
define OpioidMedicationRequests:
C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Opioid Pain Medications"],
2 years
))
define OpioidMedicationStatements:
C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Opioid Pain Medications"],
2 years
))
define ReportOpioidMedicationRequests:
(OpioidMedicationRequests) O
return {
Type: 'Request',
Name: ConceptText(O.medication as FHIR.CodeableConcept),
Start: DateTimeText(O.authoredOn),
End: null as String, // MedicationRequest end date not supported in R4,
Status: O.status.value
}
sort by Start desc, End desc
define ReportOpioidMedicationStatements:
(OpioidMedicationStatements) S
return {
Type: 'Statement',
Name: ConceptText(S.medication as FHIR.CodeableConcept),
Start: MedicationStatementDate(S),
End: DateTimeText((S.effective as FHIR.Period)."end"),
Status: S.status.value
}
sort by Start desc, End desc
define ReportOpioidMedications:
(ReportOpioidMedicationRequests union ReportOpioidMedicationStatements) M
sort by Start desc, End desc
// Non-opioid medication orders and statements with dates (lookback 2 years)
define NonOpioidMedicationRequests:
C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Non opiod pain medications"],
2 years
))
define NonOpioidMedicationStatements:
C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Non opiod pain medications"],
2 years
))
define ReportNonOpioidMedicationRequests:
(NonOpioidMedicationRequests) O
return {
Type: 'Request',
Name: ConceptText(O.medication as FHIR.CodeableConcept),
Start: DateTimeText(O.authoredOn),
End: null as String, // MedicationRequest end date not supported in R4,
Status: O.status.value
}
sort by Start desc, End desc
define ReportNonOpioidMedicationStatements:
(NonOpioidMedicationStatements) S
return {
Type: 'Statement',
Name: ConceptText(S.medication as FHIR.CodeableConcept),
Start: MedicationStatementDate(S),
End: DateTimeText((S.effective as FHIR.Period)."end"),
Status: S.status.value
}
sort by Start desc, End desc
define ReportNonOpioidMedications:
(ReportNonOpioidMedicationRequests union ReportNonOpioidMedicationStatements) M
sort by Start desc, End desc
// Non-pharmacologic treatments, orders, and referrals with dates (lookback 2 years)
define NonPharmacologicTreatmentProcedures:
C3F.ProcedurePerformance(C3F.ProcedureLookBack([Procedure: "Non pharmacologic treatments for chronic pain"], 2 years))
define ReportNonPharmacologicTreatmentProcedures:
(NonPharmacologicTreatmentProcedures) P
return {
Type: 'Procedure',
Name: ConceptText(P.code),
Date: Coalesce(
DateTimeText(P.performed as FHIR.dateTime),
DateTimeText((P.performed as FHIR.Period)."start")
)
}
sort by Date desc
define NonPharmacologicTreatmentServiceRequests:
C3F.ServiceRequestActiveOrCompleted(
C3F.ServiceRequestLookBack([ServiceRequest: "Non pharmacologic treatments for chronic pain"], 2 years)
)
define ReportNonPharmacologicTreatmentServiceRequests:
(NonPharmacologicTreatmentServiceRequests) P
return {
Type: 'ServiceRequest',
Name: ConceptText(P.code),
Date: DateTimeText(P.authoredOn)
}
sort by Date desc
define ReportNonPharmacologicTreatments:
(ReportNonPharmacologicTreatmentProcedures
union ReportNonPharmacologicTreatmentServiceRequests) M
sort by Date desc
// Stool softeners and laxatives - orders and statements with dates (lookback 6 months)
define StoolSoftenersAndLaxativesRequests:
C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Stool softeners and laxatives"],
6 months
))
define StoolSoftenersAndLaxativesStatements:
C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Stool softeners and laxatives"],
6 months
))
define ReportStoolSoftenersAndLaxativesRequests:
(StoolSoftenersAndLaxativesRequests) O
return {
Type: 'Request',
Name: ConceptText(O.medication as FHIR.CodeableConcept),
Start: DateTimeText(O.authoredOn),
End: null as String, // MedicationRequest end date not supported in R4,
Status: O.status.value
}
sort by Start desc, End desc
define ReportStoolSoftenersAndLaxativesStatements:
(StoolSoftenersAndLaxativesStatements) S
return {
Type: 'Statement',
Name: ConceptText(S.medication as FHIR.CodeableConcept),
Start: MedicationStatementDate(S),
End: DateTimeText((S.effective as FHIR.Period)."end"),
Status: S.status.value
}
sort by Start desc, End desc
define ReportStoolSoftenersAndLaxatives:
(ReportStoolSoftenersAndLaxativesRequests union ReportStoolSoftenersAndLaxativesStatements) M
sort by Start desc, End desc
// RISK CONSIDERATIONS
// MME (MOST RECENT w/ lookback 6 months) - amount and date
define MostRecentMME:
C3F.MostRecent(C3F.Verified(C3F.ObservationLookBack([Observation: "Morphine Milligram Equivalent (MME)"], 6 months)))
define ReportMostRecentMME:
if MostRecentMME is null
then null
else
(MostRecentMME) M
return {
Name: ConceptText(M.code),
Result: QuantityText(M.value as FHIR.Quantity),
Date: ObservationDate(M)
}
// Urine drug screen - dates and results (all screens w/ lookback of 1 year)
define UrineDrugScreens:
C3F.Verified(C3F.ObservationLookBack([Observation: "Urine drug screen for pain management"], 1 year))
define ReportUrineDrugScreens:
(UrineDrugScreens) S
return {
Name: ConceptText(S.code),
Result: Coalesce(
QuantityText(S.value as FHIR.Quantity),
(S.value as FHIR.string).value,
ConceptText(S.value as FHIR.CodeableConcept)
),
Interpretation: ConceptText(First(S.interpretation)),
Date: ObservationDate(S)
}
sort by Date desc
// Benzodiazepine Medications (lookback of 2 years)- orders and statements with dates
define BenzodiazepineMedicationRequests:
C3F.ActiveCompletedOrStoppedMedicationRequest(C3F.MedicationRequestLookBack(
[MedicationRequest: "Benzodiazepine medications"],
2 years
))
define function MedicationStatementLookBack(MedList List<MedicationStatement>, LookBack System.Quantity):
MedList M
let LookBackInterval: Interval[Now() - LookBack, Now()]
where (M.effective as FHIR.dateTime).value in LookBackInterval
or C3F.PeriodToInterval(M.effective as FHIR.Period) overlaps LookBackInterval
define BenzodiazepineMedicationStatements:
C3F.ActiveOrCompletedMedicationStatement(C3F.MedicationStatementLookBack(
[MedicationStatement: "Benzodiazepine medications"],
2 years
))
define ReportBenzodiazepineMedicationRequests:
(BenzodiazepineMedicationRequests) O
return {
Type: 'Request',
Name: ConceptText(O.medication as FHIR.CodeableConcept),
Start: DateTimeText(O.authoredOn),
End: null as String, // MedicationRequest end date not supported in R4,
Status: O.status.value
}
sort by Start desc, End desc
define ReportBenzodiazepineMedicationStatements:
(BenzodiazepineMedicationStatements) S
return {
Type: 'Statement',
Name: ConceptText(S.medication as FHIR.CodeableConcept),
Start: MedicationStatementDate(S),
End: DateTimeText((S.effective as FHIR.Period)."end"),
Status: S.status.value
}
sort by Start desc, End desc
define ReportBenzodiazepineMedications:
(ReportBenzodiazepineMedicationRequests union ReportBenzodiazepineMedicationStatements) M
sort by Start desc, End desc
// Naloxone Medications (unrestricted lookback) - orders and statements with dates