Kaynağa Gözat

RPM matrix updated (wip)

Vijayakrishnan 3 yıl önce
ebeveyn
işleme
50fb80b1c8

+ 165 - 0
app/Http/Controllers/PracticeManagementController.php

@@ -1257,6 +1257,171 @@ WHERE care_month.uid = '{$careMonthUid}' AND client.uid = '{$clientUid}'
         return view('app.practice-management.remote-monitoring-row', ['iPatient' => $patients[0], 'trIndex' => $request->input('trIndex')]);
     }
 
+    private function remoteMonitoring_RowByProType(Request $request, $mode) {
+
+        $clientUid = $request->input('clientUid');
+        $careMonthUid = $request->input('careMonthUid');
+
+        $query = "
+SELECT client.name_first, client.name_last,
+       (client.name_first || ' ' || client.name_last) as client_name,
+       client.uid as client_uid, 
+       client.dob,
+       client.is_enrolled_in_rm,
+       client.most_recent_completed_mcp_note_date,
+       client.most_recent_completed_mcp_note_id,
+       mrmnote.effective_dateest::date as most_recent_completed_mcp_note_date_cm,
+       mrmnote.id as most_recent_completed_mcp_note_id_cm,
+       mrmnote.uid as most_recent_completed_mcp_note_uid_cm,
+       client.cell_number,
+       client.is_assigned_cellular_bp_device,
+       client.is_assigned_cellular_weight_scale_device,
+       care_month.uid as care_month_uid,
+       care_month.id as care_month_id,
+       care_month.start_date,
+       care_month.rm_total_time_in_seconds_by_mcp,
+       care_month.rm_total_time_in_seconds_by_rmm_pro,
+       care_month.number_of_days_with_remote_measurements,
+       care_month.has_mcp_interacted_with_client_about_rm,
+       care_month.rm_num_measurements_not_stamped_by_mcp,
+       care_month.rm_num_measurements_not_stamped_by_non_hcp,
+       care_month.rm_num_measurements_not_stamped_by_rmm,
+       care_month.rm_num_measurements_not_stamped_by_rme,
+       care_month.mcp_pro_id as care_month_mcp_pro_id,
+       care_month.rmm_pro_id as care_month_rmm_pro_id,
+       client.mcp_pro_id,
+       client.default_na_pro_id,
+       client.rmm_pro_id,
+       client.rme_pro_id,
+       client.cell_number,
+       care_month.most_recent_cellular_bp_dbp_mm_hg,
+       care_month.most_recent_cellular_bp_sbp_mm_hg,
+       care_month.most_recent_cellular_bp_measurement_at,      
+       care_month.most_recent_cellular_weight_value,
+       care_month.most_recent_cellular_weight_measurement_at
+FROM care_month join client on care_month.client_id = client.id join note mrnote on client.most_recent_completed_mcp_note_id = mrnote.id
+     left join note mrmnote on mrmnote.id = (
+        select max(n.id) from note n 
+        where 
+              n.client_id = client.id AND 
+              n.is_cancelled = FALSE AND
+              (n.is_signed_by_hcp IS NOT NULL AND n.is_signed_by_hcp = TRUE) AND
+              n.effective_dateest::date >= care_month.start_date::date AND 
+              n.effective_dateest::date < (care_month.start_date::date + INTERVAL '1 month')
+     )
+WHERE care_month.uid = '{$careMonthUid}' AND client.uid = '{$clientUid}'
+";
+
+        $patients = DB::select($query);
+
+        return view('app.practice-management.remote-monitoring-row-by-pro-type', ['iPatient' => $patients[0], 'trIndex' => $request->input('trIndex'), 'mode' => $mode]);
+    }
+
+    private function rpmMatrixByProType(Request $request, $mode) {
+
+        $performer = $this->performer();
+
+        // abort_if($performer->pro->pro_type !== 'ADMIN' && !$performer->pro->can_view_rm_matrix, 403);
+
+        $ym = ($request->input('y') ?: 'Y') . '-' . ($request->input('m') ?: 'm');
+        $careMonthStart = date($ym . '-01');
+
+        $rc = $request->input('rc') ?: 1;
+        $rc2 = $request->input('rc2') ?: 2;
+
+        $conditions = [];// $this->rpmConditions($performer, $rc, $rc2);
+
+        $sortBy = $request->input('sort_by') ?: 'name_first';
+        $sortDir = $request->input('sort_dir') ?: 'ASC';
+        $orderBy = "ORDER BY $sortBy $sortDir NULLS LAST";
+
+        $query = "
+SELECT client.name_first, client.name_last,
+       (client.name_first || ' ' || client.name_last) as client_name,
+       client.uid as client_uid, 
+       client.dob,
+       client.is_enrolled_in_rm,
+       client.most_recent_completed_mcp_note_date,
+       client.most_recent_completed_mcp_note_id,
+       mrmnote.effective_dateest::date as most_recent_completed_mcp_note_date_cm,
+       mrmnote.id as most_recent_completed_mcp_note_id_cm,
+       mrmnote.uid as most_recent_completed_mcp_note_uid_cm,
+       client.cell_number,
+       client.is_assigned_cellular_bp_device,
+       client.is_assigned_cellular_weight_scale_device,
+       care_month.uid as care_month_uid,
+       care_month.id as care_month_id,
+       care_month.start_date,
+       care_month.rm_total_time_in_seconds_by_mcp,
+       care_month.rm_total_time_in_seconds_by_rmm_pro,
+       care_month.number_of_days_with_remote_measurements,
+       care_month.has_mcp_interacted_with_client_about_rm,
+       care_month.rm_num_measurements_not_stamped_by_mcp,
+       care_month.rm_num_measurements_not_stamped_by_non_hcp,
+       care_month.rm_num_measurements_not_stamped_by_rmm,
+       care_month.rm_num_measurements_not_stamped_by_rme,
+       care_month.mcp_pro_id as care_month_mcp_pro_id,
+       care_month.rmm_pro_id as care_month_rmm_pro_id,
+       client.mcp_pro_id,
+       client.default_na_pro_id,
+       client.rmm_pro_id,
+       client.rme_pro_id,
+       client.cell_number,
+       care_month.most_recent_cellular_bp_dbp_mm_hg,
+       care_month.most_recent_cellular_bp_sbp_mm_hg,
+       care_month.most_recent_cellular_bp_measurement_at,      
+       care_month.most_recent_cellular_weight_value,
+       care_month.most_recent_cellular_weight_measurement_at
+FROM care_month join client on care_month.client_id = client.id join note mrnote on client.most_recent_completed_mcp_note_id = mrnote.id
+     left join note mrmnote on mrmnote.id = (
+        select max(n.id) from note n 
+        where 
+              n.client_id = client.id AND 
+              n.is_cancelled = FALSE AND
+              (n.is_signed_by_hcp IS NOT NULL AND n.is_signed_by_hcp = TRUE) AND
+              n.effective_dateest::date >= care_month.start_date::date AND 
+              n.effective_dateest::date < (care_month.start_date::date + INTERVAL '1 month')
+     )
+WHERE
+      (care_month.mcp_pro_id = {$performer->pro->id} OR care_month.rmm_pro_id = {$performer->pro->id})
+      AND EXTRACT(MONTH from care_month.start_date) = " . ($request->input('m') ?: 'EXTRACT(MONTH from now())') . "
+      AND EXTRACT(YEAR from care_month.start_date) = " . ($request->input('y') ?: 'EXTRACT(YEAR from now())') . "
+      " . (count($conditions) > 0 ? 'AND ' . implode(" AND ", $conditions) : '') . "
+      $orderBy
+";
+
+        $patients = DB::select($query);
+
+        $timestamp = strtotime(date('Y-m-d'));
+        $daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
+
+        return view('app.practice-management.rpm-matrix-by-pro-type', compact('patients', 'daysRemaining', 'careMonthStart', 'mode'));
+    }
+
+    public function remoteMonitoringMCP(Request $request) {
+        return $this->rpmMatrixByProType($request, 'mcp');
+    }
+
+    public function remoteMonitoringRMM(Request $request) {
+        return $this->rpmMatrixByProType($request, 'rmm');
+    }
+
+    public function remoteMonitoringRME(Request $request) {
+        return $this->rpmMatrixByProType($request, 'rme');
+    }
+
+    public function remoteMonitoring_RowMCP(Request $request) {
+        return $this->remoteMonitoring_RowByProType($request, 'mcp');
+    }
+
+    public function remoteMonitoring_RowRMM(Request $request) {
+        return $this->remoteMonitoring_RowByProType($request, 'rmm');
+    }
+
+    public function remoteMonitoring_RowRME(Request $request) {
+        return $this->remoteMonitoring_RowByProType($request, 'rme');
+    }
+
     public function rpm_work_matrix(Request $request) {
 
         // get the patient having most recent unstamped measurement

+ 7 - 9
resources/views/app/practice-management/_sort_header.blade.php

@@ -1,9 +1,7 @@
-<b class="{{request()->input('sort_by') === $key ? 'text-primary' : 'text-secondary'}}">{{$label}}</b>
-<span class="ml-2 d-inline-flex align-items-baseline">
-    <a href="{{ $route }}?{{queryLineExcept(['sort_by', 'sort_dir'])}}&sort_by={{$key}}&sort_dir=DESC" class="ml-1">
-        <i class="fa fa-arrow-up {{request()->input('sort_by') === $key && request()->input('sort_dir') === 'DESC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
-    </a>
-    <a href="{{ $route }}?{{queryLineExcept(['sort_by', 'sort_dir'])}}&sort_by={{$key}}&sort_dir=ASC" class="ml-1">
-        <i class="fa fa-arrow-down {{request()->input('sort_by') === $key && request()->input('sort_dir') === 'ASC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
-    </a>
-</span>
+<a href="{{ $route }}?{{queryLineExcept(['sort_by', 'sort_dir'])}}&sort_by={{$key}}&sort_dir={{request()->input('sort_by') === $key && request()->input('sort_dir') === 'ASC' ? 'DESC' : 'ASC'}}" class="ml-1 text-decoration-none">
+    <b class="{{request()->input('sort_by') === $key ? 'text-primary' : 'text-secondary'}}">{{$label}}</b>
+    <span class="ml-2 d-inline-flex align-items-baseline">
+        <i class="text-sm fa fa-chevron-up {{request()->input('sort_by') === $key && request()->input('sort_dir') === 'DESC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
+        <i class="ml-1 text-sm fa fa-chevron-down {{request()->input('sort_by') === $key && request()->input('sort_dir') === 'ASC' ? '' : 'on-hover-opaque text-secondary'}}"></i>
+    </span>
+</a>

+ 18 - 0
resources/views/app/practice-management/remote-monitoring-row-by-pro-type.blade.php

@@ -0,0 +1,18 @@
+<?php
+
+$mStr = request()->input('m') ? request()->input('m') : date('m');
+$yStr = request()->input('y') ? request()->input('y') : date('Y');
+$rcmStartDate = $yStr . '-' . $mStr . '-' . '01';
+$m = +$mStr;
+$y = +$yStr;
+
+$daysDiff = -1;
+if($iPatient->most_recent_completed_mcp_note_date) {
+    $careMonthLastDay = date_add(date_create($rcmStartDate), date_interval_create_from_date_string("1 month"));
+    $careMonthLastDay = date_sub($careMonthLastDay, date_interval_create_from_date_string("1 day"));
+    $daysDiff = date_diff($careMonthLastDay, date_create($iPatient->most_recent_completed_mcp_note_date))->days;
+}
+$lastVisitWithin90Days = ($daysDiff !== -1 && $daysDiff <= 90);
+
+?>
+@include('app.practice-management.remote-monitoring-row-markup-by-pro-type')

+ 252 - 0
resources/views/app/practice-management/remote-monitoring-row-markup-by-pro-type.blade.php

@@ -0,0 +1,252 @@
+<tr data-client-uid="{{$iPatient->client_uid}}" data-care-month-uid="{{$iPatient->care_month_uid}}">
+    <td class="pl-2">
+        <a href="/patients/view/{{ $iPatient->client_uid }}/care-months/view/{{$iPatient->care_month_uid}}" class="text-nowrap"
+           native target="_blank"
+           open-in-stag-popup
+           update-parent="refresh-rpm-row-{{$trIndex}}"
+           popup-style="tall overflow-visible"
+           mc-initer="care-month-dashboard-{{$iPatient->client_uid}}"
+           title="{{$iPatient->client_name}}"
+        ><span class="sort-data">{{ $iPatient->client_name }}</span></a>
+    </td>
+
+    <td>{{friendly_date($iPatient->dob)}}</td>
+    <td>{!! $iPatient->is_enrolled_in_rm === 'YES' ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>{!! $iPatient->is_assigned_cellular_bp_device ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>{!! $iPatient->is_assigned_cellular_weight_scale_device ? '<i class="fa fa-check text-success"></i>' : 'No' !!}</td>
+    <td>
+        <div class="text-nowrap">
+            <span class="sort-data">{{$iPatient->most_recent_cellular_bp_sbp_mm_hg ?: '-'}}</span>/{{$iPatient->most_recent_cellular_bp_dbp_mm_hg ?: '-'}}
+            @if($iPatient->most_recent_cellular_bp_measurement_at)
+                <span class="text-sm text-secondary text-nowrap ml-1"
+                      title="{{friendly_date_time($iPatient->most_recent_cellular_bp_measurement_at)}}">({{friendly_date($iPatient->most_recent_cellular_bp_measurement_at)}})</span>
+            @endif
+        </div>
+    </td>
+    <td>
+        <div class="text-nowrap">
+            <span class="sort-data">{{$iPatient->most_recent_cellular_weight_value ? round($iPatient->most_recent_cellular_weight_value, 1) : '-'}}</span>
+            @if($iPatient->most_recent_cellular_weight_measurement_at)
+                <span class="text-sm text-secondary text-nowrap ml-1"
+                      title="{{friendly_date_time($iPatient->most_recent_cellular_weight_measurement_at)}}">({{friendly_date($iPatient->most_recent_cellular_weight_measurement_at)}})</span>
+            @endif
+        </div>
+    </td>
+    
+    <td>
+        <div class="d-flex align-items-baseline">
+            <i class="mr-1 text-sm fa {{$lastVisitWithin90Days ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+            <span class="sort-data">{{$daysDiff !== -1 ? $daysDiff : '-'}}</span>
+        </div>
+    </td>
+
+    @if($mode === 'mcp' || $mode === 'rmm')
+        @if($strategy === 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM')
+            <td>
+                <div class="d-flex align-items-baseline">
+                    <i class="mr-1 text-sm fa {{$iPatient->has_mcp_interacted_with_client_about_rm ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                    <span class="sort-data">{{$iPatient->has_mcp_interacted_with_client_about_rm ? 'Yes' : 'No'}}</span>
+                    @if($mode === 'mcp')
+                        <div moe large relative class="ml-2">
+                            <a start show class="py-0 mb-3 text-sm">Entry</a>
+                            <form url="/api/careMonthEntry/createForRm" right hook="refresh-rpm-row-{{$trIndex}}">
+                                <input type="hidden" name="careMonthUid" value="{{ $iPatient->care_month_uid }}">
+                                <input type="hidden" name="proUid" value="{{ $pro->uid }}">
+                                <div class="mb-2">
+                                    <div class="row">
+                                        <div class="col-6 pr-0">
+                                            <?php
+                                            $sD = strtotime($rcmStartDate);
+                                            $y = date('Y', $sD);
+                                            $m0 = date('m', $sD);
+                                            $d = date('t', $sD);
+                                            $defaultED = $sD >= strtotime(date('Y-m-d')) ? date('Y-m-d') : $rcmStartDate;
+                                            ?>
+                                            <label class="text-sm text-secondary mb-1">Effective Date</label>
+                                            <input autofocus type="date" min="{{ date($y . '-' . $m0 . '-01') }}" max="{{ date($y . '-' . $m0 . '-' . $d) }}"
+                                                   value="{{$defaultED}}"
+                                                   class="form-control form-control-sm w-100" name="effectiveDate"
+                                                   placeholder="Effective Date" required>
+                                        </div>
+                                        <div class="col-6">
+                                            <label class="text-sm text-secondary mb-1">Seconds</label>
+                                            <input type="number" min="75" max="300" class="form-control form-control-sm w-100 cm-time-value" name="timeInSeconds"
+                                                   value="75" placeholder="Time (secs.)" required>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="mb-2 border border-info p-2 mt-2 bg-light">
+                                    <span>I have had interactive communication with <b>{{$iPatient->client_name}}</b>.</span>
+                                    <div class="d-flex border-top mt-2">
+                                        <label class="mt-2 mb-0 d-inline-flex align-items-center mr-3">
+                                            <input type="radio" class="mr-2" name="didProInteractWithClientAboutRm" value="true" required>
+                                            <span>Yes</span>
+                                        </label>
+                                        <label class="mt-2 mb-0 d-inline-flex align-items-center">
+                                            <input type="radio" class="mr-2" name="didProInteractWithClientAboutRm" value="false" required>
+                                            <span>No</span>
+                                        </label>
+                                    </div>
+                                </div>
+                                <div class="mb-2">
+                                    <label class="text-sm text-secondary mb-1">Memo</label>
+                                    <textarea class="form-control form-control-sm w-100" name="contentText"
+                                              required>Interacted with the patient</textarea>
+                                </div>
+                                <div class="d-flex align-items-center">
+                                    <button class="btn btn-sm btn-primary mr-2" submit>Save</button>
+                                    <button class="btn btn-sm btn-default mr-2 border" cancel>Cancel</button>
+                                </div>
+                            </form>
+                        </div>
+                    @endif
+                </div>
+            </td>
+        @endif
+        <td>
+            <div class="d-flex align-items-baseline">
+                <i class="mr-1 text-sm fa {{$iPatient->number_of_days_with_remote_measurements >= 16 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                <span class="sort-data">{{$iPatient->number_of_days_with_remote_measurements ?: 0}}</span>
+                @if($iPatient->number_of_days_with_remote_measurements < 16)
+                    <div moe relative class="ml-2">
+                        <a href="#" start show class="text-sm">SMS</a>
+                        <form url="/api/clientSms/createOutgoing" right="" class="mcp-theme-1" noreload="" style="display: none;">
+                            <input type="hidden" name="uid" value="{{ $iPatient->client_uid }}">
+                            <div class="mb-2">
+                                <label for="" class="text-sm text-secondary mb-1">Cell Number</label>
+                                <input type="text" class="form-control form-control-sm" name="cellNumber" value="{{$iPatient->cell_number}}">
+                            </div>
+                            <div class="mb-2">
+                                <label for="" class="text-sm text-secondary mb-1">Message</label>
+                                <textarea rows="5" class="form-control form-control-sm" name="message">Hi! This is {{$pro->displayName(true)}}, from Cardio 1st. Please check your blood pressure.</textarea>
+                            </div>
+                            <div class="d-flex align-items-center">
+                                <button class="btn btn-sm btn-primary mr-2" submit="">Send</button>
+                                <button class="btn btn-sm btn-default mr-2 border" cancel="">Cancel</button>
+                            </div>
+                        </form>
+                    </div>
+                @endif
+            </div>
+        </td>
+        @if($strategy === 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM')
+            <td>
+                <div class="d-flex align-items-baseline">
+                    @if($mode === 'mcp')
+                        <span class="sort-data">{{$iPatient->rm_num_measurements_not_stamped_by_mcp}}</span>
+                        @if($iPatient->rm_num_measurements_not_stamped_by_mcp)
+                            <a href="{{ route('practice-management.rpm_work_matrix') }}?patientUid={{$iPatient->client_uid}}&careMonthUid={{$iPatient->care_month_uid}}"
+                               native target="_blank"
+                               open-in-stag-popup
+                               update-parent="refresh-rpm-row-{{$trIndex}}"
+                               popup-style="tall overflow-visible"
+                               class="ml-2 text-sm"
+                               mc-initer="rpm-work-matrix"
+                               title="RPM Work Matrix">
+                                View
+                            </a>
+                        @endif
+                    @elseif($mode === 'rmm')
+                        <span class="sort-data">{{$iPatient->rm_num_measurements_not_stamped_by_rmm}}</span>
+                        @if($iPatient->rm_num_measurements_not_stamped_by_rmm)
+                            <a href="{{ route('practice-management.rpm_work_matrix') }}?patientUid={{$iPatient->client_uid}}&careMonthUid={{$iPatient->care_month_uid}}"
+                               native target="_blank"
+                               open-in-stag-popup
+                               update-parent="refresh-rpm-row-{{$trIndex}}"
+                               popup-style="tall overflow-visible"
+                               class="ml-2 text-sm"
+                               mc-initer="rpm-work-matrix"
+                               title="RPM Work Matrix">
+                                View
+                            </a>
+                        @endif
+                    @endif
+                </div>
+            </td>
+        @endif
+    @elseif($mode === 'rme')
+        <td>
+            <div class="d-flex align-items-baseline">
+                <i class="mr-1 text-sm fa {{$iPatient->number_of_days_with_remote_measurements >= 16 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                <span class="sort-data">{{$iPatient->number_of_days_with_remote_measurements ?: 0}}</span>
+                @if($iPatient->number_of_days_with_remote_measurements < 16)
+                    <div moe relative class="ml-2">
+                        <a href="#" start show class="text-sm">SMS</a>
+                        <form url="/api/clientSms/createOutgoing" right="" class="mcp-theme-1" noreload="" style="display: none;">
+                            <input type="hidden" name="uid" value="{{ $iPatient->client_uid }}">
+                            <div class="mb-2">
+                                <label for="" class="text-sm text-secondary mb-1">Cell Number</label>
+                                <input type="text" class="form-control form-control-sm" name="cellNumber" value="{{$iPatient->cell_number}}">
+                            </div>
+                            <div class="mb-2">
+                                <label for="" class="text-sm text-secondary mb-1">Message</label>
+                                <textarea rows="5" class="form-control form-control-sm" name="message">Hi! This is {{$pro->displayName(true)}}, from Cardio 1st. Please check your blood pressure.</textarea>
+                            </div>
+                            <div class="d-flex align-items-center">
+                                <button class="btn btn-sm btn-primary mr-2" submit="">Send</button>
+                                <button class="btn btn-sm btn-default mr-2 border" cancel="">Cancel</button>
+                            </div>
+                        </form>
+                    </div>
+                @endif
+            </div>
+        </td>
+    @endif
+    <td>
+        @if($mode === 'mcp')
+            <div class="d-flex align-items-baseline">
+                <i class="mr-1 text-sm fa {{$iPatient->rm_total_time_in_seconds_by_mcp >= 1200 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                <span class="text-nowrap">{{round($iPatient->rm_total_time_in_seconds_by_mcp / 60)}}m {{round($iPatient->rm_total_time_in_seconds_by_mcp % 60)}}s</span>
+                <span class="sort-data d-none">{{$iPatient->rm_total_time_in_seconds_by_mcp}}</span>
+            </div>
+        @elseif($mode === 'rmm')
+            <div class="d-flex align-items-baseline">
+                <i class="mr-1 text-sm fa {{$iPatient->rm_total_time_in_seconds_by_rmm_pro >= 1200 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                <span class="text-nowrap">{{round($iPatient->rm_total_time_in_seconds_by_rmm_pro / 60)}}m {{round($iPatient->rm_total_time_in_seconds_by_rmm_pro % 60)}}s</span>
+                <span class="sort-data d-none">{{$iPatient->rm_total_time_in_seconds_by_rmm_pro}}</span>
+            </div>
+        @elseif($mode === 'rmm')
+            <div class="d-flex align-items-baseline">
+                <i class="mr-1 text-sm fa {{$iPatient->rm_total_time_in_seconds_by_rme_pro >= 1200 ? 'fa-check text-success' : 'fa-exclamation-triangle text-danger on-hover-opaque'}}"></i>
+                <span class="text-nowrap">{{round($iPatient->rm_total_time_in_seconds_by_rme_pro / 60)}}m {{round($iPatient->rm_total_time_in_seconds_by_rme_pro % 60)}}s</span>
+                <span class="sort-data d-none">{{$iPatient->rm_total_time_in_seconds_by_rme_pro}}</span>
+            </div>
+        @endif
+    </td>
+    <td>
+        @if($mode === 'mcp')
+            @if($lastVisitWithin90Days && $iPatient->has_mcp_interacted_with_client_about_rm && $iPatient->number_of_days_with_remote_measurements >= 16 && $iPatient->rm_total_time_in_seconds_by_mcp >= 1200)
+                <span class="text-success font-weight-bold">
+                    <i class="fa fa-check"></i>
+                    Yes
+                </span>
+            @else
+                <span class="text-danger font-weight-normal">
+                    Not yet
+                </span>
+            @endif
+        @elseif($mode === 'rmm')
+            @if($lastVisitWithin90Days && $iPatient->has_mcp_interacted_with_client_about_rm && $iPatient->number_of_days_with_remote_measurements >= 16 && $iPatient->rm_total_time_in_seconds_by_rmm_pro >= 1200)
+                <span class="text-success font-weight-bold">
+                    <i class="fa fa-check"></i>
+                    Yes
+                </span>
+            @else
+                <span class="text-danger font-weight-normal">
+                    Not yet
+                </span>
+            @endif
+        @elseif($mode === 'rme')
+            @if($lastVisitWithin90Days && $iPatient->number_of_days_with_remote_measurements >= 16)
+                <span class="text-success font-weight-bold">
+                    <i class="fa fa-check"></i>
+                    Yes
+                </span>
+            @else
+                <span class="text-danger font-weight-normal">
+                    Not yet
+                </span>
+            @endif
+        @endif
+    </td>
+</tr>

+ 258 - 0
resources/views/app/practice-management/rpm-matrix-by-pro-type.blade.php

@@ -0,0 +1,258 @@
+@extends ('layouts/template')
+
+@section('content')
+    <?php
+    if(!function_exists('strategy_display')) {
+        function strategy_display($_strategy, $_mode) {
+            switch ($_strategy) {
+                case 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM':
+                    return '16 meas. days + 20 mins + comm. done during the caremonth';
+                case 'X16_DAYS':
+                    return '16 meas. days';
+                default:
+                    return '-';
+            }
+        }
+    }
+    ?>
+    <style>
+        #admin-table-rm-matrix_wrapper {
+            padding-top: 10px;
+        }
+    </style>
+    <link rel="stylesheet" href="https://cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css">
+    <script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
+    <style>
+        #table-rm-matrix_length, #table-rm-matrix_info {
+            padding-left: 0.5rem;
+        }
+        #table-rm-matrix_filter {
+            padding-right: 0.5rem;
+        }
+        #table-rm-matrix_paginate {
+            padding: 0.5rem;
+        }
+    </style>
+    <div class="p-3 mcp-theme-1" id="practice-remote-monitoring" v-cloak>
+
+        <div class="card">
+
+            <div class="card-header px-2 py-2 d-flex align-items-baseline">
+                <span class="mr-4">
+                    <span class="font-size-14">Remote Monitoring</span>
+                    <i class="fas fa-arrow-right text-sm mx-1"></i>
+                    <b class="font-size-14">{{friendly_month(date((request()->input('y') ?: 'Y') . '-' . (request()->input('m') ?: 'm') . '-d'))}}</b>
+                </span>
+                <?php
+
+                $mStr = request()->input('m') ? request()->input('m') : date('m');
+                $yStr = request()->input('y') ? request()->input('y') : date('Y');
+                $rcmStartDate = $yStr . '-' . $mStr . '-' . '01';
+                $m = +$mStr;
+                $y = +$yStr;
+                ?>
+                <a href="{{ route('practice-management.rpm_work_matrix') }}?m={{$mStr}}&y={{$yStr}}"
+                   native target="_blank"
+                   open-in-stag-popup
+                   update-parent
+                   popup-style="tall overflow-visible"
+                   class="mr-4 font-weight-bold"
+                   mc-initer="rpm-work-matrix"
+                   title="RPM Work Matrix">
+                    RPM Work Matrix
+                </a>
+                <span class="mr-2">Strategy:</span>
+                @if($mode === 'mcp')
+                    {{strategy_display($pro->mcp_rpm_payment_strategy, $mode)}}
+                    <?php $strategy = $pro->mcp_rpm_payment_strategy; ?>
+                @elseif($mode === 'rmm')
+                    {{strategy_display($pro->rme_payment_strategy, $mode)}}
+                    <?php $strategy = $pro->rmm_payment_strategy; ?>
+                @elseif($mode === 'rmm')
+                    {{strategy_display($pro->rmm_payment_strategy, $mode)}}
+                    <?php $strategy = $pro->rme_payment_strategy; ?>
+                @endif
+                <form class="ml-auto d-inline-flex flex-nowrap align-items-center" action="" method="GET">
+                    <span class="mr-2">Month</span>
+                    <select class="form-control form-control-sm min-width-unset width-100px mr-3" name="m"
+                            onchange="fastLoad('{{route('practice-management.rpm-matrix-' . $mode)}}?' + $(this).closest('form').serialize())">
+                        <option value="01" {{$m === 1 ? 'selected' : ''}}>Jan</option>
+                        <option value="02" {{$m === 2 ? 'selected' : ''}}>Feb</option>
+                        <option value="03" {{$m === 3 ? 'selected' : ''}}>Mar</option>
+                        <option value="04" {{$m === 4 ? 'selected' : ''}}>Apr</option>
+                        <option value="05" {{$m === 5 ? 'selected' : ''}}>May</option>
+                        <option value="06" {{$m === 6 ? 'selected' : ''}}>Jun</option>
+                        <option value="07" {{$m === 7 ? 'selected' : ''}}>Jul</option>
+                        <option value="08" {{$m === 8 ? 'selected' : ''}}>Aug</option>
+                        <option value="09" {{$m === 9 ? 'selected' : ''}}>Sep</option>
+                        <option value="10" {{$m === 10 ? 'selected' : ''}}>Oct</option>
+                        <option value="11" {{$m === 11 ? 'selected' : ''}}>Nov</option>
+                        <option value="12" {{$m === 12 ? 'selected' : ''}}>Dec</option>
+                    </select>
+                    <span class="mr-2">Year</span>
+                    <select class="form-control form-control-sm min-width-unset width-100px" name="y"
+                            onchange="fastLoad('{{route('practice-management.rpm-matrix-' . $mode)}}?' + $(this).closest('form').serialize())">
+                        <option value="2020" {{$y === 2020 ? 'selected' : ''}}>2020</option>
+                        <option value="2021" {{$y === 2021 ? 'selected' : ''}}>2021</option>
+                        <option value="2022" {{$y === 2022 ? 'selected' : ''}}>2022</option>
+                    </select>
+                </form>
+            </div>
+
+            <?php $rc = request()->input('rc') ? request()->input('rc') : 1; ?>
+
+            <div class="card-body p-0">
+                <div class="d-flex align-items-start m-0">
+                    <div class="flex-grow-1 px-0">
+                        <?php $trIndex = 0; ?>
+                        @foreach ($patients as $iPatient)
+                            <script>
+                                addMCHook(
+                                    'refresh-rpm-row-{{$trIndex}}',
+                                    function () {
+                                        refreshRpmRow({{$trIndex}});
+                                    }
+                                );
+                            </script>
+                            <?php $trIndex++; ?>
+                        @endforeach
+                        <table class="table table-sm table-striped table-hover p-0 m-0" id="table-rm-matrix">
+                            <thead class="bg-light">
+                            <tr>
+                                <!--<th class="border-0 pl-2">Name</th>
+                                <th class="border-0">DOB</th>
+                                <th class="border-0">RPM?</th>
+                                <th class="border-0">Cell. BP?</th>
+                                <th class="border-0">Cell. Scale?</th>
+                                <th class="border-0">Last BP</th>
+                                <th class="border-0">Last Wt</th>
+                                <th class="border-0">Days Since Last Visit</th>
+                                <th class="border-0">Interacted?</th>
+                                <th class="border-0">#Meas. Days</th>
+                                <th class="border-0">#Unstamped</th>
+                                <th class="border-0 {{$strategy === 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM' ? '' : 'd-nonex'}}">#RPM Mins.</th>
+                                <th class="border-0">Billable</th>-->
+
+                                <th class="border-0 pl-2">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => 'Name', 'key' => 'client_name'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => 'DOB', 'key' => 'dob'])</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => 'RPM?', 'key' => 'is_enrolled_in_rm'])</th>
+                                <th class="border-0 text-secondary">Cell. BP?</th>
+                                <th class="border-0 text-secondary">Cell. Scale?</th>
+                                <th class="border-0 text-secondary">Latest BP</th>
+                                <th class="border-0 text-secondary">Latest Wt</th>
+                                <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => 'Days Since Last Visit', 'key' => 'most_recent_completed_mcp_note_date'])</th>
+                                @if($mode === 'mcp' || $mode === 'rmm')
+                                    @if($strategy === 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM')
+                                        <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => 'Interacted?', 'key' => 'has_mcp_interacted_with_client_about_rm'])</th>
+                                    @endif
+                                    <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#Meas. Days', 'key' => 'number_of_days_with_remote_measurements'])</th>
+                                    @if($strategy === 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM')
+                                        <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#Unstamped', 'key' => 'rm_num_measurements_not_stamped_by_mcp'])</th>
+                                    @endif
+                                    @if($mode === 'mcp')
+                                        <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#MCP Mins.', 'key' => 'rm_total_time_in_seconds_by_mcp'])</th>
+                                    @else
+                                        <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#RMM Mins.', 'key' => 'rm_total_time_in_seconds_by_rmm_pro'])</th>
+                                     @endif
+                                @elseif($mode === 'rme')
+                                    <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#Meas. Days', 'key' => 'number_of_days_with_remote_measurements'])</th>
+                                    <th class="border-0">@include('app.practice-management._sort_header', ['route' => route("practice-management.rpm-matrix-" . $mode), 'label' => '#RME Mins.', 'key' => 'rm_total_time_in_seconds_by_rme_pro'])</th>
+                                @endif
+                                <th class="border-0 text-secondary"">Billable</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <?php $trIndex = 0; ?>
+                            @foreach ($patients as $iPatient)
+                                <?php
+
+                                $daysDiff = -1;
+                                if($iPatient->most_recent_completed_mcp_note_date) {
+                                    $careMonthLastDay = date_add(date_create($rcmStartDate), date_interval_create_from_date_string("1 month"));
+                                    $careMonthLastDay = date_sub($careMonthLastDay, date_interval_create_from_date_string("1 day"));
+                                    $daysDiff = date_diff($careMonthLastDay, date_create($iPatient->most_recent_completed_mcp_note_date))->days;
+                                }
+                                $lastVisitWithin90Days = ($daysDiff !== -1 && $daysDiff <= 90);
+
+                                ?>
+                                @include('app.practice-management.remote-monitoring-row-markup-by-pro-type')
+                                <?php $trIndex++; ?>
+                            @endforeach
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script>
+        (function() {
+            let dataTableInst = null;
+            window.refreshRpmRow = function(_index) {
+                let tr = $('#table-rm-matrix tbody tr:eq(' + _index + ')');
+                if(!tr.length) return;
+                let clientUid = tr.attr('data-client-uid'), careMonthUid = tr.attr('data-care-month-uid');
+                $.get('/rpm-matrix-row-{{$mode}}?m={{$mStr}}&y={{$yStr}}&clientUid=' + clientUid + '&careMonthUid=' + careMonthUid + '&trIndex=' + _index, _data => {
+                    let row = $(_data);
+                    @if(request()->input('dt'))
+                        row.find('>td').each(function(_columnIndex) {
+                            dataTableInst.cell(_index, _columnIndex).data(this.innerHTML); //.draw();
+                        });
+                    @else
+                        tr.replaceWith(row);
+                    @endif
+                    $('#practice-remote-monitoring [moe][initialized]').removeAttr('initialized');
+                    initMoes();
+                    tr.addClass('post-refresh-highlight');
+                    setTimeout(function() {
+                        tr.removeClass('post-refresh-highlight');
+                    }, 1000);
+                });
+            }
+            function init() {
+                @if(request()->input('dt'))
+                dataTableInst = $('#table-rm-matrix').DataTable({
+                    paging: false,
+                    columnDefs: [
+                        {
+                            targets: [0, 8],
+                            type: 'string',
+                            render: function (data, type, row, meta) {
+                                if(type === 'sort') {
+                                    return $(data).find('.sort-data').first().text();
+                                }
+                                return data;
+                            },
+                        },
+                        {targets: 1, type: 'date'},
+                        {
+                            targets: 7,
+                            type: 'num',
+                            render: function (data, type, row, meta) {
+                                if(type === 'sort') {
+                                    return $(data).find('.sort-data').first().text();
+                                }
+                                return data;
+                            },
+                        },
+                        {
+                            targets: [5, 6, 10, 11, 12],
+                            type: 'num',
+                            render: function (data, type, row, meta) {
+                                if(type === 'sort') {
+                                    return +($(data).find('.sort-data').first().text());
+                                }
+                                return data;
+                            },
+                        },
+                    ]
+                });
+                @endif
+                $('#practice-remote-monitoring').removeAttr('v-cloak');
+                $('#practice-remote-monitoring [moe][initialized]').removeAttr('initialized');
+                initMoes();
+            }
+            addMCInitializer('practice-remote-monitoring', init, '#practice-remote-monitoring');
+        }).call(window);
+    </script>
+@endsection

+ 9 - 1
resources/views/layouts/template.blade.php

@@ -129,7 +129,15 @@
                     </a>
                     <div class="dropdown-menu mcp-theme-1 no-overflow-menu p-0" aria-labelledby="practice-management">
                         @if($pro->pro_type !== 'ADMIN')
-                            <a class="dropdown-item" href="{{ route('practice-management.remote-monitoring') }}">Remote Monitoring</a>
+                            @if($pro->is_enrolled_as_mcp)
+                            <a class="dropdown-item" href="{{ route('practice-management.rpm-matrix-mcp') }}">RPM (MCP)</a>
+                            @endif
+                            @if($pro->is_considered_for_rmm)
+                            <a class="dropdown-item" href="{{ route('practice-management.rpm-matrix-rmm') }}">RPM (RMM)</a>
+                            @endif
+                            @if($pro->is_considered_for_rme)
+                            <a class="dropdown-item" href="{{ route('practice-management.rpm-matrix-rme') }}">RPM (RME)</a>
+                            @endif
                             <a class="dropdown-item" href="{{ route('practice-management.client-ccm-rm-status') }}">Client RM Status</a>
                         @else
                             <a class="dropdown-item" href="{{ route('practice-management.remote-monitoring-admin') }}">Remote Monitoring (admin)</a>

+ 7 - 0
routes/web.php

@@ -346,6 +346,10 @@ Route::middleware('pro.auth')->group(function () {
         Route::get('remote-monitoring-admin', 'PracticeManagementController@remoteMonitoringAdmin')->name('remote-monitoring-admin');
         Route::get('remote-monitoring-admin-count', 'PracticeManagementController@remoteMonitoringAdminCount')->name('remote-monitoring-admin-count');
 
+        Route::get('rpm-mcp', 'PracticeManagementController@remoteMonitoringMCP')->name('rpm-matrix-mcp');
+        Route::get('rpm-rmm', 'PracticeManagementController@remoteMonitoringRMM')->name('rpm-matrix-rmm');
+        Route::get('rpm-rme', 'PracticeManagementController@remoteMonitoringRME')->name('rpm-matrix-rme');
+
 
         //stat tree stuff
         Route::name('clauses.')->prefix('clauses/')->group(function () {
@@ -641,6 +645,9 @@ Route::middleware('pro.auth')->group(function () {
     // rpm matrix single row
     Route::get('/rpm-matrix-row', 'PracticeManagementController@remoteMonitoring_Row');
 
+    Route::get('rpm-matrix-row-mcp', 'PracticeManagementController@remoteMonitoring_RowMCP')->name('rpm-matrix-row-mcp');
+    Route::get('rpm-matrix-row-rmm', 'PracticeManagementController@remoteMonitoring_RowRMM')->name('rpm-matrix-row-rmm');
+    Route::get('rpm-matrix-row-rme', 'PracticeManagementController@remoteMonitoring_RowRME')->name('rpm-matrix-row-rme');
 
     Route::get('/appointment-confirmation-history/{appointment}', 'AppointmentController@appointmentConfirmationHistory')->name('appointment-confirmation-history');