PracticeManagementController.php 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\AppSession;
  4. use App\Models\ClaimEDI;
  5. use App\Models\Measurement;
  6. use App\Models\Bill;
  7. use App\Models\Claim;
  8. use App\Models\Client;
  9. use App\Models\McpRequest;
  10. use App\Models\Note;
  11. use App\Models\Pack;
  12. use App\Models\Pro;
  13. use App\Models\Product;
  14. use App\Models\ProFavorite;
  15. use App\Models\ProGeneralAvailability;
  16. use App\Models\ProProAccess;
  17. use App\Models\ProRate;
  18. use App\Models\ProSpecificAvailability;
  19. use App\Models\ProSpecificUnavailability;
  20. use App\Models\ProTextShortcut;
  21. use App\Models\ProTransaction;
  22. use App\Models\Shipment;
  23. use App\Models\SupplyOrder;
  24. use App\Models\Ticket;
  25. use Illuminate\Support\Facades\DB;
  26. use Illuminate\Support\Facades\Http;
  27. use PDF;
  28. use DateTime;
  29. use DateTimeZone;
  30. use Illuminate\Http\Request;
  31. class PracticeManagementController extends Controller
  32. {
  33. public function dashboard(Request $request)
  34. {
  35. return view('app.practice-management.dashboard');
  36. }
  37. public function rates(Request $request, $selectedProUid = 'all')
  38. {
  39. $proUid = $selectedProUid ? $selectedProUid : 'all';
  40. $rates = ProRate::where('is_active', true);
  41. if ($proUid !== 'all') {
  42. $selectedPro = Pro::where('uid', $proUid)->first();
  43. $rates = $rates->where('pro_id', $selectedPro->id);
  44. }
  45. $rates = $rates->orderBy('pro_id', 'asc')->get();
  46. $pros = $this->pros;
  47. return view('app.practice-management.rates', compact('rates', 'pros', 'selectedProUid'));
  48. }
  49. public function previousBills(Request $request)
  50. {
  51. return view('app.practice-management.previous-bills');
  52. }
  53. public function financialTransactions(Request $request)
  54. {
  55. $transactions = ProTransaction::where('pro_id', $this->performer()->pro->id)->orderBy('created_at', 'desc')->get();
  56. return view('app.practice-management.financial-transactions', compact('transactions'));
  57. }
  58. public function pendingBillsToSign(Request $request)
  59. {
  60. return view('app.practice-management.pending-bills-to-sign');
  61. }
  62. public function HR(Request $request)
  63. {
  64. return view('app.practice-management.hr');
  65. }
  66. public function directDepositSettings(Request $request)
  67. {
  68. return view('app.practice-management.direct-deposit-settings');
  69. }
  70. public function w9(Request $request)
  71. {
  72. return view('app.practice-management.w9');
  73. }
  74. public function contract(Request $request)
  75. {
  76. return view('app.practice-management.contract');
  77. }
  78. public function notes(Request $request, $filter = '')
  79. {
  80. $proID = $this->performer()->pro->id;
  81. $query = Note::where('hcp_pro_id', $proID);
  82. switch ($filter) {
  83. case 'not-yet-signed':
  84. $query = $query->where('is_signed_by_hcp', false);
  85. break;
  86. // more cases can be added as needed
  87. default:
  88. break;
  89. }
  90. $notes = $query->orderBy('created_at', 'desc')->get();
  91. return view('app.practice-management.notes', compact('notes', 'filter'));
  92. }
  93. public function bills(Request $request, $filter = '')
  94. {
  95. $proID = $this->performer()->pro->id;
  96. $query = Bill::where('is_cancelled', false);
  97. switch ($filter) {
  98. case 'not-yet-signed':
  99. $query = $query
  100. ->where(function ($q) use ($proID) {
  101. $q->where(function ($q2) use ($proID) {
  102. $q2->where('hcp_pro_id', $proID)->where('is_signed_by_hcp', false);
  103. })
  104. ->orWhere(function ($q2) use ($proID) {
  105. $q2->where('cm_pro_id', $proID)->where('is_signed_by_cm', false);
  106. })
  107. ->orWhere(function ($q2) use ($proID) {
  108. $q2->where('rme_pro_id', $proID)->where('is_signed_by_rme', false);
  109. })
  110. ->orWhere(function ($q2) use ($proID) {
  111. $q2->where('rmm_pro_id', $proID)->where('is_signed_by_rmm', false);
  112. });
  113. });
  114. break;
  115. case 'previous':
  116. $query = $query
  117. ->where(function ($q) use ($proID) {
  118. $q->where(function ($q2) use ($proID) {
  119. $q2->where('hcp_pro_id', $proID)->where('is_signed_by_hcp', true);
  120. })
  121. ->orWhere(function ($q2) use ($proID) {
  122. $q2->where('cm_pro_id', $proID)->where('is_signed_by_cm', true);
  123. })
  124. ->orWhere(function ($q2) use ($proID) {
  125. $q2->where('rme_pro_id', $proID)->where('is_signed_by_rme', true);
  126. })
  127. ->orWhere(function ($q2) use ($proID) {
  128. $q2->where('rmm_pro_id', $proID)->where('is_signed_by_rmm', true);
  129. });
  130. });
  131. break;
  132. // more cases can be added as needed
  133. default:
  134. break;
  135. }
  136. $bills = $query->orderBy('created_at', 'desc')->get();
  137. return view('app.practice-management.bills', compact('bills', 'filter'));
  138. }
  139. public function unacknowledgedCancelledBills(Request $request)
  140. {
  141. $bills = Bill::where('hcp_pro_id', $this->performer()->pro->id)
  142. ->where('is_cancelled', true)
  143. ->where('is_cancellation_acknowledged', false)
  144. ->orderBy('created_at', 'desc')
  145. ->get();
  146. return view('app.practice-management.unacknowledged-cancelled-bills', compact('bills'));
  147. }
  148. public function myTickets(Request $request, $filter = 'open')
  149. {
  150. $performer = $this->performer();
  151. $myTickets = Ticket::where(function ($q) use ($performer) {
  152. $q->where('assigned_pro_id', $performer->pro_id)
  153. ->orWhere('manager_pro_id', $performer->pro_id)
  154. ->orWhere('ordering_pro_id', $performer->pro_id)
  155. ->orWhere('initiating_pro_id', $performer->pro_id);
  156. });
  157. if ($filter === 'open') {
  158. $myTickets = $myTickets->where('is_open', true);
  159. } else if ($filter === 'closed') {
  160. $myTickets = $myTickets->where('is_open', false);
  161. }
  162. $myTickets = $myTickets->orderBy('created_at', 'desc')->get();
  163. return view('app.practice-management.my-tickets', compact('myTickets', 'filter'));
  164. }
  165. public function myTextShortcuts(Request $request)
  166. {
  167. $performer = $this->performer();
  168. $myTextShortcuts = ProTextShortcut::where('pro_id', $performer->pro_id)->where('is_removed', false)->get();
  169. return view('app.practice-management.my-text-shortcuts', compact('myTextShortcuts'));
  170. }
  171. public function myFavorites(Request $request, $filter = 'all')
  172. {
  173. $performer = $this->performer();
  174. $myFavorites = ProFavorite::where('pro_id', $performer->pro_id)
  175. ->where('is_removed', false);
  176. if ($filter !== 'all') {
  177. $myFavorites = $myFavorites->where('category', $filter);
  178. }
  179. $myFavorites = $myFavorites
  180. ->orderBy('category', 'asc')
  181. ->orderBy('position_index', 'asc')
  182. ->get();
  183. return view('app.practice-management.my-favorites', compact('myFavorites', 'filter'));
  184. }
  185. public function proAvailability(Request $request, $proUid = null)
  186. {
  187. $performer = $this->performer();
  188. $pro = $performer->pro;
  189. if ($proUid) {
  190. $pro = Pro::where('uid', $proUid)->first();
  191. }
  192. if ($request->get('pro_uid')) {
  193. $proUid = $request->get('pro_uid');
  194. $pro = Pro::where('uid', $proUid)->first();
  195. }
  196. $selectedProUid = $pro->uid;
  197. $pros = $this->pros;
  198. $generalAvailabilitiesList = ProGeneralAvailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('created_at', 'asc')->get();
  199. $generalAvailabilities = [
  200. 'MONDAY' => [],
  201. 'TUESDAY' => [],
  202. 'WEDNESDAY' => [],
  203. 'THURSDAY' => [],
  204. 'FRIDAY' => [],
  205. 'SATURDAY' => [],
  206. 'SUNDAY' => [],
  207. ];
  208. foreach ($generalAvailabilitiesList as $ga) {
  209. if ($ga->day_of_week == 'MONDAY') {
  210. $generalAvailabilities['MONDAY'][] = $ga;
  211. }
  212. if ($ga->day_of_week == 'TUESDAY') {
  213. $generalAvailabilities['TUESDAY'][] = $ga;
  214. }
  215. if ($ga->day_of_week == 'WEDNESDAY') {
  216. $generalAvailabilities['WEDNESDAY'][] = $ga;
  217. }
  218. if ($ga->day_of_week == 'THURSDAY') {
  219. $generalAvailabilities['THURSDAY'][] = $ga;
  220. }
  221. if ($ga->day_of_week == 'FRIDAY') {
  222. $generalAvailabilities['FRIDAY'][] = $ga;
  223. }
  224. if ($ga->day_of_week == 'SATURDAY') {
  225. $generalAvailabilities['SATURDAY'][] = $ga;
  226. }
  227. if ($ga->day_of_week == 'SUNDAY') {
  228. $generalAvailabilities['SUNDAY'][] = $ga;
  229. }
  230. }
  231. $specificAvailabilities = ProSpecificAvailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('start_time')->get();
  232. $specificUnavailabilities = ProSpecificUnavailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('start_time', 'asc')->get();
  233. //events for the calendar
  234. $startDate = date('Y-m-d', strtotime("sunday -1 week"));
  235. $endDateTime = new DateTime($startDate);
  236. $endDateTime->modify('+6 day');
  237. $endDate = $endDateTime->format("Y-m-d");
  238. $eventsData = $pro->getAvailabilityEvents($startDate, $endDate);
  239. $events = json_encode($eventsData);
  240. return view(
  241. 'app.practice-management.pro-availability',
  242. compact(
  243. 'pros',
  244. 'generalAvailabilities',
  245. 'specificAvailabilities',
  246. 'specificUnavailabilities',
  247. 'events',
  248. 'selectedProUid'
  249. )
  250. );
  251. }
  252. public function loadAvailability(Request $request, $proUid)
  253. {
  254. $performer = $this->performer();
  255. $pro = $performer->pro;
  256. $startDate = $request->get('start');
  257. $endDate = $request->get('end');
  258. $selectedPro = Pro::where('uid', $proUid)->first();
  259. return $selectedPro->getAvailabilityEvents($startDate, $endDate);
  260. }
  261. public function proAvailabilityFilter(Request $request)
  262. {
  263. $proUid = $request->get('proUid');
  264. return ['success' => true, 'data' => $proUid];
  265. }
  266. // video call page (RHS)
  267. // generic call handle (no uid)
  268. // specific call handle (uid of client)
  269. public function meet(Request $request, $uid = false)
  270. {
  271. $session = AppSession::where('session_key', $request->cookie('sessionKey'))->first();
  272. $client = !empty($uid) ? Client::where('uid', $uid)->first() : null;
  273. if (!empty($client)) {
  274. return view('app.video.call-minimal', compact('session', 'client'));
  275. }
  276. return view('app.video.call-agora-v2', compact('session', 'client'));
  277. }
  278. // check video page
  279. public function checkVideo(Request $request, $uid)
  280. {
  281. $session = AppSession::where('session_key', $request->cookie('sessionKey'))->first();
  282. $client = !empty($uid) ? Client::where('uid', $uid)->first() : null;
  283. $publish = false;
  284. return view('app.video.check-video-minimal', compact('session', 'client'));
  285. }
  286. public function getParticipantInfo(Request $request)
  287. {
  288. $sid = intval($request->get('uid')) - 1000000;
  289. $session = AppSession::where('id', $sid)->first();
  290. $result = [
  291. "type" => '',
  292. "name" => ''
  293. ];
  294. if ($session) {
  295. $result["type"] = $session->session_type;
  296. switch ($session->session_type) {
  297. case 'PRO':
  298. $pro = Pro::where('id', $session->pro_id)->first();
  299. $result["name"] = $pro->displayName();
  300. break;
  301. case 'CLIENT':
  302. $client = Client::where('id', $session->client_id)->first();
  303. $result["name"] = $client->displayName();
  304. break;
  305. }
  306. }
  307. return json_encode($result);
  308. }
  309. // ajax ep used by the video page
  310. // this is needed bcoz meet() is used not
  311. // just for the client passed to the view
  312. public function getOpentokSessionKey(Request $request, $uid)
  313. {
  314. $client = Client::where('uid', $uid)->first();
  315. return json_encode(["data" => $client ? $client->opentok_session_id : '']);
  316. }
  317. // poll to check if there are patients with active mcp requests
  318. public function getPatientsInQueue(Request $request)
  319. {
  320. $myInitiatives = $this->performer->pro->initiatives;
  321. if ($myInitiatives) {
  322. $myInitiatives = strtoupper($myInitiatives);
  323. }
  324. $myInitiativesList = explode('|', $myInitiatives);
  325. $myForeignLanguages = $this->performer->pro->foreign_languages;
  326. if ($myForeignLanguages) {
  327. $myForeignLanguages = strtoupper($myForeignLanguages);
  328. }
  329. $myForeignLanguagesList = explode('|', $myForeignLanguages);
  330. $clients = Client::whereNotNull('active_mcp_request_id')->where(function ($query) use ($myInitiativesList) {
  331. $query->whereNull('initiative')->orWhereIn('initiative', $myInitiativesList);
  332. })
  333. ->where(function ($query) use ($myForeignLanguagesList) {
  334. $query->whereNull('preferred_foreign_language')->orWhereIn('preferred_foreign_language', $myForeignLanguagesList);
  335. })->limit(3)->get();
  336. $results = [];
  337. foreach ($clients as $client) {
  338. $results[] = [
  339. 'clientUid' => $client->uid,
  340. 'name' => $client->displayName(),
  341. 'initials' => substr($client->name_first, 0, 1) . substr($client->name_last, 0, 1)
  342. ];
  343. }
  344. return json_encode($results);
  345. }
  346. public function currentWork(Request $request)
  347. {
  348. return view('app/current-work');
  349. }
  350. public function calendar(Request $request, $proUid = null)
  351. {
  352. $pros = Pro::all();
  353. if ($this->pro && $this->pro->pro_type != 'ADMIN') {
  354. $accessiblePros = ProProAccess::where('owner_pro_id', $this->pro->id);
  355. $accessibleProIds = [];
  356. foreach ($accessiblePros as $accessiblePro) {
  357. $accessibleProIds[] = $accessiblePro->id;
  358. }
  359. $accessibleProIds[] = $this->pro->id;
  360. $pros = Pro::whereIn('id', $accessibleProIds)->get();
  361. }
  362. return view('app.practice-management.calendar', compact('pros'));
  363. }
  364. public function cellularDeviceManager(Request $request, $proUid = null)
  365. {
  366. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  367. $performerPro = $this->performer->pro;
  368. $targetPro = null;
  369. $allPros = [];
  370. $expectedForHcp = null;
  371. if ($performerPro->pro_type == 'ADMIN') {
  372. $allPros = Pro::all();
  373. $targetPro = Pro::where('uid', $proUid)->first();
  374. } else {
  375. $targetPro = $performerPro;
  376. }
  377. $clients = [];
  378. if ($targetPro) {
  379. $clients = Client::where('mcp_pro_id', $targetPro->id)->orderBy('created_at', 'desc')->paginate(100);
  380. } else {
  381. $clients = Client::orderBy('created_at', 'desc')->paginate(100);
  382. }
  383. return view('app.practice-management.cellular-device-manager', compact('clients', 'allPros', 'targetPro', 'proUid'));
  384. }
  385. public function treatmentServiceUtil(Request $request)
  386. {
  387. $view_treatment_service_utilization_org = DB::select(DB::raw("SELECT * FROM view_treatment_service_utilization_org ORDER BY effective_date DESC"));
  388. $view_treatment_service_utilization = DB::select(DB::raw("SELECT * FROM view_treatment_service_utilization ORDER BY effective_date DESC, total_hrs DESC"));
  389. $view_treatment_service_utilization_by_patient = DB::select(DB::raw("SELECT * FROM view_treatment_service_utilization_by_patient ORDER BY pro_lname ASC, pro_fname ASC, hcp_pro_id ASC, total_hrs DESC"));
  390. return view('app.practice-management.treatment-services-util', compact(
  391. 'view_treatment_service_utilization_org',
  392. 'view_treatment_service_utilization',
  393. 'view_treatment_service_utilization_by_patient'));
  394. }
  395. public function processingBillMatrix(Request $request, $proUid = null)
  396. {
  397. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  398. $performerPro = $this->performer->pro;
  399. $targetPro = null;
  400. $allPros = [];
  401. if ($performerPro->pro_type == 'ADMIN') {
  402. $allPros = Pro::all();
  403. $targetPro = Pro::where('uid', $proUid)->first();
  404. } else {
  405. $targetPro = $performerPro;
  406. }
  407. $bills = [];
  408. if ($targetPro) {
  409. $bills = Bill::where('hcp_pro_id', $targetPro->id)->
  410. where('has_hcp_been_paid', false)->
  411. where('is_cancelled', false)->
  412. where('is_signed_by_hcp', true)->
  413. orderBy('effective_date', 'desc')->paginate();
  414. } else {
  415. $bills = Bill::where('has_hcp_been_paid', false)->
  416. where('is_cancelled', false)->
  417. where('is_signed_by_hcp', true)->
  418. orderBy('effective_date', 'desc')->
  419. paginate();
  420. }
  421. $viewData = [
  422. 'bills' => $bills,
  423. 'allPros' => $allPros,
  424. 'targetPro' => $targetPro,
  425. 'performerPro' => $performerPro,
  426. 'proUid' => $proUid
  427. ];
  428. return view('app.practice-management.processing-bill-matrix', $viewData);
  429. }
  430. public function hcpBillMatrix(Request $request, $proUid = null)
  431. {
  432. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  433. $performerPro = $this->performer->pro;
  434. $targetPro = null;
  435. $allPros = [];
  436. $expectedForHcp = null;
  437. if ($performerPro->pro_type == 'ADMIN') {
  438. $allPros = Pro::all();
  439. $targetPro = Pro::where('uid', $proUid)->first();
  440. } else {
  441. $targetPro = $performerPro;
  442. }
  443. $rows = [];
  444. if ($targetPro) {
  445. $rows = DB::select(DB::raw("SELECT * FROM aemish_bill_report WHERE hcp_pro_id = :targetProID"), ['targetProID' => $targetPro->id]);
  446. } else {
  447. $rows = DB::select(DB::raw("SELECT * FROM aemish_bill_report"));
  448. }
  449. return view('app.practice-management.hcp-bill-matrix', compact('rows', 'allPros', 'expectedForHcp', 'targetPro', 'proUid'));
  450. }
  451. public function billingManager(Request $request, $proUid = null)
  452. {
  453. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  454. $performerPro = $this->performer->pro;
  455. $targetPro = null;
  456. $allPros = [];
  457. $expectedForHcp = null;
  458. if ($performerPro->pro_type == 'ADMIN') {
  459. $allPros = Pro::all();
  460. $targetPro = Pro::where('uid', $proUid)->first();
  461. } else {
  462. $targetPro = $performerPro;
  463. }
  464. $notes = [];
  465. if ($targetPro) {
  466. $expectedForHcp = DB::select(DB::raw("SELECT coalesce(SUM(hcp_expected_payment_amount),0) as expected_pay FROM bill WHERE hcp_pro_id = :targetProID AND is_signed_by_hcp IS TRUE AND is_cancelled = false"), ['targetProID' => $targetPro->id])[0]->expected_pay;
  467. $notes = Note::where('hcp_pro_id', $targetPro->id);
  468. } else {
  469. $notes = Note::where('id', '>', 0);
  470. }
  471. $filters = [];
  472. $filters['bills_created'] = $request->input('bills_created');
  473. $filters['is_billing_marked_done'] = $request->input('is_billing_marked_done');
  474. $filters['bills_resolved'] = $request->input('bills_resolved');
  475. $filters['bills_closed'] = $request->input('bills_closed');
  476. $filters['claims_created'] = $request->input('claims_created');
  477. $filters['claims_closed'] = $request->input('claims_closed');
  478. if ($filters['bills_created']) {
  479. $notes->where(
  480. 'bill_total_expected',
  481. ($filters['bills_created'] === 'yes' ? '>' : '<='),
  482. 0);
  483. }
  484. if ($filters['is_billing_marked_done']) {
  485. $notes->where(
  486. 'is_billing_marked_done',
  487. ($filters['is_billing_marked_done'] === 'yes' ? '=' : '!='),
  488. true);
  489. }
  490. if ($filters['bills_resolved']) {
  491. $notes->whereRaw('(SELECT count(id) FROM bill WHERE note_id = note.id) > 0'); // have bills
  492. if ($filters['bills_resolved'] === 'yes') {
  493. $notes->whereRaw('(SELECT count(id) FROM bill WHERE note_id = note.id AND (is_cancelled = false AND is_verified = false) OR (is_cancelled = TRUE AND is_cancellation_acknowledged = FALSE)) > 0');
  494. } elseif ($filters['bills_resolved'] === 'no') {
  495. $notes->whereRaw('(SELECT count(id) FROM bill WHERE note_id = note.id AND ((is_cancelled = true AND is_cancellation_acknowledged = true) OR is_verified = true)) = 0');
  496. }
  497. }
  498. if ($filters['bills_closed']) {
  499. $notes->where(
  500. 'is_bill_closed',
  501. ($filters['bills_closed'] === 'yes' ? '=' : '!='),
  502. true);
  503. }
  504. if ($filters['claims_created']) {
  505. $notes->where(
  506. 'claim_total_expected',
  507. ($filters['claims_created'] === 'yes' ? '>' : '<='),
  508. 0);
  509. }
  510. if ($filters['claims_closed']) {
  511. $notes->where(
  512. 'is_claim_closed',
  513. ($filters['claims_closed'] === 'yes' ? '=' : '!='),
  514. true);
  515. }
  516. $notes = $notes->orderBy('effective_dateest', 'desc')->paginate();
  517. return view('app.practice-management.billing-manager', compact('notes', 'allPros', 'expectedForHcp', 'targetPro', 'proUid', 'filters'));
  518. }
  519. public function billMatrix(Request $request)
  520. {
  521. $bClients = [];
  522. $bHCPPros = [];
  523. $bNAPros = [];
  524. $filters = [];
  525. $filters['client'] = $request->input('client');
  526. $filters['service'] = $request->input('service');
  527. $filters['hcp'] = $request->input('hcp');
  528. $filters['hcp_paid'] = $request->input('hcp_paid');
  529. $filters['expected_op'] = $request->input('expected_op');
  530. $filters['expected_value'] = $request->input('expected_value');
  531. $filters['paid_op'] = $request->input('paid_op');
  532. $filters['paid_value'] = $request->input('paid_value');
  533. $filters['bal_post_date_op'] = $request->input('bal_post_date_op');
  534. $filters['bal_post_date_value'] = $request->input('bal_post_date_value');
  535. $filters['hcp_sign'] = $request->input('hcp_sign');
  536. $filters['verified'] = $request->input('verified');
  537. $filters['cancelled'] = $request->input('cancelled');
  538. $bills = Bill::orderBy('effective_date')->paginate();
  539. return view('app.practice-management.bill-matrix', compact('bills', 'bClients', 'bHCPPros', 'filters'));
  540. }
  541. public function medicarePartBClaims(Request $request)
  542. {
  543. $medicarePartBOnly = $request->get("medicare_part_b");
  544. $allClaims = Claim::where('was_submitted', false)->orWhere('was_submitted', null)->orderBy('created_at', 'desc')->get();
  545. //Only medicare claims
  546. $claims = [];
  547. foreach ($allClaims as $claim) {
  548. if ($claim->client != null && $claim->client->is_part_b_primary == 'YES' && !$claim->edi) {
  549. $claims[] = $claim;
  550. }
  551. }
  552. $claimEDIs = ClaimEDI::all();
  553. return view('app.practice-management.medicare-partb-claims', compact('claims', 'claimEDIs'));
  554. }
  555. // Generate PDF
  556. public function downloadClaims()
  557. {
  558. $claims = Claim::where('was_submitted', false)->orWhere('was_submitted', null)->orderBy('created_at', 'desc')->limit(100)->get();
  559. view()->share('claims', $claims);
  560. $pdf = PDF::loadView('app.practice-management.claims-pdf', $claims);
  561. return $pdf->download('pdf_file.pdf');
  562. }
  563. public function tickets(Request $request, $proUid = null)
  564. {
  565. $tickets = Ticket::orderBy('created_at', 'desc')->paginate();
  566. return view('app.practice-management.tickets', compact('tickets'));
  567. }
  568. public function supplyOrders(Request $request)
  569. {
  570. // counts
  571. $counts = $this->getSupplyOrderCounts();
  572. // so clients
  573. $soClientIDs = DB::table('supply_order')->select('client_id')->distinct()->get()->toArray();
  574. $soClientIDs = array_map(function ($_x) {
  575. return $_x->client_id;
  576. }, $soClientIDs);
  577. $soClients = Client::whereIn('id', $soClientIDs)->get();
  578. // so products
  579. $soProductIDs = DB::table('supply_order')->select('product_id')->distinct()->get()->toArray();
  580. $soProductIDs = array_map(function ($_x) {
  581. return $_x->product_id;
  582. }, $soProductIDs);
  583. $soProducts = Product::whereIn('id', $soProductIDs)->get();
  584. $filters = [];
  585. $filters['client'] = $request->input('client');
  586. $filters['product'] = $request->input('product');
  587. $filters['reason'] = $request->input('reason');
  588. $filters['cu_memo'] = $request->input('cu_memo');
  589. $filters['pro_sign'] = $request->input('pro_sign');
  590. $filters['client_sign'] = $request->input('client_sign');
  591. $filters['shipment'] = $request->input('shipment');
  592. $filters['lot_number'] = $request->input('lot_number');
  593. $filters['imei'] = $request->input('imei');
  594. $filters['cancelled'] = $request->input('cancelled');
  595. $supplyOrders = SupplyOrder::where('id', '>', 0);
  596. // apply filters
  597. if ($filters['client']) $supplyOrders->where('client_id', $filters['client']);
  598. if ($filters['product']) $supplyOrders->where('product_id', $filters['product']);
  599. if ($filters['reason']) $supplyOrders->where('reason', 'ILIKE', '%' . $filters['reason'] . '%');
  600. if ($filters['cu_memo']) $supplyOrders->where('cu_memo', 'ILIKE', '%' . $filters['cu_memo'] . '%');
  601. if ($filters['pro_sign']) $supplyOrders->where('is_signed_by_pro', ($filters['pro_sign'] === 'signed'));
  602. if ($filters['client_sign']) {
  603. if ($filters['client_sign'] === 'signed')
  604. $supplyOrders->where('is_signed_by_client', true);
  605. elseif ($filters['client_sign'] === 'waived')
  606. $supplyOrders->where('is_client_signature_waived', true);
  607. else
  608. $supplyOrders->where('is_client_signature_waived', false)->where('is_signed_by_client', false);
  609. }
  610. if ($filters['shipment']) {
  611. if ($filters['shipment'] === 'not_cleared_for_shipment')
  612. $supplyOrders->whereNull('shipment_id')->where('is_cleared_for_shipment', false);
  613. elseif ($filters['shipment'] === 'cleared_for_shipment')
  614. $supplyOrders->whereNull('shipment_id')->where('is_cleared_for_shipment', true);
  615. else
  616. $supplyOrders
  617. ->whereNotNull('shipment_id')
  618. ->whereRaw('(SELECT status FROM shipment WHERE id = shipment_id LIMIT 1) = ?', [$filters['shipment']]);
  619. }
  620. if ($filters['lot_number']) $supplyOrders->where('lot_number', 'ILIKE', '%' . $filters['lot_number'] . '%');
  621. if ($filters['imei']) $supplyOrders->where('imei', 'ILIKE', '%' . $filters['imei'] . '%');
  622. if ($filters['cancelled']) $supplyOrders->where('is_cancelled', ($filters['cancelled'] === 'cancelled'));
  623. $supplyOrders = $supplyOrders->orderBy('created_at', 'desc')->paginate();
  624. return view('app.practice-management.supply-orders',
  625. compact('supplyOrders', 'filters',
  626. 'soClients', 'soProducts', 'counts'
  627. )
  628. );
  629. }
  630. public function shipments(Request $request, $filter = null)
  631. {
  632. // counts
  633. $counts = $this->getShipmentCounts();
  634. // so clients
  635. $shClientIDs = DB::table('shipment')->select('client_id')->distinct()->get()->toArray();
  636. $shClientIDs = array_map(function ($_x) {
  637. return $_x->client_id;
  638. }, $shClientIDs);
  639. $shClients = Client::whereIn('id', $shClientIDs)->get();
  640. $shipments = Shipment::where('id', '>', 0);
  641. $filters = [];
  642. $filters['client'] = $request->input('client');
  643. $filters['courier'] = $request->input('courier');
  644. $filters['tracking_num'] = $request->input('tracking_num');
  645. $filters['label'] = $request->input('label');
  646. $filters['status'] = $request->input('status');
  647. $filters['cancelled'] = $request->input('cancelled');
  648. if ($filters['client']) $shipments->where('client_id', $filters['client']);
  649. if ($filters['courier']) $shipments->where('courier', 'ILIKE', '%' . $filters['courier'] . '%');
  650. if ($filters['tracking_num']) $shipments->where('tracking_number', 'ILIKE', '%' . $filters['tracking_num'] . '%');
  651. if ($filters['label']) {
  652. if ($filters['label'] === 'yes')
  653. $shipments->whereNotNull('label_system_file_id');
  654. else
  655. $shipments->whereNull('label_system_file_id');
  656. }
  657. if ($filters['status']) $shipments->where('status', $filters['status']);
  658. if ($filters['cancelled']) $shipments->where('is_cancelled', ($filters['cancelled'] === 'cancelled'));
  659. $shipments = $shipments->orderBy('created_at', 'desc')->paginate();
  660. return view('app.practice-management.shipments', compact('shipments', 'filters', 'shClients', 'counts'));
  661. }
  662. public function cellularMeasurements(Request $request)
  663. {
  664. $measurements = Measurement::orderBy('ts', 'desc')->whereNotNull('ts')->paginate();
  665. return view('app.practice-management.cellular-measurements', compact('measurements'));
  666. }
  667. // v2 supply-orders & shipments management (wh)
  668. public function supplyOrdersReadyToShip(Request $request)
  669. {
  670. $counts = $this->getSupplyOrderCounts();
  671. $supplyOrders = SupplyOrder
  672. ::where('is_cleared_for_shipment', true)
  673. ->where('is_cancelled', false)
  674. ->whereNull('shipment_id')
  675. ->join('client', 'client.id', '=', 'supply_order.client_id')
  676. ->orderBy('client.name_last', 'ASC')
  677. ->orderBy('client.name_first', 'ASC')
  678. ->orderBy('supply_order.client_id', 'ASC')
  679. ->orderBy('supply_order.mailing_address_full', 'ASC')
  680. ->orderBy('supply_order.created_at', 'ASC')
  681. ->select('supply_order.*')
  682. ->paginate();
  683. return view('app.practice-management.supply-orders-ready-to-ship', compact('supplyOrders', 'counts'));
  684. }
  685. public function supplyOrdersShipmentUnderway(Request $request)
  686. {
  687. $counts = $this->getSupplyOrderCounts();
  688. $supplyOrders = SupplyOrder
  689. ::where('is_cancelled', false)
  690. ->whereNotNull('shipment_id')
  691. ->orderBy('client_id', 'ASC')
  692. ->orderBy('mailing_address_full', 'ASC')
  693. ->orderBy('created_at', 'ASC')
  694. ->paginate();
  695. return view('app.practice-management.supply-orders-shipment-underway', compact('supplyOrders', 'counts'));
  696. }
  697. public function supplyOrdersHanging(Request $request)
  698. {
  699. $counts = $this->getSupplyOrderCounts();
  700. $supplyOrders = SupplyOrder
  701. ::select('supply_order.*')
  702. ->leftJoin('shipment', function($join) {
  703. $join->on('supply_order.shipment_id', '=', 'shipment.id');
  704. })
  705. ->where('shipment.status', 'CANCELLED')
  706. ->where('supply_order.is_cancelled', false)
  707. ->orderBy('supply_order.client_id', 'ASC')
  708. ->orderBy('supply_order.mailing_address_full', 'ASC')
  709. ->orderBy('supply_order.created_at', 'ASC')
  710. ->paginate();
  711. return view('app.practice-management.supply-orders-hanging', compact('supplyOrders', 'counts'));
  712. }
  713. private function getSupplyOrderCounts()
  714. {
  715. return [
  716. "supplyOrders" => SupplyOrder::count(),
  717. "supplyOrdersReadyToShip" => SupplyOrder
  718. ::where('is_cleared_for_shipment', true)
  719. ->where('is_cancelled', false)
  720. ->whereNull('shipment_id')->count(),
  721. "supplyOrdersShipmentUnderway" => SupplyOrder
  722. ::where('is_cancelled', false)
  723. ->whereNotNull('shipment_id')->count(),
  724. "supplyOrdersHanging" => SupplyOrder
  725. ::leftJoin('shipment', function($join) {
  726. $join->on('supply_order.shipment_id', '=', 'shipment.id');
  727. })
  728. ->where('shipment.status', 'CANCELLED')
  729. ->where('supply_order.is_cancelled', false)
  730. ->count(),
  731. ];
  732. }
  733. public function shipmentsReadyToPrint(Request $request)
  734. {
  735. $counts = $this->getShipmentCounts();
  736. $shipments = Shipment
  737. ::where('is_cancelled', false)
  738. ->where('status', 'CREATED')
  739. ->orderBy('created_at', 'ASC')
  740. ->paginate();
  741. return view('app.practice-management.shipments-ready-to-print', compact('shipments', 'counts'));
  742. }
  743. public function shipmentsShipmentUnderway(Request $request)
  744. {
  745. $counts = $this->getShipmentCounts();
  746. $shipments = Shipment
  747. ::where('is_cancelled', false)
  748. ->where('status', 'PRINTED')
  749. ->orderBy('created_at', 'ASC')
  750. ->paginate();
  751. return view('app.practice-management.shipments-waiting-for-picker', compact('shipments', 'counts'));
  752. }
  753. private function getShipmentCounts()
  754. {
  755. return [
  756. "shipments" => Shipment::count(),
  757. "shipmentsReadyToPrint" => Shipment
  758. ::where('is_cancelled', false)
  759. ->where('status', 'CREATED')
  760. ->count(),
  761. "shipmentsWaitingForPicker" => Shipment
  762. ::where('is_cancelled', false)
  763. ->where('status', 'PRINTED')
  764. ->count()
  765. ];
  766. }
  767. public function shipment(Request $request, Shipment $shipment)
  768. {
  769. return view('app.practice-management.shipment', compact('shipment'));
  770. }
  771. public function shipmentsMultiPrint(Request $request, $ids)
  772. {
  773. $ids = array_map(function ($_x) {
  774. return intval($_x);
  775. }, explode("|", $ids));
  776. $shipments = Shipment::whereIn('id', $ids)->get();
  777. return view('app.practice-management.shipments-multi-print', compact('shipments'));
  778. }
  779. public function patientClaimSummary(Request $request, $proUid=null)
  780. {
  781. $notesTotal = DB::select(DB::raw("SELECT COUNT(*) FROM note WHERE is_cancelled IS NOT TRUE"))[0]->count;
  782. $notesTotalWithBillingClosed = DB::select(DB::raw("SELECT COUNT(*) FROM note WHERE is_cancelled IS NOT TRUE AND is_bill_closed IS TRUE"))[0]->count;
  783. $notesTotalWithClaimingClosed = DB::select(DB::raw("SELECT COUNT(*) FROM note WHERE is_cancelled IS NOT TRUE AND is_claim_closed IS TRUE"))[0]->count;
  784. $patientsTotal = DB::select(DB::raw("SELECT COUNT(*) FROM client WHERE is_active IS TRUE AND 0 NOT IN (SELECT c FROM (SELECT COUNT(*) c FROM note WHERE is_cancelled IS NOT TRUE AND note.client_id = client.id) x)"))[0]->count;
  785. $patientsTotalWithBillingClosed = DB::select(DB::raw("SELECT COUNT(*) FROM client WHERE is_active IS TRUE AND 0 NOT IN (SELECT c FROM (SELECT COUNT(*) c FROM note WHERE is_cancelled IS NOT TRUE AND note.client_id = client.id) y) AND 0 IN (SELECT c FROM (SELECT COUNT(*) c FROM note WHERE is_cancelled IS NOT TRUE AND is_bill_closed IS NOT TRUE AND note.client_id = client.id) x)"))[0]->count;
  786. $patientsTotalWithClaimingClosed = DB::select(DB::raw("SELECT COUNT(*) FROM client WHERE is_active IS TRUE AND 0 NOT IN (SELECT c FROM (SELECT COUNT(*) c FROM note WHERE is_cancelled IS NOT TRUE AND note.client_id = client.id) y) AND 0 IN (SELECT c FROM (SELECT COUNT(*) c FROM note WHERE is_cancelled IS NOT TRUE AND is_claim_closed IS NOT TRUE AND note.client_id = client.id) x)"))[0]->count;
  787. $performerPro = $this->performer->pro;
  788. $allPros = [];
  789. if ($performerPro->pro_type == 'ADMIN') {
  790. $allPros = Pro::all();
  791. } else {
  792. $allPros = [$performerPro];
  793. }
  794. //Patient | MCP | # Notes Total | # Notes without Billing Closed | # Notes without Claiming Closed
  795. $patientsQuery = Client::where('is_dummy', '=', false)
  796. ->select('id', 'uid', 'name_first', 'name_last', 'mcp_pro_id',
  797. DB::raw("(SELECT name_first||' '||name_last FROM pro where pro.id = client.mcp_pro_id) as mcp"),
  798. DB::raw("(SELECT uid FROM pro where pro.id = mcp_pro_id) as mcp_pro_uid"),
  799. DB::raw("(SELECT COUNT(*) FROM note where note.client_id = client.id) as notes_total"),
  800. DB::raw("(SELECT COUNT(*) FROM note where note.client_id = client.id AND is_bill_closed IS NOT true) as notes_without_billing_closed"),
  801. DB::raw("(SELECT COUNT(*) FROM note where note.client_id = client.id AND is_claim_closed IS NOT true) as notes_without_claiming_closed")
  802. )->orderBy('notes_without_claiming_closed', 'desc');
  803. if($proUid){
  804. $mcpPro = Pro::where('uid', $proUid)->first();
  805. if($mcpPro){
  806. $patientsQuery->where('client.mcp_pro_id','=', $mcpPro->id);
  807. }
  808. }
  809. $patients = $patientsQuery->paginate(50);
  810. $data = [
  811. 'patients' => $patients,
  812. 'proUid' => $proUid,
  813. 'allPros' => $allPros,
  814. 'notesTotal' => $notesTotal,
  815. 'notesTotalWithBillingClosed' => $notesTotalWithBillingClosed,
  816. 'notesTotalWithClaimingClosed' => $notesTotalWithClaimingClosed,
  817. 'patientsTotal' => $patientsTotal,
  818. 'patientsTotalWithBillingClosed' => $patientsTotalWithBillingClosed,
  819. 'patientsTotalWithClaimingClosed' => $patientsTotalWithClaimingClosed
  820. ];
  821. return view('app.practice-management.patient-claim-summary', $data);
  822. }
  823. public function packsMultiPrint(Request $request) {
  824. $packs = Pack
  825. ::select('pack.*')
  826. ->leftJoin('shipment', function($join) {
  827. $join->on('pack.shipment_id', '=', 'shipment.id');
  828. })
  829. ->whereNotIn('shipment.status', ['CANCELLED', 'DISPATCHED'])
  830. ->where(function ($query) {
  831. $query->where('pack.status', '<>', 'DELETED')->orWhereNull('pack.status'); // weird, but just the <> isn't working!
  832. })
  833. ->whereNotNull('pack.label_system_file_id')
  834. ->orderBy('pack.created_at', 'ASC')
  835. ->get();
  836. return view('app.practice-management.packs-multi-print', compact('packs'));
  837. }
  838. public function packsMultiPDF(Request $request, $ids) {
  839. $ids = array_map(function ($_x) {
  840. return intval($_x);
  841. }, explode("|", $ids));
  842. $packs = Pack::whereIn('id', $ids)->get();
  843. }
  844. private function callJava($request, $endPoint, $data)
  845. {
  846. $url = config('stag.backendUrl') . $endPoint;
  847. $response = Http::asForm()
  848. ->withHeaders([
  849. 'sessionKey' => $request->cookie('sessionKey')
  850. ])
  851. ->post($url, $data)
  852. ->body();
  853. dd($response);
  854. return $response;
  855. }
  856. }