FDBPGController.php 26 KB

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