PracticeManagementController.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\AppSession;
  4. use App\Models\Measurement;
  5. use App\Models\Bill;
  6. use App\Models\Claim;
  7. use App\Models\Client;
  8. use App\Models\McpRequest;
  9. use App\Models\Note;
  10. use App\Models\Pro;
  11. use App\Models\ProFavorite;
  12. use App\Models\ProGeneralAvailability;
  13. use App\Models\ProProAccess;
  14. use App\Models\ProRate;
  15. use App\Models\ProSpecificAvailability;
  16. use App\Models\ProSpecificUnavailability;
  17. use App\Models\ProTextShortcut;
  18. use App\Models\ProTransaction;
  19. use App\Models\Shipment;
  20. use App\Models\SupplyOrder;
  21. use App\Models\Ticket;
  22. use Illuminate\Support\Facades\DB;
  23. use PDF;
  24. use DateTime;
  25. use DateTimeZone;
  26. use Illuminate\Http\Request;
  27. class PracticeManagementController extends Controller
  28. {
  29. public function dashboard(Request $request)
  30. {
  31. return view('app.practice-management.dashboard');
  32. }
  33. public function rates(Request $request, $selectedProUid = 'all')
  34. {
  35. $proUid = $selectedProUid ? $selectedProUid : 'all';
  36. $rates = ProRate::where('is_active', true);
  37. if ($proUid !== 'all') {
  38. $selectedPro = Pro::where('uid', $proUid)->first();
  39. $rates = $rates->where('pro_id', $selectedPro->id);
  40. }
  41. $rates = $rates->orderBy('pro_id', 'asc')->get();
  42. $pros = $this->pros;
  43. return view('app.practice-management.rates', compact('rates', 'pros', 'selectedProUid'));
  44. }
  45. public function previousBills(Request $request)
  46. {
  47. return view('app.practice-management.previous-bills');
  48. }
  49. public function financialTransactions(Request $request)
  50. {
  51. $transactions = ProTransaction::where('pro_id', $this->performer()->pro->id)->orderBy('created_at', 'desc')->get();
  52. return view('app.practice-management.financial-transactions', compact('transactions'));
  53. }
  54. public function pendingBillsToSign(Request $request)
  55. {
  56. return view('app.practice-management.pending-bills-to-sign');
  57. }
  58. public function HR(Request $request)
  59. {
  60. return view('app.practice-management.hr');
  61. }
  62. public function directDepositSettings(Request $request)
  63. {
  64. return view('app.practice-management.direct-deposit-settings');
  65. }
  66. public function w9(Request $request)
  67. {
  68. return view('app.practice-management.w9');
  69. }
  70. public function contract(Request $request)
  71. {
  72. return view('app.practice-management.contract');
  73. }
  74. public function notes(Request $request, $filter = '')
  75. {
  76. $proID = $this->performer()->pro->id;
  77. $query = Note::where('hcp_pro_id', $proID);
  78. switch ($filter) {
  79. case 'not-yet-signed':
  80. $query = $query->where('is_signed_by_hcp', false);
  81. break;
  82. // more cases can be added as needed
  83. default:
  84. break;
  85. }
  86. $notes = $query->orderBy('created_at', 'desc')->get();
  87. return view('app.practice-management.notes', compact('notes', 'filter'));
  88. }
  89. public function bills(Request $request, $filter = '')
  90. {
  91. $proID = $this->performer()->pro->id;
  92. $query = Bill::where('is_cancelled', false);
  93. switch ($filter) {
  94. case 'not-yet-signed':
  95. $query = $query
  96. ->where(function ($q) use ($proID) {
  97. $q->where(function ($q2) use ($proID) {
  98. $q2->where('hcp_pro_id', $proID)->where('is_signed_by_hcp', false);
  99. })
  100. ->orWhere(function ($q2) use ($proID) {
  101. $q2->where('cm_pro_id', $proID)->where('is_signed_by_cm', false);
  102. })
  103. ->orWhere(function ($q2) use ($proID) {
  104. $q2->where('rme_pro_id', $proID)->where('is_signed_by_rme', false);
  105. })
  106. ->orWhere(function ($q2) use ($proID) {
  107. $q2->where('rmm_pro_id', $proID)->where('is_signed_by_rmm', false);
  108. });
  109. });
  110. break;
  111. case 'previous':
  112. $query = $query
  113. ->where(function ($q) use ($proID) {
  114. $q->where(function ($q2) use ($proID) {
  115. $q2->where('hcp_pro_id', $proID)->where('is_signed_by_hcp', true);
  116. })
  117. ->orWhere(function ($q2) use ($proID) {
  118. $q2->where('cm_pro_id', $proID)->where('is_signed_by_cm', true);
  119. })
  120. ->orWhere(function ($q2) use ($proID) {
  121. $q2->where('rme_pro_id', $proID)->where('is_signed_by_rme', true);
  122. })
  123. ->orWhere(function ($q2) use ($proID) {
  124. $q2->where('rmm_pro_id', $proID)->where('is_signed_by_rmm', true);
  125. });
  126. });
  127. break;
  128. // more cases can be added as needed
  129. default:
  130. break;
  131. }
  132. $bills = $query->orderBy('created_at', 'desc')->get();
  133. return view('app.practice-management.bills', compact('bills', 'filter'));
  134. }
  135. public function myTickets(Request $request, $filter = 'open')
  136. {
  137. $performer = $this->performer();
  138. $myTickets = Ticket::where(function ($q) use ($performer) {
  139. $q->where('assigned_pro_id', $performer->pro_id)
  140. ->orWhere('manager_pro_id', $performer->pro_id)
  141. ->orWhere('ordering_pro_id', $performer->pro_id)
  142. ->orWhere('initiating_pro_id', $performer->pro_id);
  143. });
  144. if ($filter === 'open') {
  145. $myTickets = $myTickets->where('is_open', true);
  146. } else if ($filter === 'closed') {
  147. $myTickets = $myTickets->where('is_open', false);
  148. }
  149. $myTickets = $myTickets->orderBy('created_at', 'desc')->get();
  150. return view('app.practice-management.my-tickets', compact('myTickets', 'filter'));
  151. }
  152. public function myTextShortcuts(Request $request)
  153. {
  154. $performer = $this->performer();
  155. $myTextShortcuts = ProTextShortcut::where('pro_id', $performer->pro_id)->where('is_removed', false)->get();
  156. return view('app.practice-management.my-text-shortcuts', compact('myTextShortcuts'));
  157. }
  158. public function myFavorites(Request $request, $filter = 'all')
  159. {
  160. $performer = $this->performer();
  161. $myFavorites = ProFavorite::where('pro_id', $performer->pro_id)
  162. ->where('is_removed', false);
  163. if ($filter !== 'all') {
  164. $myFavorites = $myFavorites->where('category', $filter);
  165. }
  166. $myFavorites = $myFavorites
  167. ->orderBy('category', 'asc')
  168. ->orderBy('position_index', 'asc')
  169. ->get();
  170. return view('app.practice-management.my-favorites', compact('myFavorites', 'filter'));
  171. }
  172. public function proAvailability(Request $request, $proUid = null)
  173. {
  174. $performer = $this->performer();
  175. $pro = $performer->pro;
  176. if ($proUid) {
  177. $pro = Pro::where('uid', $proUid)->first();
  178. }
  179. if ($request->get('pro_uid')) {
  180. $proUid = $request->get('pro_uid');
  181. $pro = Pro::where('uid', $proUid)->first();
  182. }
  183. $selectedProUid = $pro->uid;
  184. $pros = $this->pros;
  185. $generalAvailabilitiesList = ProGeneralAvailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('created_at', 'asc')->get();
  186. $generalAvailabilities = [
  187. 'MONDAY' => [],
  188. 'TUESDAY' => [],
  189. 'WEDNESDAY' => [],
  190. 'THURSDAY' => [],
  191. 'FRIDAY' => [],
  192. 'SATURDAY' => [],
  193. 'SUNDAY' => [],
  194. ];
  195. foreach ($generalAvailabilitiesList as $ga) {
  196. if ($ga->day_of_week == 'MONDAY') {
  197. $generalAvailabilities['MONDAY'][] = $ga;
  198. }
  199. if ($ga->day_of_week == 'TUESDAY') {
  200. $generalAvailabilities['TUESDAY'][] = $ga;
  201. }
  202. if ($ga->day_of_week == 'WEDNESDAY') {
  203. $generalAvailabilities['WEDNESDAY'][] = $ga;
  204. }
  205. if ($ga->day_of_week == 'THURSDAY') {
  206. $generalAvailabilities['THURSDAY'][] = $ga;
  207. }
  208. if ($ga->day_of_week == 'FRIDAY') {
  209. $generalAvailabilities['FRIDAY'][] = $ga;
  210. }
  211. if ($ga->day_of_week == 'SATURDAY') {
  212. $generalAvailabilities['SATURDAY'][] = $ga;
  213. }
  214. if ($ga->day_of_week == 'SUNDAY') {
  215. $generalAvailabilities['SUNDAY'][] = $ga;
  216. }
  217. }
  218. $specificAvailabilities = ProSpecificAvailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('start_time')->get();
  219. $specificUnavailabilities = ProSpecificUnavailability::where('pro_id', $pro->id)->where('is_cancelled', false)->orderBy('start_time', 'asc')->get();
  220. //events for the calendar
  221. $startDate = date('Y-m-d', strtotime("sunday -1 week"));
  222. $endDateTime = new DateTime($startDate);
  223. $endDateTime->modify('+6 day');
  224. $endDate = $endDateTime->format("Y-m-d");
  225. $eventsData = $pro->getAvailabilityEvents($startDate, $endDate);
  226. $events = json_encode($eventsData);
  227. return view(
  228. 'app.practice-management.pro-availability',
  229. compact(
  230. 'pros',
  231. 'generalAvailabilities',
  232. 'specificAvailabilities',
  233. 'specificUnavailabilities',
  234. 'events',
  235. 'selectedProUid'
  236. )
  237. );
  238. }
  239. public function loadAvailability(Request $request, $proUid)
  240. {
  241. $performer = $this->performer();
  242. $pro = $performer->pro;
  243. $startDate = $request->get('start');
  244. $endDate = $request->get('end');
  245. $selectedPro = Pro::where('uid', $proUid)->first();
  246. return $selectedPro->getAvailabilityEvents($startDate, $endDate);
  247. }
  248. public function proAvailabilityFilter(Request $request)
  249. {
  250. $proUid = $request->get('proUid');
  251. return ['success' => true, 'data' => $proUid];
  252. }
  253. // video call page (RHS)
  254. // generic call handle (no uid)
  255. // specific call handle (uid of client)
  256. public function meet(Request $request, $uid = false)
  257. {
  258. $session = AppSession::where('session_key', $request->cookie('sessionKey'))->first();
  259. $client = !empty($uid) ? Client::where('uid', $uid)->first() : null;
  260. if (!empty($client)) {
  261. return view('app.video.call-minimal', compact('session', 'client'));
  262. }
  263. return view('app.video.call-agora-v2', compact('session', 'client'));
  264. }
  265. // check video page
  266. public function checkVideo(Request $request, $uid)
  267. {
  268. $session = AppSession::where('session_key', $request->cookie('sessionKey'))->first();
  269. $client = !empty($uid) ? Client::where('uid', $uid)->first() : null;
  270. $publish = false;
  271. return view('app.video.check-video-minimal', compact('session', 'client'));
  272. }
  273. public function getParticipantInfo(Request $request)
  274. {
  275. $sid = intval($request->get('uid')) - 1000000;
  276. $session = AppSession::where('id', $sid)->first();
  277. $result = [
  278. "type" => '',
  279. "name" => ''
  280. ];
  281. if ($session) {
  282. $result["type"] = $session->session_type;
  283. switch ($session->session_type) {
  284. case 'PRO':
  285. $pro = Pro::where('id', $session->pro_id)->first();
  286. $result["name"] = $pro->displayName();
  287. break;
  288. case 'CLIENT':
  289. $client = Client::where('id', $session->client_id)->first();
  290. $result["name"] = $client->displayName();
  291. break;
  292. }
  293. }
  294. return json_encode($result);
  295. }
  296. // ajax ep used by the video page
  297. // this is needed bcoz meet() is used not
  298. // just for the client passed to the view
  299. public function getOpentokSessionKey(Request $request, $uid)
  300. {
  301. $client = Client::where('uid', $uid)->first();
  302. return json_encode(["data" => $client ? $client->opentok_session_id : '']);
  303. }
  304. // poll to check if there are patients with active mcp requests
  305. public function getPatientsInQueue(Request $request)
  306. {
  307. $myInitiatives = $this->performer->pro->initiatives;
  308. if($myInitiatives){
  309. $myInitiatives = strtoupper($myInitiatives);
  310. }
  311. $myInitiativesList = explode('|', $myInitiatives);
  312. $myForeignLanguages = $this->performer->pro->foreign_languages;
  313. if($myForeignLanguages){
  314. $myForeignLanguages = strtoupper($myForeignLanguages);
  315. }
  316. $myForeignLanguagesList = explode('|', $myForeignLanguages);
  317. $clients = Client::whereNotNull('active_mcp_request_id')->where(function($query) use ($myInitiativesList){
  318. $query->whereNull('initiative')->orWhereIn('initiative', $myInitiativesList);
  319. })
  320. ->where(function($query) use ($myForeignLanguagesList) {
  321. $query->whereNull('preferred_foreign_language')->orWhereIn('preferred_foreign_language', $myForeignLanguagesList);
  322. })->limit(3)->get();
  323. $results = [];
  324. foreach($clients as $client){
  325. $results[] = [
  326. 'clientUid' => $client->uid,
  327. 'name' => $client->displayName(),
  328. 'initials'=> substr($client->name_first, 0, 1) . substr($client->name_last, 0, 1)
  329. ];
  330. }
  331. return json_encode($results);
  332. }
  333. public function currentWork(Request $request)
  334. {
  335. return view('app/current-work');
  336. }
  337. public function calendar(Request $request, $proUid = null)
  338. {
  339. $pros = Pro::all();
  340. if($this->pro && $this->pro->pro_type != 'ADMIN'){
  341. $accessiblePros = ProProAccess::where('owner_pro_id', $this->pro->id);
  342. $accessibleProIds = [];
  343. foreach($accessiblePros as $accessiblePro){
  344. $accessibleProIds[] = $accessiblePro->id;
  345. }
  346. $accessibleProIds[] = $this->pro->id;
  347. $pros = Pro::whereIn('id', $accessibleProIds)->get();
  348. }
  349. return view('app.practice-management.calendar', compact('pros'));
  350. }
  351. public function cellularDeviceManager(Request $request, $proUid = null)
  352. {
  353. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  354. $performerPro = $this->performer->pro;
  355. $targetPro = null;
  356. $allPros = [];
  357. $expectedForHcp = null;
  358. if ($performerPro->pro_type == 'ADMIN') {
  359. $allPros = Pro::all();
  360. $targetPro = Pro::where('uid', $proUid)->first();
  361. } else {
  362. $targetPro = $performerPro;
  363. }
  364. $clients = [];
  365. if ($targetPro) {
  366. $clients = Client::where('mcp_pro_id', $targetPro->id)->orderBy('created_at', 'desc')->paginate(100);
  367. } else {
  368. $clients = Client::orderBy('created_at', 'desc')->paginate(100);
  369. }
  370. return view('app.practice-management.cellular-device-manager', compact('clients', 'allPros', 'targetPro', 'proUid'));
  371. }
  372. public function treatmentServiceUtil(Request $request){
  373. $view_treatment_service_utilization_org = DB::select(DB::raw("SELECT * FROM view_treatment_service_utilization_org ORDER BY effective_date DESC"));
  374. $view_treatment_service_utilization = DB::select(DB::raw("SELECT * FROM view_treatment_service_utilization ORDER BY effective_date DESC, total_hrs DESC"));
  375. $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"));
  376. return view('app.practice-management.treatment-services-util', compact(
  377. 'view_treatment_service_utilization_org',
  378. 'view_treatment_service_utilization',
  379. 'view_treatment_service_utilization_by_patient'));
  380. }
  381. public function processingBillMatrix(Request $request, $proUid = null)
  382. {
  383. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  384. $performerPro = $this->performer->pro;
  385. $targetPro = null;
  386. $allPros = [];
  387. if ($performerPro->pro_type == 'ADMIN') {
  388. $allPros = Pro::all();
  389. $targetPro = Pro::where('uid', $proUid)->first();
  390. } else {
  391. $targetPro = $performerPro;
  392. }
  393. $bills = [];
  394. if ($targetPro) {
  395. $bills = Bill::where('hcp_pro_id', $targetPro->id)->
  396. where('has_hcp_been_paid', false)->
  397. where('is_cancelled', false)->
  398. where('is_signed_by_hcp', true)->
  399. orderBy('effective_date', 'desc')->paginate();
  400. } else {
  401. $bills = Bill::where('has_hcp_been_paid', false)->
  402. where('is_cancelled', false)->
  403. where('is_signed_by_hcp', true)->
  404. orderBy('effective_date', 'desc')->
  405. paginate();
  406. }
  407. $viewData = [
  408. 'bills' => $bills,
  409. 'allPros' => $allPros,
  410. 'targetPro' => $targetPro,
  411. 'performerPro' => $performerPro,
  412. 'proUid' => $proUid
  413. ];
  414. return view('app.practice-management.processing-bill-matrix', $viewData);
  415. }
  416. public function hcpBillMatrix(Request $request, $proUid = null)
  417. {
  418. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  419. $performerPro = $this->performer->pro;
  420. $targetPro = null;
  421. $allPros = [];
  422. $expectedForHcp = null;
  423. if ($performerPro->pro_type == 'ADMIN') {
  424. $allPros = Pro::all();
  425. $targetPro = Pro::where('uid', $proUid)->first();
  426. } else {
  427. $targetPro = $performerPro;
  428. }
  429. $rows = [];
  430. if ($targetPro) {
  431. $rows = DB::select(DB::raw("SELECT * FROM aemish_bill_report WHERE hcp_pro_id = :targetProID"), ['targetProID' => $targetPro->id]);
  432. } else {
  433. $rows = DB::select(DB::raw("SELECT * FROM aemish_bill_report"));
  434. }
  435. return view('app.practice-management.hcp-bill-matrix', compact('rows', 'allPros', 'expectedForHcp', 'targetPro', 'proUid'));
  436. }
  437. public function billingManager(Request $request, $proUid = null)
  438. {
  439. $proUid = $proUid ? $proUid : $request->get('pro-uid');
  440. $performerPro = $this->performer->pro;
  441. $targetPro = null;
  442. $allPros = [];
  443. $expectedForHcp = null;
  444. if ($performerPro->pro_type == 'ADMIN') {
  445. $allPros = Pro::all();
  446. $targetPro = Pro::where('uid', $proUid)->first();
  447. } else {
  448. $targetPro = $performerPro;
  449. }
  450. $notes = [];
  451. if ($targetPro) {
  452. $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;
  453. $notes = Note::where('hcp_pro_id', $targetPro->id)->orderBy('effective_dateest', 'desc')->paginate();
  454. } else {
  455. $notes = Note::orderBy('effective_dateest', 'desc')->paginate();
  456. }
  457. return view('app.practice-management.billing-manager', compact('notes', 'allPros', 'expectedForHcp', 'targetPro', 'proUid'));
  458. }
  459. public function claims(Request $request)
  460. {
  461. $claims = Claim::where('was_submitted', false)->orWhere('was_submitted', null)->orderBy('created_at', 'desc')->paginate();
  462. return view('app.practice-management.claims', compact('claims'));
  463. }
  464. // Generate PDF
  465. public function downloadClaims()
  466. {
  467. $claims = Claim::where('was_submitted', false)->orWhere('was_submitted', null)->orderBy('created_at', 'desc')->limit(100)->get();
  468. view()->share('claims', $claims);
  469. $pdf = PDF::loadView('app.practice-management.claims-pdf', $claims);
  470. return $pdf->download('pdf_file.pdf');
  471. }
  472. public function tickets(Request $request, $proUid = null)
  473. {
  474. $tickets = Ticket::orderBy('created_at', 'desc')->paginate();
  475. return view('app.practice-management.tickets', compact('tickets'));
  476. }
  477. public function supplyOrders(Request $request, $filter = null) {
  478. $supplyOrders = SupplyOrder::orderBy('created_at', 'desc')->paginate();
  479. return view('app.practice-management.supply-orders', compact('supplyOrders'));
  480. }
  481. public function shipments(Request $request, $filter = null) {
  482. $shipments = Shipment::orderBy('created_at', 'desc')->paginate();
  483. return view('app.practice-management.shipments', compact('shipments'));
  484. }
  485. public function cellularMeasurements(Request $request){
  486. $measurements = Measurement::orderBy('ts', 'desc')->whereNotNull('ts')->paginate();
  487. return view('app.practice-management.cellular-measurements', compact('measurements'));
  488. }
  489. }