Samson Mutunga 3 anni fa
parent
commit
31a7401eea

+ 19 - 2
app/Http/Controllers/DnaController.php

@@ -69,6 +69,17 @@ class DnaController extends Controller
         return view('app.dna.patients', compact('patients', 'filters'));
     }
 
+    public function encounters(Request $request)
+    {
+        $filters = $request->all();
+        $notes = Note::query();
+        $notes = $notes->where('ally_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $notes, 'effective_time', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $notes, 'new_or_fu_or_na', 'new_or_fu_or_na');
+        $notes = $notes->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.encounters', compact('notes', 'filters'));
+    }
+
     public function notes(Request $request)
     {
         $data = [];
@@ -77,8 +88,14 @@ class DnaController extends Controller
 
     public function appointments(Request $request)
     {
-        $data = [];
-        return view('app.dna.appointments', $data);
+        $filters = $request->all();
+        $appointments = Appointment::select('appointment.*')
+                        ->join('client', 'client.id', '=', 'appointment.client_id')
+                        ->where('client.default_na_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $appointments, 'raw_date', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $appointments, 'status', 'status');
+        $appointments = $appointments->orderBy('end_time', 'DESC')->paginate(20);
+        return view('app.dna.appointments', compact('appointments', 'filters'));
     }
 
     public function bills(Request $request)

+ 168 - 0
resources/views/app/dna/DnaController.php

@@ -0,0 +1,168 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Appointment;
+use App\Models\BDTDevice;
+use App\Models\CareMonth;
+use App\Models\Client;
+use App\Models\ClientBDTDevice;
+use App\Models\ClientInfoLine;
+use App\Models\Erx;
+use App\Models\Facility;
+use App\Models\Handout;
+use App\Models\IncomingReport;
+use App\Models\MBClaim;
+use App\Models\MBPayer;
+use App\Models\Note;
+use App\Models\NoteTemplate;
+use App\Models\Pro;
+use App\Models\Product;
+use App\Models\ProProAccess;
+use App\Models\SectionTemplate;
+use App\Models\Shipment;
+use App\Models\SupplyOrder;
+use App\Models\Ticket;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\File;
+
+use Illuminate\Support\Facades\Http;
+use PDF;
+
+class DnaController extends Controller
+{
+
+    public function patients(Request $request)
+    {
+        $filters = $request->all();
+        $patients = Client::whereNull('shadow_pro_id')->where('default_na_pro_id', $this->performer->pro->id);
+
+        if ($request->input('name')) {
+            $name = trim($request->input('name'));
+            if ($name) {
+                $patients = $patients->where(function ($q) use ($name) {
+                    $q->where('name_first', 'ILIKE', '%' . $name . '%')
+                        ->orWhere('name_last', 'ILIKE', '%' . $name . '%');
+                });
+            }
+        }
+
+        $this->filterMultiQuery($request, $patients, 'age_in_years', 'age_category', 'age_value_1', 'age_value_2');
+        $this->filterSimpleQuery($request, $patients, 'sex', 'sex');
+        $this->filterMultiQuery($request, $patients, 'usual_bmi_max', 'bmi_category', 'bmi_value_1', 'bmi_value_2');
+        $this->filterMultiQuery($request, $patients, 'most_recent_completed_mcp_note_date', 'last_visit_category', 'last_visit_value_1', 'last_visit_value_2'); 
+        $this->filterMultiQuery($request, $patients, 'next_mcp_appointment_date', 'next_appointment_category', 'next_appointment_value_1', 'next_appointment_value_2');
+
+        switch($request->input('status')) {
+            case 'ACTIVE':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', true);
+                break;
+            case 'AWAITING_VISIT':
+                $patients->where('is_active', true)->where('has_mcp_done_onboarding_visit', false);
+                break;
+            case 'INACTIVE':
+                $patients->where('is_active', '<>', true);
+                break;
+        }
+        $patients = $patients->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.patients', compact('patients', 'filters'));
+    }
+
+    public function encounters(Request $request)
+    {
+        $filters = $request->all();
+        $notes = Note::query();
+        $notes = $notes->where('ally_pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $notes, 'effective_time', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $notes, 'new_or_fu_or_na', 'new_or_fu_or_na');
+        $notes = $notes->orderBy('created_at', 'DESC')->paginate(20);
+        return view('app.dna.encounters', compact('notes', 'filters'));
+    }
+
+    public function notes(Request $request)
+    {
+        $data = [];
+        return view('app.dna.notes', $data);
+    }
+
+    public function appointments(Request $request)
+    {
+        $filters = $request->all();
+        $appointments = Appointment::where('pro_id', $this->performer->pro->id);
+        $this->filterMultiQuery($request, $appointments, 'raw_date', 'date_category', 'date_value_1', 'date_value_2');
+        $this->filterSimpleQuery($request, $appointments, 'status', 'status');
+        $appointments = $appointments->orderBy('end_time', 'DESC')->paginate(20);
+        return view('app.dna.appointments', compact('appointments', 'filters'));
+    }
+
+    public function bills(Request $request)
+    {
+        $data = [];
+        return view('app.dna.bills', $data);
+    }
+
+    public function erx_and_orders(Request $request)
+    {
+        $data = [];
+        return view('app.dna.erx_and_orders', $data);
+    }
+
+    public function reports(Request $request)
+    {
+        $data = [];
+        return view('app.dna.reports', $data);
+    }
+
+    public function supply_orders(Request $request)
+    {
+        $data = [];
+        return view('app.dna.supply_orders', $data);
+    }
+
+    public function new_patients_awaiting_visit(Request $request){
+        $data = [];
+        return view('app.dna.new_patients_awaiting_visit', $data);
+    }
+    public function notes_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.notes_pending_signature', $data);
+    }
+    public function notes_pending_billing(Request $request){
+        $data = [];
+        return view('app.dna.notes_pending_billing', $data);
+    }
+    public function reports_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.reports_pending_signature', $data);
+    }
+    public function patients_without_appointments(Request $request){
+        $data = [];
+        return view('app.dna.patients_without_appointments', $data);
+    }
+    public function patients_overdue_for_visit(Request $request){
+        $data = [];
+        return view('app.dna.patients_overdue_for_visit', $data);
+    }
+    public function cancelled_appointments_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_appointments_pending_review', $data);
+    }
+    public function cancelled_bills_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_bills_pending_review', $data);
+    }
+    public function cancelled_supply_orders_pending_review(Request $request){
+        $data = [];
+        return view('app.dna.cancelled_supply_orders_pending_review', $data);
+    }
+    public function erx_and_orders_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.erx_and_orders_pending_signature', $data);
+    }
+    public function supply_orders_pending_signature(Request $request){
+        $data = [];
+        return view('app.dna.supply_orders_pending_signature', $data);
+    }
+
+}

+ 92 - 2
resources/views/app/dna/appointments.blade.php

@@ -1,5 +1,95 @@
 @extends ('layouts/template')
 
 @section('content')
-    <h1>Hi</h1>
-@endsection
+<div class="p-3 mcp-theme-1" id="patients-list">
+    <div class="card">
+
+        <div class="card-header px-3 py-2 d-flex align-items-center">
+            <strong class="mr-4">
+                <i class="fas fa-calendar-alt"></i>
+                Appointments
+            </strong>
+        </div>
+
+        <div class="card-body p-0">
+            <div class="p-3">
+                @include('app.dna.appointments_filters')
+            </div>
+            <table class="table table-condensed p-0 m-0">
+                <thead class="bg-light">
+                    <tr>
+                        <th class="px-3 border-0">Chart #</th>
+                        <th class="px-3 border-0">Name</th>
+                        <th class="px-3 border-0">DOB</th>
+                        <th class="px-3 border-0">Age</th>
+                        <th class="px-3 border-0">Sex</th>
+                        <th class="px-3 border-0">Insurance</th>
+                        <th class="px-3 border-0">MCP</th>
+                        <th class="px-3 border-0">Time</th>
+                        <th class="px-3 border-0">Status</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    @foreach($appointments as $appointment)
+                    <tr>
+
+                        <td class="px-3 text-nowrap">
+                            <a native target="_blank" href="{{route('patients.view.dashboard', $appointment->client)}}">
+                                {{$appointment->client->chart_number}}
+                            </a>
+                        </td>
+                        <td class="px-3 text-nowrap">
+                            <a native target="_blank" href="{{route('patients.view.dashboard', $appointment->client)}}">
+                                {{$appointment->client->displayName()}}
+                            </a>
+                        </td>
+                        <td class="text-nowrap">{{ friendly_date_time($appointment->client->dob, false) }}</td>
+                        <td>{{ $appointment->client->age_in_years ?  $appointment->client->age_in_years : '-' }}</td>
+                        <td>{{ $appointment->client->sex }}</td>
+                        <td>
+                            <?php $coverageStatus = $appointment->client->getPrimaryCoverageStatus(); ?>
+                            <div class="text-nowrap">
+                                @if($coverageStatus === 'YES')
+                                <i class="fa fa-check-circle text-success" data-toggle="tooltip" data-placement="bottom" title="Covered"></i>
+                                @elseif($coverageStatus === 'NO')
+                                <i class="fa fa-times text-danger" data-toggle="tooltip" data-placement="bottom" title="Not Covered"></i>
+                                @else
+                                <i class="fa fa-exclamation-triangle text-warning-mellow" data-toggle="tooltip" data-placement="bottom" title="Unknown"></i>
+                                @endif
+                                <?php $coverage = $appointment->client->getPrimaryCoverage(); ?>
+                                @if($coverage)
+                                {{$coverage->insuranceDisplayName()}}
+                                @endif
+                            </div>
+                        </td>
+                        <td>{{ $appointment->client->mcp->displayName() }}</td>
+                        <td>
+                            <a href="/patients/view/{{$appointment->client->uid}}/calendar/{{$appointment->uid}}" class="font-weight-bold text-nowrap">
+                                {{friendlier_date_time($appointment->raw_date . ' ' . $appointment->raw_start_time)}}
+                            </a>
+                        </td>
+                        <td class="px-2">
+                            {{ $appointment->status }}
+                            @if($appointment->status_memo)
+                            <hr>
+                            {{$appointment->status_memo}}
+                            @endif
+                        </td>
+                    </tr>
+                    @endforeach
+
+                    @if(count($appointments) === 0)
+                    <tr>
+                        <td colspan="6">No records found!</td>
+                    </tr>
+                    @endif
+                </tbody>
+
+            </table>
+            <div class="ml-2 mt-2">
+                {{ $appointments->appends(request()->input())->links() }}
+            </div>
+        </div>
+    </div>
+</div>
+@endsection

+ 111 - 0
resources/views/app/dna/appointments_filters.blade.php

@@ -0,0 +1,111 @@
+<style>
+	#dna-appointments-filters label {
+		font-weight: bold;
+	}
+
+	#dna-appointments-filters .mw-100px {
+		min-width: 100px;
+	}
+	.filter-container{
+		display: flex;
+		align-items: flex-start;
+		flex-wrap: wrap;
+	}
+	.filter-container >div {
+		width: 165px;
+	}
+	.filter-container >div:not(:last-child) {
+		margin-right: 15px;
+	}
+</style>
+<form id="dna-appointments-filters" method="GET" action="{{ route('dna.appointments') }}" class="filter-container" v-cloak>
+	   <!-- DATE -->
+	<div class="">
+		<div class="form-group">
+			<label>Date:</label>
+			<select name="date_category" class="form-control input-sm" v-model="filters.date_category">
+				<option value="">All</option>
+				<option value="EXACTLY">Exactly</option>
+				<option value="LESS_THAN">Less Than</option>
+				<option value="GREATER_THAN">Greater Than</option>
+				<option value="BETWEEN">Between</option>
+				<option value="NOT_BETWEEN">Not Between</option>
+			</select>
+			<div v-show="filters.date_category" class="mt-2">
+				<div>
+					<input  name="date_value_1" v-model="filters.date_value_1" type="date" class="form-control input-sm"/>
+				</div>
+				<div v-show="filters.date_category === 'BETWEEN' || filters.date_category === 'NOT_BETWEEN'" class="mt-2">
+					<input name="date_value_2" v-model="filters.date_value_2" type="date" class="form-control input-sm"/>
+				</div>
+			</div>
+		</div>
+	</div>
+	<!-- STATUS -->
+	<div class="">
+		<div class="form-group">
+			<label>Status:</label>
+			<select name="status" class="form-control input-sm" v-model="filters.status">
+				<option value="">All</option>
+				<option value="PENDING">PENDING</option>
+				<option value="CONFIRMED">CONFIRMED</option>
+				<option value="CANCELLED">CANCELLED</option>
+				<option value="COMPLETED">COMPLETED</option>
+			</select>
+		</div>
+	</div>
+
+	<div class="">
+		<div class="form-group">
+			<label>&nbsp;</label>
+			<div class="d-flex">
+				<button type="submit" v-on:click.prevent="doSubmit()" class="btn btn-primary btn-sm mr-2"><i class="fas fa-filter"></i> Filter</button>
+				<a href="#" v-on:click.prevent="fastLoad('{{route('dna.appointments')}}')" class="btn btn-link btn-sm text-danger">Clear Filters</a>
+			</div>
+		</div>
+	</div>
+</form>
+
+<?php
+$loadedFilters = $filters;
+$allFilterKeys = [
+	'date_category',
+	'date_value_1',
+	'date_value_2',
+	'status'
+];
+for ($i=0; $i < count($allFilterKeys); $i++) {
+	if (!isset($loadedFilters[$allFilterKeys[$i]]) || !$loadedFilters[$allFilterKeys[$i]]) {
+		$loadedFilters[$allFilterKeys[$i]] = '';
+	}
+}
+?>
+
+<script>
+	(function() {
+		function init() {
+			window.apapp = new Vue({
+				el: '#dna-appointments-filters',
+				delimiters: ['@{{', '}}'],
+				data: {
+					filters: <?= json_encode($loadedFilters) ?>
+				},
+				methods: {
+					doSubmit: function() {
+						fastLoad('{{ route("dna.appointments") }}?' + $('#dna-appointments-filters').serialize());
+						return false;
+					},
+					init: function() {
+
+					}
+				},
+				mounted: function() {
+					this.init();
+				},
+			});
+
+
+		}
+		addMCInitializer('dna-appointments-filters', init, '#dna-appointments-filters');
+	})();
+</script>

+ 90 - 0
resources/views/app/dna/encounters.blade.php

@@ -0,0 +1,90 @@
+@extends ('layouts/template')
+
+@section('content')
+<div class="p-3 mcp-theme-1" id="patients-list">
+    <div class="card">
+
+        <div class="card-header px-3 py-2 d-flex align-items-center">
+            <strong class="mr-4">
+                <i class="fas fa-notes-medical"></i>
+                Encounters
+            </strong>
+        </div>
+
+        <div class="card-body p-0">
+            <div class="p-3">
+                @include('app.dna.encounters_filters')
+            </div>
+            <table class="table table-condensed p-0 m-0">
+                <thead class="bg-light">
+                    <tr>
+                        <th class="px-3 border-0">Chart #</th>
+                        <th class="px-3 border-0">Name</th>
+                        <th class="px-3 border-0">DOB</th>
+                        <th class="px-3 border-0">Age</th>
+                        <th class="px-3 border-0">Sex</th>
+                        <th class="px-3 border-0">Insurance</th>
+                        <th class="px-3 border-0">MCP</th>
+                        <th class="px-3 border-0">Visit Date</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    @foreach ($notes as $note)
+                    <tr class="{{ $note->is_cancelled ? 'cancelled-item always-clickable' : '' }}">
+                        <td class="px-3 text-nowrap">
+                            <a native target="_blank" href="{{route('patients.view.dashboard', $note->client)}}">
+                                {{$note->client->chart_number}}
+                            </a>
+                        </td>
+                        <td class="px-3 text-nowrap">
+                            <a native target="_blank" href="{{route('patients.view.dashboard', $note->client)}}">
+                                {{$note->client->displayName()}}
+                            </a>
+                        </td>
+                        <td class="text-nowrap">{{ friendly_date_time($note->client->dob, false) }}</td>
+                        <td>{{ $note->client->age_in_years ?  $note->client->age_in_years : '-' }}</td>
+                        <td>{{ $note->client->sex }}</td>
+                        <td>
+                            <?php $coverageStatus = $note->client->getPrimaryCoverageStatus(); ?>
+                            <div class="text-nowrap">
+                                @if($coverageStatus === 'YES')
+                                <i class="fa fa-check-circle text-success" data-toggle="tooltip" data-placement="bottom" title="Covered"></i>
+                                @elseif($coverageStatus === 'NO')
+                                <i class="fa fa-times text-danger" data-toggle="tooltip" data-placement="bottom" title="Not Covered"></i>
+                                @else
+                                <i class="fa fa-exclamation-triangle text-warning-mellow" data-toggle="tooltip" data-placement="bottom" title="Unknown"></i>
+                                @endif
+                                <?php $coverage = $note->client->getPrimaryCoverage(); ?>
+                                @if($coverage)
+                                {{$coverage->insuranceDisplayName()}}
+                                @endif
+                            </div>
+                        </td>
+                        <td>{{ $note->client->mcp->displayName() }}</td>
+                        <td class="px-2">
+                            <a href="/patients/view/{{ $note->client->uid }}/notes/view/{{ $note->uid }}" class="font-weight-bold">
+                                {{ friendly_date_time($note->effective_dateest, false) }}
+                            </a>
+                            @if(!!$note->visitTemplate)
+                            <span class="text-info font-weight-bold">*</span>
+                            @endif
+                            <span class="ml-1">{{ $note->is_cancelled ? '[cancelled]' : '' }}</span>
+                        </td>
+                    </tr>
+                    @endforeach
+
+                    @if(count($notes) === 0)
+                    <tr>
+                        <td colspan="8">No records found!</td>
+                    </tr>
+                    @endif
+                </tbody>
+
+            </table>
+            <div class="ml-2 mt-2">
+                {{ $notes->appends(request()->input())->links() }}
+            </div>
+        </div>
+    </div>
+</div>
+@endsection

+ 107 - 0
resources/views/app/dna/encounters_filters.blade.php

@@ -0,0 +1,107 @@
+<style>
+	#dna-notes-filters label {
+		font-weight: bold;
+	}
+
+	#dna-notes-filters .mw-100px {
+		min-width: 100px;
+	}
+	.filter-container{
+		display: flex;
+		align-items: flex-start;
+		flex-wrap: wrap;
+	}
+	.filter-container >div {
+		width: 165px;
+	}
+	.filter-container >div:not(:last-child) {
+		margin-right: 15px;
+	}
+</style>
+<form id="dna-notes-filters" method="GET" action="{{ route('dna.encounters') }}" class="filter-container" v-cloak>
+	<!-- DATE	 -->
+	<div>
+		<div class="form-group">
+			<label>Date:</label>
+			<select name="date_category" class="form-control input-sm" v-model="filters.date_category">
+				<option value="">All</option>
+				<option value="EXACTLY">Exactly</option>
+				<option value="LESS_THAN">Less Than</option>
+				<option value="GREATER_THAN">Greater Than</option>
+				<option value="BETWEEN">Between</option>
+				<option value="NOT_BETWEEN">Not Between</option>
+			</select>
+			<div v-show="filters.date_category" class="filter-child-container mt-2">
+				<div>
+					<input  name="date_value_1" v-model="filters.date_value_1" type="date" class="form-control input-sm"/>
+				</div>
+				<div v-show="filters.date_category === 'BETWEEN' || filters.date_category === 'NOT_BETWEEN'" class="mt-2">
+					<input name="date_value_2" v-model="filters.date_value_2" type="date" class="form-control input-sm"/>
+				</div>
+			</div>
+		</div>
+	</div>
+	<!-- STATUS -->
+	<div>
+		<div class="form-group">
+			<label>New/FU:</label>
+			<select name="new_or_fu_or_na" class="form-control input-sm" v-model="filters.new_or_fu_or_na">
+				<option value="">All</option>
+				<option value="NEW">New</option>
+				<option value="FU">FU</option>
+			</select>
+		</div>
+	</div>
+
+	<div>
+		<div class="form-group">
+			<label>&nbsp;</label>
+			<div class="d-flex">
+				<button type="submit"  v-on:click.prevent="doSubmit()" class="btn btn-primary btn-sm mr-2"><i class="fas fa-filter"></i> Filter</button>
+				<a href="#" v-on:click.prevent="fastLoad('{{route('dna.encounters')}}')" class="btn btn-link btn-sm text-danger">Clear Filters</a>
+			</div>
+		</div>
+	</div>
+</form>
+<?php
+$loadedFilters = $filters;
+$allFilterKeys = [
+	'date_category',
+	'date_value_1',
+	'date_value_2',
+	'new_or_fu_or_na'
+];
+for ($i=0; $i < count($allFilterKeys); $i++) {
+	if (!isset($loadedFilters[$allFilterKeys[$i]]) || !$loadedFilters[$allFilterKeys[$i]]) {
+		$loadedFilters[$allFilterKeys[$i]] = '';
+	}
+}
+?>
+
+<script>
+	(function() {
+		function init() {
+			window.apapp = new Vue({
+				el: '#dna-notes-filters',
+				delimiters: ['@{{', '}}'],
+				data: {
+					filters: <?= json_encode($loadedFilters) ?>
+				},
+				methods: {
+					doSubmit: function() {
+						fastLoad('{{ route("dna.encounters") }}?' + $('#dna-notes-filters').serialize());
+						return false;
+					},
+					init: function() {
+
+					}
+				},
+				mounted: function() {
+					this.init();
+				},
+			});
+
+		}
+		addMCInitializer('dna-notes-filters', init, '#dna-notes-filters');
+	})();
+</script>

+ 2 - 0
resources/views/layouts/template.blade.php

@@ -212,6 +212,8 @@
                         @elseif($pro && $pro->isDefaultNA())
 
                             <a class="dropdown-item" href="/practice-management/my-teams">My Teams</a>
+                            <a class="dropdown-item" href="{{ route('dna.encounters') }}">Encounters</a>
+                            <a class="dropdown-item" href="{{ route('dna.appointments') }}">Appointments</a>
 
                         @endif