middleware('auth'); $this->middleware('permission:audit_trail-list', ['only' => ['index', 'search', 'patient_timeline', 'user_timeline']]); } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index(Request $request) { $audits = Audit::with('user') ->where('created_at', '>=', Carbon::now()->subDay()) ->orderBy('created_at', 'desc') ->paginate(100); if ($audits->count() <= 0) { flash("There are no records in the audit trail")->error(); } // users with activity $user_id_array = DB::table('audits') ->groupBy('user_id') ->select('user_id') ->get() ->toArray(); $user_id = array(count($user_id_array)); foreach ($user_id_array as $value) { $user_id[$value->user_id] = get_full_name($value->user_id, 'id', 'first_name', 'last_name', 'users'); } // remove the count from the array unset($user_id[0]); // add --select-- $user_id = ['all' => 'ALL'] + $user_id; // users with activity $action_performed_array = DB::table('audits') ->groupBy('event') ->select('event') ->get() ->toArray(); $action_performed = array(count($action_performed_array)); foreach ($action_performed_array as $value) { $action_performed[$value->event] = ucwords($value->event); } // remove the count from the array unset($action_performed[0]); // add --select-- $action_performed = ['all' => 'ALL'] + $action_performed; // users with activity $records_affected_array = DB::table('audits') ->groupBy('auditable_type') ->select('auditable_type') ->get() ->toArray(); $records_affected = array(count($records_affected_array)); foreach ($records_affected_array as $value) { $record = str_replace('Streamline\\', '', $value->auditable_type); /*================ show better text on forming the drop down ===========*/ $cleaned_model_name = str_replace('Streamline\\', '', $value->auditable_type); $cleaned_model_name = preg_split('/(?=[A-Z])/', $cleaned_model_name); $spaced_model_name = implode(' ', $cleaned_model_name); /*========================================================*/ $records_affected[$record] = $spaced_model_name; } // remove the count from the array unset($records_affected[0]); // add --select-- $records_affected = ['all' => 'ALL'] + $records_affected; // get all first names $first_names = DB::table('users')->pluck('first_name', 'id'); // get all last names $last_names = DB::table('users')->pluck('last_name', 'id'); return view('audit_trail.index', compact([ 'audits', 'first_names', 'last_names', 'user_id', 'action_performed', 'records_affected' ])); } public function audit_trail_print(Request $request) { $audit_trail_values = json_decode($request->data, 1); $hospitalInfo = DB::table('hospital_information')->find(1); $receipt_date = date('Y-m-d h:i:s'); $data = [ 'hospitalInfo' => $hospitalInfo, 'audit_trail' => $request->data, 'receipt_data' => $receipt_date ]; $audit_trail = json_decode($data['audit_trail'])->data; //return view('audit_trail.audit_trail_print', compact('audit_trail')); $pdf = SnappyPDF::loadView('audit_trail.audit_trail_print', compact('audit_trail')) ->setOrientation('portrait') ->setOption('margin-bottom', 7) ->setOption('margin-top', 5) ->setOption('footer-html', 'Stre@mline'); return $pdf->inline('Audit Trail' . date(" d-m-y h:ia") . '.pdf'); } public function failed_login_print(Request $request){ $audit_trail_values = json_decode($request->data, 1); $hospitalInfo = DB::table('hospital_information')->find(1); $receipt_date = date('Y-m-d h:i:s'); $data = [ 'hospitalInfo' => $hospitalInfo, 'failed_login_data' => $request->data, 'receipt_data' => $receipt_date ]; $failed_login_data = json_decode($data['failed_login_data'])->data; //return view('audit_trail.failed_login_print', compact('data', 'failed_login_data')); $pdf = SnappyPDF::loadView('audit_trail.failed_login_print', compact('failed_login_data')) ->setOrientation('portrait') ->setOption('margin-bottom', 7) ->setOption('margin-top', 5) ->setOption('footer-html', 'Stre@mline'); return $pdf->inline('Audit Trail' . date(" d-m-y h:ia") . '.pdf'); } public function online_user_print(Request $request){ $audit_trail_values = json_decode($request->data, 1); $hospitalInfo = DB::table('hospital_information')->find(1); $receipt_date = date('Y-m-d h:i:s'); $data = [ 'hospitalInfo' => $hospitalInfo, 'audit_trail' => $audit_trail_values, 'receipt_data' => $receipt_date ]; $online_users = $audit_trail_values['data']; //return view('audit_trail.online_user_print', compact('online_users')); $pdf = SnappyPDF::loadView('audit_trail.online_user_print', compact('online_users')) ->setOrientation('portrait') ->setOption('margin-bottom', 7) ->setOption('margin-top', 5) ->setOption('footer-html', 'Stre@mline'); return $pdf->inline('Audit Trail' . date(" d-m-y h:ia") . '.pdf'); } /** * Return audit table. * * @return \Illuminate\Http\Response */ public static function return_audit_table() { $audits = Audit::with('user')->orderBy('created_at', 'desc')->paginate(100); echo " Old values @if(array_key_exists('updated_at', $audit->toArray()['old_values'])) @foreach ($audit->toArray()['old_values'] as $key => $value) $patient = Streamline\Models\Patient::where('id', $value)->first(); $user = Streamline\Models\User::where('id', $value)->first(); if($patient->id == $value && $key == 'patient_id') @elseif($key == 'updated_by' || $key == 'created_by' || $key == 'staff_id') @else @endif @endforeach @endif
{{ format_key($key) }}{{ $patient ? $patient->first_name : '' }} {{ $patient ? $patient->last_name : '' }}{{ $user ? $user->first_name : '' }} {{ $user ? $user->last_name : '' }}{{ $value }}
New values "; } /** * Search for audit trail records with given parameters * * @param Request $request * @return \Illuminate\Contracts\View\Factory|\Illuminate\Foundation\Application|\Illuminate\View\View */ public function search(Request $request) { $user_id = $request->user_id; $action_performed = $request->action_performed; $records_affected = $request->records_affected; // Get the selected date criteria $dates = $request->dates; $filters = []; if ($user_id != 'all') : array_push($filters, ['user_id', '=', $user_id]); endif; if ($action_performed != 'all') : array_push($filters, ['event', '=', $action_performed]); endif; if ($records_affected != 'all') : array_push($filters, ['auditable_type', '=', 'Streamline\\' . $records_affected]); endif; // switch the selected date search criteria - today, yesterday, last week, last month etc switch ($dates) { case 'today': $today = Carbon::today()->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', $today)->paginate(100); break; case 'yesterday': $yesterday = Carbon::yesterday()->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', $yesterday)->paginate(100); break; case 'week': $week_ago = Carbon::today()->subDays(7)->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '>=', $week_ago)->paginate(100); break; case 'month': $month_ago = Carbon::today()->subDays(30)->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '>=', $month_ago)->paginate(100); break; case 'custom-date': $start_date = Carbon::parse($request->start_date)->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereDate('created_at', '=', $start_date)->paginate(100); break; case 'custom-range': $start_date = Carbon::parse($request->start_date)->format('Y-m-d'); $end_date = Carbon::parse($request->end_date)->format('Y-m-d'); $audits = Audit::orderBy('created_at', 'desc')->where($filters)->whereBetween('created_at', [$start_date, $end_date])->paginate(100); break; default: $audits = Audit::orderBy('created_at', 'desc')->where($filters)->paginate(150); break; } if ($audits->count() <= 0) { flash("There are no records found in the search")->error(); } // users with activity $user_id_array = DB::table('audits')->groupBy('user_id')->select('user_id')->get()->toArray(); $user_id = array(count($user_id_array)); foreach ($user_id_array as $value) { $user_id[$value->user_id] = get_full_name($value->user_id, 'id', 'first_name', 'last_name', 'users'); } // remove the count from the array unset($user_id[0]); // add --select-- $user_id = ['all' => 'ALL'] + $user_id; // users with activity $action_performed_array = DB::table('audits')->groupBy('event')->select('event')->get()->toArray(); $action_performed = array(count($action_performed_array)); foreach ($action_performed_array as $value) { $action_performed[$value->event] = ucwords($value->event); } // remove the count from the array unset($action_performed[0]); // add --select-- $action_performed = ['all' => 'ALL'] + $action_performed; // users with activity $records_affected_array = DB::table('audits')->groupBy('auditable_type')->select('auditable_type')->get()->toArray(); $records_affected = array(count($records_affected_array)); foreach ($records_affected_array as $value) { $record = str_replace('Streamline\\', '', $value->auditable_type); //$records_affected[$record] = $record; /*================ show better text on forming the drop down ===========*/ $cleaned_model_name = str_replace('Streamline\\', '', $value->auditable_type); $cleaned_model_name = preg_split('/(?=[A-Z])/', $cleaned_model_name); $spaced_model_name = implode(' ', $cleaned_model_name); /*========================================================*/ $records_affected[$record] = $spaced_model_name; } // remove the count from the array unset($records_affected[0]); // add --select-- $records_affected = ['all' => 'ALL'] + $records_affected; // get all first names $first_names = DB::table('users')->pluck('first_name', 'id'); // get all last names $last_names = DB::table('users')->pluck('last_name', 'id'); return view('audit_trail.index', compact('audits', 'first_names', 'last_names', 'user_id', 'action_performed', 'records_affected')); } public function audit_trail_details($id) { //$audits = Audit::where(['id' => $id])->get(); $audit = Audit::where(['id' => $id])->first(); $user = User::where('id', $audit->user_id)->first(); //dd($audit); // get all first names $first_names = DB::table('users')->pluck('first_name', 'id'); // get all last names $last_names = DB::table('users')->pluck('last_name', 'id'); // get full names $full_names = $user->first_name." ".$user->last_name; return view('audit_trail.audit_trail_details', compact('full_names', 'audit', 'last_names', 'first_names')); } public function select_patient_and_episode(Request $request) { $patient = []; $patient_episodes_details = []; if (isset($request->patient_id)) { $patient_searched = true; $patient = Patient::find($request->patient_id); if ($patient) { $patient_episodes = PatientEpisode::where('patient_id', $patient->id)->get(); $counter = 0; foreach ($patient_episodes as $episode) { $patient_episodes_details[$counter]['id'] = $episode->id; $patient_episodes_details[$counter]['created_at'] = streamline_date_time($episode->created_at); $counter++; } } } else { $patient_searched = false; } return view('audit_trail.select_patient_and_episode', compact('patient_searched', 'patient', 'patient_episodes_details')); } public function patient_timeline($patient_id, $episode_id) { $patient = Patient::find($patient_id); $episode = PatientEpisode::find($episode_id); $patient_timeline = []; $index = 0; // add when episode was created $patient_timeline[$index]["date"] = streamline_date_time($episode->created_at); $patient_timeline[$index]["text"] = "Episode was started by " . get_full_name($episode->created_by, 'id', 'first_name', 'last_name', 'users'); $index++; // fetch triage info if (!is_null($episode->triage_id)) { $triage_audits = Audit::where(['auditable_type' => 'Streamline\\Triage', 'auditable_id' => $episode->triage_id]) ->select('old_values', 'new_values', 'event', 'created_at', 'user_id') ->orderBy('created_at', 'desc') ->get() ->toArray(); foreach ($triage_audits as $audit) { if ($audit["event"] == "created") { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $patient_timeline[$index]["text"] = "Patient Triage was carried out by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users') . " with patient being assigned to the " . get_name($audit["new_values"]["clinic_allocation"], 'id', 'name', 'clinics') . " clinic with severe grade of " . severe_grade($audit["new_values"]["severe_grade"]); } else { $text = "Patient Triage was edited by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); if (key_exists("clinic_allocation", $audit["new_values"])) { $text .= "
Clinic allocation changed to " . get_name($audit["new_values"]["clinic_allocation"], 'id', 'name', 'clinics'); } if (key_exists("severe_grade", $audit["new_values"])) { $text .= "
Severe Grade changed to " . severe_grade($audit["new_values"]["severe_grade"]); } $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $patient_timeline[$index]["text"] = $text; } $index++; } } // fetch consultation data if (!is_null($episode->consultation_id)) { $consultation_audits = Audit::where(['auditable_type' => 'Streamline\\Consultation', 'auditable_id' => $episode->consultation_id]) ->select('old_values', 'new_values', 'event', 'created_at', 'user_id') ->orderBy('created_at', 'desc') ->get() ->toArray(); foreach ($consultation_audits as $audit) { if ($audit["event"] == "created") { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $patient_timeline[$index]["text"] = "Patient Consultation was carried out by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users') . " with primary diagnosis set as " . get_name($audit["new_values"]["primary_diagnosis"], 'id', 'name', 'diagnoses') . " and outcome of " . get_name($audit["new_values"]["outcome_id"], 'id', 'name', 'outcomes'); } else { $text = "Patient Consultation was edited by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); if (key_exists("primary_diagnosis", $audit["new_values"])) { $text .= "
Primary Diagnosis changed to " . get_name($audit["new_values"]["primary_diagnosis"], 'id', 'name', 'diagnoses'); } if (key_exists("outcome_id", $audit["new_values"])) { $text .= "
Outcome changed to " . get_name($audit["new_values"]["outcome_id"], 'id', 'name', 'outcomes'); } $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $patient_timeline[$index]["text"] = $text; } $index++; } } // fetch treatment data if (!is_null($episode->treatment_id)) { $treatment_audits = Audit::where(['auditable_type' => 'Streamline\\Treatment', 'auditable_id' => $episode->treatment_id]) ->select('old_values', 'new_values', 'event', 'created_at', 'user_id') ->orderBy('created_at', 'desc') ->get() ->toArray(); foreach ($treatment_audits as $audit) { if ($audit["event"] == "created") { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $text = "Prescriptions were ordered by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); $text .= "
Treatments:"; $drugs = explode(",", $audit["new_values"]["drugs"]); $durations = explode(",", $audit["new_values"]["durations"]); for ($i = 0; $i < count($drugs); $i++) { $text .= "
" . get_name($drugs[$i], 'id', 'name', 'drugs') . " for " . $durations[$i]; } $patient_timeline[$index]["text"] = $text; } else if ($audit["event"] == "updated" && key_exists("drugs", $audit["new_values"]) && key_exists("durations", $audit["new_values"])) { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $text = "Prescriptions were edited by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); $text .= "
Treatments:"; $drugs = explode(",", $audit["new_values"]["drugs"]); $durations = explode(",", $audit["new_values"]["durations"]); for ($i = 0; $i < count($drugs); $i++) { $text .= "
" . get_name($drugs[$i], 'id', 'name', 'drugs') . " for " . $durations[$i]; } $patient_timeline[$index]["text"] = $text; } $index++; } } // check for any ordered investigations $ordered_investigations = DB::table('ordered_investigations') ->where('patient_id', $patient_id) ->where('episode_id', $episode_id) ->get(); foreach ($ordered_investigations as $inv) { $investigation_audits = Audit::where(['auditable_type' => 'Streamline\\OrderedInvestigation', 'auditable_id' => $inv->id]) ->select('old_values', 'new_values', 'event', 'created_at', 'user_id') ->orderBy('created_at', 'desc') ->get() ->toArray(); foreach ($investigation_audits as $audit) { if ($audit["event"] == "created") { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $text = "Investigations were ordered by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); $text .= "
Investigations ( " . $audit["new_values"]["order_type"] . "):"; $invs_id = explode(",", $audit["new_values"]["investigation_id"]); for ($i = 0; $i < count($invs_id); $i++) { $text .= "
" . get_name($invs_id[$i], 'id', 'name', 'investigations'); } $patient_timeline[$index]["text"] = $text; } else if ($audit["event"] == "updated" && key_exists("investigation_id", $audit["new_values"])) { $patient_timeline[$index]["date"] = streamline_date_time($audit["created_at"]); $text = "Investigations were edited by " . get_full_name($audit["user_id"], 'id', 'first_name', 'last_name', 'users'); $text .= "
Investigations ( " . get_name($inv->id, 'id', 'order_type', 'ordered_investigations') . "):"; $invs_id = explode(",", $audit["new_values"]["investigation_id"]); for ($i = 0; $i < count($invs_id); $i++) { $text .= "
" . get_name($invs_id[$i], 'id', 'name', 'investigations'); } $patient_timeline[$index]["text"] = $text; } $index++; } } // check for any ordered procedures $ordered_procedures = DB::table('ordered_procedures') ->where('patient_id', $patient_id) ->where('episode_id', $episode_id) ->get(); // here we shall categorize the procedures. If their created at is within 5 seconds // then they are in the same group of being created $categorized_procedures = []; $counter = 0; $time_last_procedure_was_created = 0; foreach ($ordered_procedures as $procedure) { if ($time_last_procedure_was_created != 0) { $diff_in_time = Carbon::createFromTimeString($procedure->created_at)->diffInSeconds($time_last_procedure_was_created); if ($diff_in_time < 5) { $categorized_procedures[$counter - 1]['ids'][] = $procedure->procedure_id; $categorized_procedures[$counter - 1]['deleted'][] = $procedure->deleted_at; } else { $categorized_procedures[$counter]['ids'] = [$procedure->procedure_id]; $categorized_procedures[$counter]['time'] = $procedure->created_at; $categorized_procedures[$counter]['user_id'] = $procedure->created_by; $categorized_procedures[$counter]['deleted'] = [$procedure->deleted_at]; $time_last_procedure_was_created = $procedure->created_at; $counter++; } } else { $categorized_procedures[$counter]['ids'] = [$procedure->procedure_id]; $categorized_procedures[$counter]['time'] = $procedure->created_at; $categorized_procedures[$counter]['user_id'] = $procedure->created_by; $categorized_procedures[$counter]['deleted'] = [$procedure->deleted_at]; $time_last_procedure_was_created = $procedure->created_at; $counter++; } } foreach ($categorized_procedures as $record) { $patient_timeline[$index]["date"] = streamline_date_time($record['time']); $text = "Procedures were ordered by " . get_full_name($record['user_id'], 'id', 'first_name', 'last_name', 'users'); $text .= "
Procedures:"; for ($i = 0; $i < count($record['ids']); $i++) { $text .= "
" . get_name($record['ids'][$i], 'id', 'name', 'procedures'); if ($record['deleted'][$i]) { $text .= " was later removed at " . streamline_date_time($record['deleted'][$i]) . ""; } } $patient_timeline[$index]["text"] = $text; $index++; } // sort the array in descending order according to the date usort($patient_timeline, array($this, "sort_timeline_by_date")); return view('audit_trail.patient_timeline', compact('patient', 'patient_timeline')); } public function user_timeline(Request $request) { // } function sort_timeline_by_date($a, $b) { return strcmp($a["date"], $b["date"]); } }