FDBPGController.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Support\Facades\DB;
  5. class FDBPGController extends Controller
  6. {
  7. public function rx(Request $request)
  8. {
  9. return view('app.fdb-pg.fdb-rx');
  10. }
  11. // 1. medication suggest
  12. public function medSuggest(Request $request)
  13. {
  14. $term = $request->input('term') ? trim($request->input('term')) : '';
  15. if (empty($term)) return '';
  16. $matches = DB::connection('pgsql_fdb')->select(
  17. "SELECT med_name_id, med_name FROM rminmid1_med_name WHERE med_status_cd = '0' AND med_name ILIKE :term ORDER BY med_name",
  18. ['term' => '%' . $term . '%']
  19. );
  20. return view('app.fdb-pg.fdb-med-suggest', compact('matches'));
  21. }
  22. // 1.1 medication suggest (json response)
  23. public function medSuggestJSON(Request $request)
  24. {
  25. $term = $request->input('term') ? trim($request->input('term')) : '';
  26. if (empty($term)) return '';
  27. $matches = DB::connection('pgsql_fdb')->select(
  28. "SELECT med_name_id, med_name as text FROM rminmid1_med_name WHERE med_status_cd = '0' AND med_name ILIKE :term ORDER BY med_name",
  29. ['term' => '%' . $term . '%']
  30. );
  31. return json_encode([
  32. "success" => true,
  33. "data" => $matches
  34. ]);
  35. }
  36. // 2. routed meds from men name
  37. public function routedMeds(Request $request)
  38. {
  39. $medNameID = $request->input('med-name-id') ? trim($request->input('med-name-id')) : '';
  40. if (empty($medNameID)) return '';
  41. $matches = DB::connection('pgsql_fdb')->select(
  42. "SELECT routed_med_id, med_routed_med_id_desc FROM rmirmid1_routed_med WHERE med_status_cd = '0' AND med_name_id = :medNameID ORDER BY med_routed_med_id_desc",
  43. ['medNameID' => $medNameID]
  44. );
  45. return json_encode($matches);
  46. }
  47. // 3. routed dosage from routed med
  48. public function routedDosages(Request $request)
  49. {
  50. $routedMedID = $request->input('routed-med-id') ? trim($request->input('routed-med-id')) : '';
  51. if (empty($routedMedID)) return '';
  52. $matches = DB::connection('pgsql_fdb')->select(
  53. "SELECT routed_dosage_form_med_id, med_routed_df_med_id_desc FROM rmidfid1_routed_dose_form_med WHERE med_status_cd = '0' AND routed_med_id = :routedMedID ORDER BY med_routed_df_med_id_desc",
  54. ['routedMedID' => $routedMedID]
  55. );
  56. return json_encode($matches);
  57. }
  58. // 4. strengths from routed med
  59. public function meds(Request $request)
  60. {
  61. $dosageFormMedId = $request->input('dosage-form-med-id') ? trim($request->input('dosage-form-med-id')) : '';
  62. if (empty($dosageFormMedId)) return '';
  63. $matches = DB::connection('pgsql_fdb')->select(
  64. "SELECT medid, med_medid_desc, gcn_seqno FROM rmiid1_med WHERE med_status_cd = '0' AND routed_dosage_form_med_id = :dosageFormMedId ORDER BY med_medid_desc",
  65. ['dosageFormMedId' => $dosageFormMedId]
  66. );
  67. return json_encode($matches);
  68. }
  69. // ** med suggest V2 ** //
  70. public function medSuggestV2JSON(Request $request)
  71. {
  72. $term = $request->input('term') ? trim($request->input('term')) : '';
  73. if (empty($term)) return '';
  74. $matches = DB::connection('pgsql_fdb')->select("
  75. SELECT r_med.medid,
  76. r_med.med_medid_desc as text,
  77. r_med.gcn_seqno,
  78. r_dosage_form.routed_dosage_form_med_id,
  79. r_route.routed_med_id
  80. FROM rmiid1_med r_med
  81. JOIN rmidfid1_routed_dose_form_med r_dosage_form
  82. ON r_med.routed_dosage_form_med_id = r_dosage_form.routed_dosage_form_med_id
  83. JOIN rmirmid1_routed_med r_route ON r_dosage_form.routed_med_id = r_route.routed_med_id
  84. WHERE r_med.med_status_cd = '0'
  85. AND r_med.med_medid_desc ILIKE :term
  86. ORDER BY r_route.med_routed_med_id_desc, r_med.med_medid_desc",
  87. ['term' => '%' . $term . '%']
  88. );
  89. return json_encode([
  90. "success" => true,
  91. "data" => $matches
  92. ]);
  93. }
  94. // side effects for a given rx
  95. public function sideEffects(Request $request)
  96. {
  97. $gcnSeqNo = $request->input('gcn-seq-no') ? trim($request->input('gcn-seq-no')) : '';
  98. if (empty($gcnSeqNo)) return '';
  99. $sides = DB::connection('pgsql_fdb')->select("
  100. SELECT r1.side, sm.side_freq, sm.side_sev, sm.dxid, dx.dxid_desc56
  101. FROM rsidegc0_gcnseqno_link r1
  102. JOIN rsidema3_mstr sm ON r1.side = sm.side
  103. JOIN rfmldx0_dxid dx ON sm.dxid = dx.dxid
  104. WHERE r1.gcn_seqno = :gcnSeqNo
  105. ORDER BY sm.side_sev DESC, sm.side_freq ASC
  106. ",
  107. ['gcnSeqNo' => $gcnSeqNo]
  108. );
  109. return view('app.fdb-pg.fdb-side-effects', compact('sides'));
  110. }
  111. // ger prec for a given rx
  112. public function geriatricPrecautions(Request $request)
  113. {
  114. $gcnSeqNo = $request->input('gcn-seq-no') ? trim($request->input('gcn-seq-no')) : '';
  115. if (empty($gcnSeqNo)) return '';
  116. $precautions = DB::connection('pgsql_fdb')->select("
  117. SELECT r1.geri_code, gm.geri_sl, gm.geri_desc, gm.geri_narrative
  118. FROM rgerigc0_geri_gcnseqno_link r1
  119. JOIN rgerima1_geri_mstr gm ON r1.geri_code = gm.geri_code
  120. WHERE r1.gcn_seqno = :gcnSeqNo
  121. ORDER BY gm.geri_desc
  122. ",
  123. ['gcnSeqNo' => $gcnSeqNo]
  124. );
  125. return view('app.fdb-pg.fdb-geriatric-precautions', compact('precautions'));
  126. }
  127. // indication of a given rx
  128. public function indications(Request $request)
  129. {
  130. $gcnSeqNo = $request->input('gcn-seq-no') ? trim($request->input('gcn-seq-no')) : '';
  131. if (empty($gcnSeqNo)) return '';
  132. $indications = DB::connection('pgsql_fdb')->select("
  133. SELECT r1.indcts, r2.indcts_sn, r2.indcts_lbl, r2.dxid, r2.proxy_ind, r3.dxid_desc56
  134. FROM rindmgc0_indcts_gcnseqno_link r1
  135. JOIN rindmma2_indcts_mstr r2 ON r1.indcts = r2.indcts
  136. JOIN rfmldx0_dxid r3 ON r2.dxid = r3.dxid
  137. WHERE r1.gcn_seqno = :gcnSeqNo
  138. ORDER BY r3.dxid_desc56
  139. ",
  140. ['gcnSeqNo' => $gcnSeqNo]
  141. );
  142. return view('app.fdb-pg.fdb-indications', compact('indications'));
  143. }
  144. // contra-indications of a given rx
  145. public function contraindications(Request $request)
  146. {
  147. $routedMedID = $request->input('routed-med-id') ? trim($request->input('routed-med-id')) : '';
  148. if (empty($routedMedID)) return '';
  149. $contraindications = DB::connection('pgsql_fdb')->select("
  150. SELECT r1.ddxcn, r2.dxid, r2.ddxcn_sl, r3.dxid_desc56
  151. FROM rddcmrm0_routed_med_link r1
  152. JOIN rddcmma1_contra_mstr r2 ON r1.ddxcn = r2.ddxcn
  153. JOIN rfmldx0_dxid r3 ON r2.dxid = r3.dxid
  154. WHERE r1.routed_med_id = :routedMedID
  155. ORDER BY r2.ddxcn_sl
  156. ",
  157. ['routedMedID' => $routedMedID]
  158. );
  159. return view('app.fdb-pg.fdb-contraindications', compact('contraindications'));
  160. }
  161. // dx suggest
  162. public function dxSuggest(Request $request)
  163. {
  164. $term = $request->input('term') ? trim($request->input('term')) : '';
  165. if (empty($term)) return '';
  166. $matches = DB::connection('pgsql_fdb')->select("
  167. SELECT distinct(r1.dxid), r1.dxid_desc56
  168. FROM rfmldx0_dxid r1
  169. JOIN rfmlsyn0_dxid_syn r2 ON r1.dxid = r2.dxid
  170. WHERE (r1.dxid_desc56 ILIKE :term OR r1.dxid_desc100 ILIKE :term OR r2.dxid_syn_desc56 ILIKE :term OR r2.dxid_syn_desc100 ILIKE :term)
  171. ORDER BY r1.dxid_desc56
  172. ",
  173. ['term' => '%' . $term . '%']
  174. );
  175. return view('app.fdb-pg.fdb-dx-suggest', compact('matches'));
  176. }
  177. public function dxSuggestJSON(Request $request)
  178. {
  179. $term = $request->input('term') ? trim($request->input('term')) : '';
  180. if (empty($term)) return '';
  181. $matches = DB::connection('pgsql_fdb')->select("
  182. SELECT distinct(r1.dxid), r1.dxid_desc56 as text
  183. FROM rfmldx0_dxid r1
  184. JOIN rfmlsyn0_dxid_syn r2 ON r1.dxid = r2.dxid
  185. WHERE (r1.dxid_desc56 ILIKE :term OR r1.dxid_desc100 ILIKE :term OR r2.dxid_syn_desc56 ILIKE :term OR r2.dxid_syn_desc100 ILIKE :term)
  186. ORDER BY r1.dxid_desc56
  187. ",
  188. ['term' => '%' . $term . '%']
  189. );
  190. return response()->json(['success'=>true, 'data'=>$matches]);
  191. }
  192. public function dxICDsForDxID(Request $request) {
  193. $matches = DB::connection('pgsql_fdb')->select("
  194. select r1.search_icd_cd, r1.icd_cd_type, r2.icd_desc
  195. from RFMLISR1_ICD_SEARCH r1
  196. left join RFMLINM1_ICD_DESC r2 on r1.search_icd_cd = r2.icd_cd
  197. where r1.related_dxid = :dxid
  198. and (/*r1.icd_cd_type = '01' or */r1.icd_cd_type = '05')
  199. and r1.fml_clin_code = '01'
  200. /*and fml_nav_code = '01'*/
  201. ",
  202. ['dxid' => $request->input('dxid')]
  203. );
  204. return response()->json($matches);
  205. }
  206. // allergy suggest
  207. public function allergySuggest(Request $request)
  208. {
  209. $term = $request->input('term') ? trim($request->input('term')) : '';
  210. if (empty($term)) return '';
  211. $matches = DB::connection('pgsql_fdb')->select("
  212. SELECT r1.dam_concept_id, r1.dam_concept_id_typ, r1.dam_concept_id_desc
  213. FROM rdamca0_concept r1
  214. WHERE (r1.dam_concept_id_desc ILIKE :term)
  215. ORDER BY r1.dam_concept_id_desc
  216. ",
  217. ['term' => '%' . $term . '%']
  218. );
  219. return view('app.fdb-pg.fdb-allergy-suggest', compact('matches'));
  220. }
  221. // allergy suggest (json response)
  222. public function allergySuggestJSON(Request $request)
  223. {
  224. $term = $request->input('term') ? trim($request->input('term')) : '';
  225. if (empty($term)) return '';
  226. $matches = DB::connection('pgsql_fdb')->select("
  227. SELECT r1.dam_concept_id, r1.dam_concept_id_typ, r1.dam_concept_id_desc as text
  228. FROM rdamca0_concept r1
  229. WHERE (r1.dam_concept_id_desc ILIKE :term)
  230. ORDER BY r1.dam_concept_id_desc
  231. ",
  232. ['term' => '%' . $term . '%']
  233. );
  234. return json_encode([
  235. "success" => true,
  236. "data" => $matches
  237. ]);
  238. }
  239. // drug <-> allergy match making
  240. public function drugAllergies(Request $request) {
  241. // override
  242. if($request->input('test')) {
  243. $x = new \stdClass();
  244. $x->allergen = 'Pollen';
  245. $x->dam_concept_id_typ = 6;
  246. $allergies = [$x];
  247. $y = new \stdClass();
  248. $y->rx = 'Brufen';
  249. $rx = [$y];
  250. }
  251. else {
  252. $input = json_decode($request->input('data'));
  253. $allergies = $input->allergies;
  254. $rx = $input->rx;
  255. }
  256. $output = [];
  257. /*
  258. for each allergy
  259. if dam_concept_id_typ = 1 // allergen-group-id
  260. // https://docs.fdbhealth.com/display/MKDOCUS/Screening+an+NDC+for+a+DAM_ALRGN_GRP+Allergen+-+Illustration+of+Scenario+C
  261. ...
  262. elseif dam_concept_id_typ = 2 // medication-name-id
  263. // https://docs.fdbhealth.com/display/MKDOCUS/Screening+an+NDC+for+a+MED_NAME_ID+Allergen+-+Illustration+of+Scenario+B
  264. ...
  265. elseif dam_concept_id_typ = 6 // base-ingredient-id
  266. // https://docs.fdbhealth.com/display/MKDOCUS/Screening+an+NDC+for+an+Ingredient+Allergen+-+Illustration+of+Scenario+A
  267. ...
  268. endif
  269. endfor
  270. */
  271. foreach ($allergies as $allergy) {
  272. foreach ($rx as $rxItem) {
  273. if($allergy->dam_concept_id_typ == 6) { // ingredient
  274. if ($this->drugAllergyIngredientAllergenVsSingleRx($allergy, $rxItem)) {
  275. $output[] = "<b>{$rxItem->rx}</b> can cause allergic reactions since the patient is allergic to <b>{$allergy->allergen}</b>.";
  276. }
  277. }
  278. else if($allergy->dam_concept_id_typ == 2) { // medication
  279. if ($this->drugAllergyMedicationAllergenVsSingleRx($allergy, $rxItem)) {
  280. $output[] = "<b>{$rxItem->rx}</b> can cause allergic reactions since the patient is allergic to <b>{$allergy->allergen}</b>.";
  281. }
  282. }
  283. else if($allergy->dam_concept_id_typ == 1) { // allergen group
  284. if ($this->drugAllergyGroupAllergenVsSingleRx($allergy, $rxItem)) {
  285. $output[] = "<b>{$rxItem->rx}</b> can cause allergic reactions since the patient is allergic to <b>{$allergy->allergen}</b>.";
  286. }
  287. }
  288. }
  289. }
  290. return implode("<br>", $output);
  291. }
  292. private function drugAllergyIngredientAllergenVsSingleRx($_allergen, $_rx) {
  293. $matches = DB::connection('pgsql_fdb')->select("
  294. (
  295. -- ingredients from medication
  296. SELECT R1.related_hic_seqn as hic_seqn, R2.hic_desc
  297. FROM RHICHCR0_HIC_HIC_LINK R1
  298. JOIN RHICD5_HIC_DESC R2 ON R1.related_hic_seqn = R2.hic_seqn
  299. WHERE R1.hic_seqn IN (
  300. SELECT S2.dam_alrgn_hic_seqn
  301. FROM RMEDMHL0_MED_HICLSEQNO_LINK S1
  302. JOIN RDAMHHA0_HIC_HICL_ALG_LINK S2 ON S1.hicl_seqno = S2.hicl_seqno
  303. WHERE S1.med_concept_id = :medid
  304. AND S1.med_concept_id_typ = 3
  305. )
  306. )
  307. INTERSECT
  308. (
  309. -- all ingredients directly and related from allergens
  310. (
  311. SELECT R1.related_hic_seqn as hic_seqn, R2.hic_desc
  312. FROM RHICHCR0_HIC_HIC_LINK R1
  313. JOIN RHICD5_HIC_DESC R2 ON R1.related_hic_seqn = R2.hic_seqn
  314. WHERE R1.hic_seqn = :allergenConceptID
  315. )
  316. UNION
  317. -- all ingredients via related dam allergen groups
  318. (
  319. SELECT r3.hic_seqn, r4.hic_desc
  320. FROM RDAMGHC0_HIC_ALRGN_GRP_LINK R1
  321. JOIN rdamagd1_alrgn_grp_desc R2 on R1.dam_alrgn_grp = R2.dam_alrgn_grp
  322. JOIN RDAMGHC0_HIC_ALRGN_GRP_LINK R3 on R1.dam_alrgn_grp = R3.dam_alrgn_grp
  323. JOIN RHICD5_HIC_DESC R4 on r3.hic_seqn = r4.hic_seqn
  324. WHERE R1.hic_seqn = :allergenConceptID
  325. AND R2.dam_alrgn_grp_status_cd = 0
  326. ORDER BY r3.hic_seqn
  327. )
  328. )
  329. ",
  330. ['medid' => $_rx->medid, 'allergenConceptID' => $_allergen->dam_concept_id]
  331. );
  332. return !!count($matches);
  333. }
  334. private function drugAllergyMedicationAllergenVsSingleRx($_allergen, $_rx) {
  335. $matches = DB::connection('pgsql_fdb')->select("
  336. (
  337. -- ingredients from medication
  338. SELECT R1.related_hic_seqn as hic_seqn
  339. FROM RHICHCR0_HIC_HIC_LINK R1
  340. JOIN RHICD5_HIC_DESC R2 ON R1.related_hic_seqn = R2.hic_seqn
  341. WHERE R1.hic_seqn IN (
  342. SELECT S2.dam_alrgn_hic_seqn
  343. FROM RMEDMHL0_MED_HICLSEQNO_LINK S1
  344. JOIN RDAMHHA0_HIC_HICL_ALG_LINK S2 ON S1.hicl_seqno = S2.hicl_seqno
  345. WHERE S1.med_concept_id = :medid
  346. AND S1.med_concept_id_typ = 3
  347. )
  348. )
  349. INTERSECT
  350. (
  351. -- all ingredients directly and related from allergens
  352. SELECT R1.dam_alrgn_hic_seqn as hic_seqn
  353. FROM RDAMHHA0_HIC_HICL_ALG_LINK R1
  354. WHERE R1.hicl_seqno IN (
  355. SELECT R1.hicl_seqno
  356. FROM RMEDMHL0_MED_HICLSEQNO_LINK R1
  357. WHERE R1.med_concept_id_typ = 1
  358. AND R1.med_concept_id = :allergenConceptID
  359. AND MED_CONCEPT_HICL_SRC_CD = 0
  360. )
  361. )
  362. ",
  363. ['medid' => $_rx->medid, 'allergenConceptID' => $_allergen->dam_concept_id]
  364. );
  365. return !!count($matches);
  366. }
  367. private function drugAllergyGroupAllergenVsSingleRx($_allergen, $_rx) {
  368. $matches = DB::connection('pgsql_fdb')->select("
  369. (
  370. -- ingredients from medication
  371. SELECT R1.related_hic_seqn as hic_seqn
  372. FROM RHICHCR0_HIC_HIC_LINK R1
  373. JOIN RHICD5_HIC_DESC R2 ON R1.related_hic_seqn = R2.hic_seqn
  374. WHERE R1.hic_seqn IN (
  375. SELECT S2.dam_alrgn_hic_seqn
  376. FROM RMEDMHL0_MED_HICLSEQNO_LINK S1
  377. JOIN RDAMHHA0_HIC_HICL_ALG_LINK S2 ON S1.hicl_seqno = S2.hicl_seqno
  378. WHERE S1.med_concept_id = :medid
  379. AND S1.med_concept_id_typ = 3
  380. )
  381. )
  382. INTERSECT
  383. (
  384. -- ingredients from medication allergen
  385. (
  386. SELECT R1.hic_seqn as hic_seqn
  387. FROM RDAMGHC0_HIC_ALRGN_GRP_LINK R1
  388. WHERE R1.DAM_ALRGN_GRP = :allergenConceptID
  389. )
  390. UNION
  391. (
  392. SELECT distinct s1.hic_seqn
  393. FROM RDAMXHC0_HIC_ALRGN_XSENSE_LINK S1
  394. WHERE S1.dam_alrgn_xsense IN (
  395. SELECT R1.dam_alrgn_xsense
  396. FROM RDAMGX0_ALRGN_GRP_XSENSE_LINK R1
  397. JOIN RDAMCSD1_XSENSIT_ALLERGY_DESC R2 on R1.dam_alrgn_xsense = R2.dam_alrgn_xsense
  398. WHERE R1.dam_alrgn_grp = :allergenConceptID
  399. AND R2.dam_alrgn_xsense_status_cd = 0
  400. )
  401. )
  402. )
  403. ",
  404. ['medid' => $_rx->medid, 'allergenConceptID' => $_allergen->dam_concept_id]
  405. );
  406. return !!count($matches);
  407. }
  408. // drug <-> drug match making
  409. public function drugDrugInteraction(Request $request) {
  410. if($request->input('test')) {
  411. // override
  412. $rx = json_decode(json_encode([
  413. [
  414. "gcn_seqno" => "45190",
  415. "med_name_id" => "18604",
  416. "medid" => "234539",
  417. "routed_dosage_form_med_id" => "95130",
  418. "routed_med_id" => "19876",
  419. "rx" => "Zyprexa Zydis",
  420. ],
  421. [
  422. "gcn_seqno" => "49853",
  423. "med_name_id" => "26164",
  424. "medid" => "400058",
  425. "routed_dosage_form_med_id" => "36194",
  426. "routed_med_id" => "32562",
  427. "rx" => "Orfadin",
  428. ],
  429. ]));
  430. }
  431. else {
  432. $input = json_decode($request->input('data'));
  433. $rx = $input->rx;
  434. }
  435. if(count($rx) < 2) return "";
  436. $leftIndex = 0;
  437. $output = [];
  438. for ($i=$leftIndex; $i<count($rx) - 1; $i++) {
  439. for ($j=$i + 1; $j<count($rx); $j++) {
  440. $output[] = $this->drugDrugInteractionSinglePair($rx[$i], $rx[$j]);
  441. }
  442. }
  443. $output = array_filter($output, function($_x) {
  444. return !!$_x;
  445. });
  446. return implode("<br>", $output);
  447. }
  448. private function drugDrugInteractionSinglePair($_rx1, $_rx2) {
  449. $output = [];
  450. // get active ingredient DDI_CODEX values for drug 1 and 2
  451. $rx1ActiveDdiCodex = $this->getActiveDdiCodexFromGcnSeqNo($_rx1->gcn_seqno);
  452. $rx2ActiveDdiCodex = $this->getActiveDdiCodexFromGcnSeqNo($_rx2->gcn_seqno);
  453. if(!$rx1ActiveDdiCodex || !$rx2ActiveDdiCodex || !count($rx1ActiveDdiCodex) || !count($rx2ActiveDdiCodex)) return "";
  454. // dump($rx1_DDI_CODEX);
  455. // dump($rx2_DDI_CODEX);
  456. // get inactive ingredient DDI_CODEX values for drug 1 and 2
  457. // to get this we need to first get the NDCs of the drugs
  458. $rx1Ndc = $this->getNdcFromMedId($_rx1->medid);
  459. $rx2Ndc = $this->getNdcFromMedId($_rx2->medid);
  460. // dump($rx1Ndc);
  461. // dump($rx2Ndc);
  462. $rx1InactiveDdiCodex = $this->getInactiveDdiCodexFromNdc($rx1Ndc);
  463. $rx2InactiveDdiCodex = $this->getInactiveDdiCodexFromNdc($rx2Ndc);
  464. // if(!$rx1InactiveDdiCodex || !$rx2InactiveDdiCodex || !count($rx1InactiveDdiCodex) || !count($rx2InactiveDdiCodex)) return "";
  465. // dump($rx1InactiveDdiCodex);
  466. // dump($rx2InactiveDdiCodex);
  467. // get ddi codex - monox pairs for drug 1 & 2
  468. $rx1ActiveDdiCodexMonoxPairs = $this->getDdiCodexMonoxPairs($rx1ActiveDdiCodex);
  469. $rx1InactiveDdiCodexMonoxPairs = $this->getDdiCodexMonoxPairs($rx1InactiveDdiCodex);
  470. $rx2ActiveDdiCodexMonoxPairs = $this->getDdiCodexMonoxPairs($rx2ActiveDdiCodex);
  471. $rx2InactiveDdiCodexMonoxPairs = $this->getDdiCodexMonoxPairs($rx2InactiveDdiCodex);
  472. // dump($rx1ActiveDdiCodexMonoxPairs);
  473. // dump($rx1InactiveDdiCodexMonoxPairs);
  474. // dump($rx2ActiveDdiCodexMonoxPairs);
  475. // dump($rx2InactiveDdiCodexMonoxPairs);
  476. // compare 1-active to 2-active and 2-inactive
  477. $activeCatches = [];
  478. foreach ($rx1ActiveDdiCodexMonoxPairs as $compareLeft) {
  479. foreach ($rx2ActiveDdiCodexMonoxPairs as $compareRight) {
  480. if($compareLeft->ddi_monox == $compareRight->ddi_monox && $compareLeft->ddi_codex != $compareRight->ddi_codex) {
  481. $activeCatches[] = $compareLeft->ddi_codex;
  482. }
  483. }
  484. foreach ($rx2InactiveDdiCodexMonoxPairs as $compareRight) {
  485. if($compareLeft->ddi_monox == $compareRight->ddi_monox && $compareLeft->ddi_codex != $compareRight->ddi_codex) {
  486. $activeCatches[] = $compareLeft->ddi_codex;
  487. }
  488. }
  489. }
  490. // compare 1-inactive to 2-active and 2-inactive
  491. $inactiveCatches = [];
  492. foreach ($rx1InactiveDdiCodexMonoxPairs as $compareLeft) {
  493. foreach ($rx2ActiveDdiCodexMonoxPairs as $compareRight) {
  494. if($compareLeft->ddi_monox == $compareRight->ddi_monox && $compareLeft->ddi_codex != $compareRight->ddi_codex) {
  495. $inactiveCatches[] = $compareLeft->ddi_codex;
  496. }
  497. }
  498. foreach ($rx2InactiveDdiCodexMonoxPairs as $compareRight) {
  499. if($compareLeft->ddi_monox == $compareRight->ddi_monox && $compareLeft->ddi_codex != $compareRight->ddi_codex) {
  500. $inactiveCatches[] = $compareLeft->ddi_codex;
  501. }
  502. }
  503. }
  504. if(count($activeCatches)) {
  505. $output[] = "<b>{$_rx2->rx}</b> interacts with one or more active ingredients in <b>{$_rx1->rx}</b>.";
  506. }
  507. if(count($inactiveCatches)) {
  508. $output[] = "<b>{$_rx2->rx}</b> interacts with one or more inactive ingredients in <b>{$_rx1->rx}</b>.";
  509. }
  510. // TODO: find out and show the names of the actual ingredients causing interaction
  511. return implode("<br>", $output);
  512. }
  513. private function getActiveDdiCodexFromGcnSeqNo($_gcnSeqNo) {
  514. $ddiCodexArray = [];
  515. $query = DB::connection('pgsql_fdb')->select("
  516. SELECT r1.ddi_codex
  517. FROM RADIMGC4_GCNSEQNO_LINK r1
  518. WHERE r1.gcn_seqno = :gcnSeqNo
  519. ",
  520. ['gcnSeqNo' => $_gcnSeqNo]
  521. );
  522. if(count($query)) {
  523. $ddiCodexArray = array_map(function($_x) {
  524. return $_x->ddi_codex;
  525. }, $query);
  526. }
  527. return $ddiCodexArray;
  528. }
  529. private function getNdcFromMedId($_medId) {
  530. $ndcArray = [];
  531. $query = DB::connection('pgsql_fdb')->select("
  532. select ndc from rmindc1_ndc_medid where medid = :medId
  533. ",
  534. ['medId' => $_medId]
  535. );
  536. if(count($query)) {
  537. $ndcArray = array_map(function($_x) {
  538. return $_x->ndc;
  539. }, $query);
  540. }
  541. return $ndcArray;
  542. }
  543. private function getInactiveDdiCodexFromNdc($_ndc) {
  544. $ddiCodexArray = [];
  545. $query = DB::connection('pgsql_fdb')->select("
  546. SELECT distinct r1.ddi_codex
  547. FROM RDDIMIN0_NDC_INACTV_DDIM_LINK r1
  548. WHERE r1.ddi_ndc IN (" . implode(',', array_map(function($_x) {return "'" . $_x . "'";}, $_ndc)) . ")
  549. "
  550. );
  551. if(count($query)) {
  552. $ddiCodexArray = array_map(function($_x) {
  553. return $_x->ddi_codex;
  554. }, $query);
  555. }
  556. return $ddiCodexArray;
  557. }
  558. private function getDdiCodexMonoxPairs($_ddiCodexArray) {
  559. $ddiCodexMonoxPairsArray = [];
  560. if(count($_ddiCodexArray)) {
  561. $ddiCodexMonoxPairsArray = DB::connection('pgsql_fdb')->select("
  562. SELECT r1.ddi_codex, r1.ddi_monox
  563. FROM RADIMMA5_MSTR r1
  564. WHERE r1.ddi_codex IN (" . implode(',', array_map(function($_x) {return "'" . $_x . "'";}, $_ddiCodexArray)) . ")
  565. "
  566. );
  567. }
  568. return $ddiCodexMonoxPairsArray;
  569. }
  570. // drug <-> drug coadministration notes
  571. public function drugCoadministration(Request $request) {
  572. $gcnSeqnos = $request->input('gcn-seqnos') ? trim($request->input('gcn-seqnos')) : '';
  573. if (empty($gcnSeqnos)) return '';
  574. //$gcnSeqnos = explode(",", $gcnSeqnos);
  575. $coadministration = DB::connection('pgsql_fdb')->select("
  576. SELECT distinct r1.coadmin_dosing_text
  577. FROM radige0_ddi_gcnseqno_except r1
  578. WHERE r1.side_a_gcn_seqno in ($gcnSeqnos) AND r1.side_b_gcn_seqno in ($gcnSeqnos)
  579. "
  580. );
  581. return view('app.fdb-pg.fdb-coadministration', compact('coadministration'));
  582. }
  583. // duplicate therapy indications
  584. public function duplicateTherapy(Request $request) {
  585. if($request->input('test')) {
  586. // override
  587. $rx = json_decode(json_encode([
  588. [
  589. "gcn_seqno" => "4376",
  590. "med_name_id" => "1076",
  591. "medid" => "172480",
  592. "routed_dosage_form_med_id" => "5870",
  593. "routed_med_id" => "1082",
  594. "rx" => "aspirin 325",
  595. ],
  596. [
  597. "gcn_seqno" => "4377",
  598. "med_name_id" => "1076",
  599. "medid" => "216092",
  600. "routed_dosage_form_med_id" => "5870",
  601. "routed_med_id" => "1082",
  602. "rx" => "aspirin 500",
  603. ],
  604. ]));
  605. }
  606. else {
  607. $input = json_decode($request->input('data'));
  608. $rx = $input->rx;
  609. }
  610. $dptClasses = [];
  611. foreach ($rx as $rxItem) {
  612. $rxItem->dpt = $this->getDptClassFromGcnSeqNo($rxItem->gcn_seqno);
  613. }
  614. // dd($rx);
  615. $leftIndex = 0;
  616. $matches = [];
  617. for ($i=$leftIndex; $i<count($rx) - 1; $i++) {
  618. for ($j=$i + 1; $j<count($rx); $j++) {
  619. $compareResult = $this->compareDPTs($rx[$i]->dpt, $rx[$j]->dpt);
  620. foreach ($compareResult as $c) {
  621. $matches[] = "<b>{$rx[$i]->rx}</b> and <b>{$rx[$j]->rx}</b> both participate in the duplicate therapy class <b>{$c->dpt_class_desc}</b> (duplicates allowed: {$c->dpt_allowance})";
  622. }
  623. }
  624. }
  625. return "<ol class='pl-0 ml-3'>" . implode("", array_map(function($_x) {
  626. return "<li class='mb-2'>" . $_x . "</li>";
  627. }, $matches)) . "</ol>";
  628. }
  629. private function getDptClassFromGcnSeqNo($_gcnSeqNo) {
  630. return DB::connection('pgsql_fdb')->select("
  631. SELECT distinct r1.dpt_class_id, r2.dpt_allowance, r2.dpt_class_desc
  632. FROM RDPTGC0_GCNSEQNO_LINK r1
  633. JOIN RDPTCL0_CLASS_ID r2 on r1.dpt_class_id = r2.dpt_class_id
  634. WHERE r1.gcn_seqno = :gcnSeqNo
  635. ",
  636. ['gcnSeqNo' => $_gcnSeqNo]
  637. );
  638. }
  639. private function compareDPTs($_dptArray1, $_dptArray2) {
  640. $output = [];
  641. for ($i=0; $i<count($_dptArray1); $i++) {
  642. for ($j=0; $j<count($_dptArray2); $j++) {
  643. if($_dptArray1[$i]->dpt_class_id == $_dptArray2[$j]->dpt_class_id) {
  644. $output[] = json_decode(json_encode([
  645. "dpt_allowance" => $_dptArray1[$i]->dpt_allowance,
  646. "dpt_class_desc" => $_dptArray1[$i]->dpt_class_desc
  647. ]));
  648. }
  649. }
  650. }
  651. return $output;
  652. }
  653. }