* добавлены операции и услуги операций
* добавлена выборка и подсчет по датам для роли зав. * переключатель ролей * выбор отделений для роли зав.
This commit is contained in:
@@ -7,13 +7,16 @@ use App\Http\Resources\Mis\FormattedPatientResource;
|
||||
use App\Models\MetrikaGroup;
|
||||
use App\Models\MetrikaResult;
|
||||
use App\Models\MisMedicalHistory;
|
||||
use App\Models\MisMigrationPatient;
|
||||
use App\Models\MisStationarBranch;
|
||||
use App\Models\ObservationPatient;
|
||||
use App\Models\Report;
|
||||
use App\Models\UnwantedEvent;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
use Inertia\Inertia;
|
||||
|
||||
@@ -21,9 +24,26 @@ class ReportController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$user = Auth::user();
|
||||
$department = $user->department;
|
||||
|
||||
$startDateCarbon = Carbon::now()->firstOfMonth();
|
||||
$startDate = $request->query('startAt', $startDateCarbon->format('Y-m-d'));
|
||||
$endDateCarbon = Carbon::now();
|
||||
$endDate = $request->query('endAt', $endDateCarbon->format('Y-m-d'));
|
||||
|
||||
$doctorStartDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
$doctorEndDate = Carbon::now()->format('Y-m-d');
|
||||
|
||||
if (is_numeric($startDate)) {
|
||||
$startDateCarbon = Carbon::createFromTimestampMs($startDate);
|
||||
$startDate = Carbon::createFromTimestampMs($startDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
if (is_numeric($endDate)) {
|
||||
$endDateCarbon = Carbon::createFromTimestampMs($endDate);
|
||||
$endDate = Carbon::createFromTimestampMs($endDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
|
||||
$beds = (int)$department->metrikaDefault()->where('rf_metrika_item_id', 1)->first()->value;
|
||||
$occupiedBeds = optional(Report::where('rf_department_id', $user->rf_department_id)
|
||||
->join('metrika_results', 'reports.report_id', '=', 'metrika_results.rf_report_id')
|
||||
@@ -35,10 +55,103 @@ class ReportController extends Controller
|
||||
$metrikaGroup = MetrikaGroup::whereMetrikaGroupId(2)->first();
|
||||
$metrikaItems = $metrikaGroup->metrikaItems;
|
||||
|
||||
$misDepartmentId = $request->user()->department->rf_mis_department_id;
|
||||
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
if ($user->isHeadOfDepartment())
|
||||
{
|
||||
$medicalHistoryIds = MisMigrationPatient::whereInDepartment($branchId)
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
$extractedMedicalHistoryIds = MisMigrationPatient::extractedToday($branchId, $startDate, $endDate)
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
$recipientCount = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->when($user->isHeadOfDepartment(), function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateRecipient', [$startDate, $endDate]);
|
||||
})
|
||||
->when(!$user->isHeadOfDepartment(), function($query) use ($doctorStartDate, $doctorEndDate) {
|
||||
return $query->whereBetween('DateRecipient', [$doctorStartDate, $doctorEndDate]);
|
||||
})
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
|
||||
$extractedCount = MisMedicalHistory::whereIn('MedicalHistoryID', $extractedMedicalHistoryIds)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
|
||||
$recipientIds = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->when($doctorStartDate, function($query) use ($doctorStartDate, $doctorEndDate) {
|
||||
return $query->whereBetween('DateRecipient', [$doctorStartDate, $doctorEndDate]);
|
||||
})
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->pluck('MedicalHistoryID')
|
||||
->values();
|
||||
|
||||
$currentCount = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else {
|
||||
$medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId)
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
$extractedMedicalHistoryIds = MisMigrationPatient::extractedToday($branchId)
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
$recipientCount = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->when($user->isHeadOfDepartment(), function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateRecipient', [$startDate, $endDate]);
|
||||
})
|
||||
->when(!$user->isHeadOfDepartment(), function($query) use ($doctorStartDate, $doctorEndDate) {
|
||||
return $query->whereBetween('DateRecipient', [$doctorStartDate, $doctorEndDate]);
|
||||
})
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
|
||||
$extractedCount = MisMedicalHistory::whereIn('MedicalHistoryID', $extractedMedicalHistoryIds)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
|
||||
$recipientIds = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->when($user->isHeadOfDepartment(), function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateRecipient', [$startDate, $endDate]);
|
||||
})
|
||||
->when(!$user->isHeadOfDepartment(), function($query) use ($doctorStartDate, $doctorEndDate) {
|
||||
return $query->whereBetween('DateRecipient', [$doctorStartDate, $doctorEndDate]);
|
||||
})
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->pluck('MedicalHistoryID')
|
||||
->values();
|
||||
|
||||
$currentCount = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
}
|
||||
|
||||
|
||||
return response()->json([
|
||||
'department' => [
|
||||
'beds' => $beds,
|
||||
'percentLoadedBeds' => $percentLoadedBeds,
|
||||
'recipientCount' => $recipientCount,
|
||||
'extractCount' => $extractedCount,
|
||||
'currentCount' => $currentCount,
|
||||
'recipientIds' => $recipientIds
|
||||
],
|
||||
'dates' => [
|
||||
'startAt' => $startDateCarbon->getTimestampMs(),
|
||||
'endAt' => $endDateCarbon->getTimestampMs()
|
||||
],
|
||||
'metrikaItems' => $metrikaItems
|
||||
]);
|
||||
@@ -50,6 +163,7 @@ class ReportController extends Controller
|
||||
'metrics' => 'required',
|
||||
'observationPatients' => 'nullable',
|
||||
'departmentId' => 'required|integer',
|
||||
'unwantedEvent' => 'nullable'
|
||||
]);
|
||||
|
||||
$metrics = $data['metrics'];
|
||||
@@ -74,6 +188,13 @@ class ReportController extends Controller
|
||||
'sent_at' => now()
|
||||
]);
|
||||
|
||||
if (in_array('unwantedEvent', $data)) {
|
||||
$unwantedEvent = UnwantedEvent::create([
|
||||
'rf_report_id' => $report->id,
|
||||
'comment' => $data['unwantedEvent']['comment'] ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($metriks as $metrika) {
|
||||
$metrika->rf_report_id = $report->report_id;
|
||||
$metrika->save();
|
||||
@@ -97,59 +218,215 @@ class ReportController extends Controller
|
||||
|
||||
public function getPatients(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$data = $request->validate([
|
||||
'status' => 'required|string', // plan emergency
|
||||
'startAt' => 'nullable',
|
||||
'endAt' => 'nullable',
|
||||
]);
|
||||
|
||||
$status = $data['status'];
|
||||
|
||||
$startDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
$endDate = Carbon::now()->format('Y-m-d');
|
||||
$startDateCarbon = Carbon::now()->firstOfMonth();
|
||||
$startDate = $data['startAt'] ?? $startDateCarbon->format('Y-m-d');
|
||||
$endDateCarbon = Carbon::now();
|
||||
$endDate = $data['endAt'] ?? $startDateCarbon->format('Y-m-d');
|
||||
|
||||
$doctorStartDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
$doctorEndDate = Carbon::now()->format('Y-m-d');
|
||||
|
||||
if (is_numeric($startDate)) {
|
||||
$startDateCarbon = Carbon::createFromTimestampMs($startDate);
|
||||
$startDate = Carbon::createFromTimestampMs($startDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
if (is_numeric($endDate)) {
|
||||
$endDateCarbon = Carbon::createFromTimestampMs($endDate);
|
||||
$endDate = Carbon::createFromTimestampMs($endDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
|
||||
$model = new MisMedicalHistory();
|
||||
$misDepartmentId = $request->user()->department->rf_mis_department_id;
|
||||
$userDepartmentId = $request->user()->department->department_id;
|
||||
$misStationarBranchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)->first()->StationarBranchID;
|
||||
if ($status === 'plan') {
|
||||
$patients = MisMedicalHistory::select(
|
||||
[
|
||||
...$model->getFillable(),
|
||||
DB::raw('ROW_NUMBER() OVER (ORDER BY "DateRecipient" DESC) as num')
|
||||
])
|
||||
->plan()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) {
|
||||
$item->num = $index + 1;
|
||||
return $item;
|
||||
});;
|
||||
} else if ($status === 'emergency') {
|
||||
$patients = MisMedicalHistory::select(
|
||||
[
|
||||
...$model->getFillable(),
|
||||
DB::raw('ROW_NUMBER() OVER (ORDER BY "DateRecipient" DESC) as num')
|
||||
])
|
||||
->emergency()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) {
|
||||
$item->num = $index + 1;
|
||||
return $item;
|
||||
});
|
||||
} else if ($status === 'observation') {
|
||||
$patients = ObservationPatient::with(['history'])
|
||||
->where('rf_department_id', $misDepartmentId)
|
||||
->history;
|
||||
} else if ($status === 'deceased') {
|
||||
$patients = MisMedicalHistory::select(...$model->getFillable())
|
||||
->deceased()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->get()
|
||||
->map(function ($item, $index) {
|
||||
$item->num = $index + 1;
|
||||
return $item;
|
||||
});
|
||||
|
||||
if ($user->isHeadOfDepartment()) {
|
||||
if ($status === 'plan') {
|
||||
// Сначала получаем ID локально
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
|
||||
if (!$branchId) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$medicalHistoryIds = MisMigrationPatient::whereInDepartment($branchId)
|
||||
->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||||
})
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
// Получаем истории
|
||||
$patients = MisMedicalHistory::select($model->getFillable())
|
||||
->plan()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
} else if ($status === 'emergency') {
|
||||
// Сначала получаем ID локально
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
|
||||
if (!$branchId) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$medicalHistoryIds = MisMigrationPatient::whereInDepartment($branchId)
|
||||
->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||||
})
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
// Получаем истории
|
||||
$patients = MisMedicalHistory::select($model->getFillable())
|
||||
->emergency()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->with(['surgicalOperations'])
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
} else if ($status === 'observation') {
|
||||
$medicalHistoryIds = ObservationPatient::where('rf_department_id', $userDepartmentId)
|
||||
->pluck('rf_medicalhistory_id')
|
||||
->toArray();
|
||||
|
||||
$patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->get()->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
|
||||
} else if ($status === 'deceased') {
|
||||
$patients = MisMedicalHistory::select(...$model->getFillable())
|
||||
->deceased()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->get()
|
||||
->map(function ($item, $index) {
|
||||
$item->num = $index + 1;
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if ($status === 'plan') {
|
||||
// Сначала получаем ID локально
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
|
||||
if (!$branchId) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId)
|
||||
// ->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
// return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||||
// })
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
// Получаем истории
|
||||
$patients = MisMedicalHistory::select($model->getFillable())
|
||||
->plan()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
} else if ($status === 'emergency') {
|
||||
// Сначала получаем ID локально
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
|
||||
if (!$branchId) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId)
|
||||
// ->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
// return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||||
// })
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
// Получаем истории
|
||||
$patients = MisMedicalHistory::select($model->getFillable())
|
||||
->emergency()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->with(['surgicalOperations'])
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
} else if ($status === 'observation') {
|
||||
$medicalHistoryIds = ObservationPatient::where('rf_department_id', $userDepartmentId)
|
||||
->pluck('rf_medicalhistory_id')
|
||||
->toArray();
|
||||
|
||||
$patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->get()->map(function ($item, $index) use ($misStationarBranchId) {
|
||||
$item->num = $index + 1;
|
||||
$item->misStationarBranchId = $misStationarBranchId;
|
||||
return $item;
|
||||
});
|
||||
|
||||
} else if ($status === 'deceased') {
|
||||
$patients = MisMedicalHistory::select(...$model->getFillable())
|
||||
->deceased()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->get()
|
||||
->map(function ($item, $index) {
|
||||
$item->num = $index + 1;
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$patients->load(['migrations' => function ($query) use ($startDate, $endDate, $misStationarBranchId) {
|
||||
@@ -164,29 +441,97 @@ class ReportController extends Controller
|
||||
|
||||
public function getPatientsCount(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$data = $request->validate([
|
||||
'status' => 'required|string', // plan emergency
|
||||
'startAt' => 'nullable',
|
||||
'endAt' => 'nullable',
|
||||
]);
|
||||
|
||||
$status = $data['status'];
|
||||
|
||||
$startDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
$endDate = Carbon::now()->format('Y-m-d');
|
||||
$startDateCarbon = Carbon::now()->firstOfMonth();
|
||||
$startDate = $data['startAt'] ?? $startDateCarbon->format('Y-m-d');
|
||||
$endDateCarbon = Carbon::now();
|
||||
$endDate = $data['endAt'] ?? $endDateCarbon->format('Y-m-d');
|
||||
|
||||
$doctorStartDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
$doctorEndDate = Carbon::now()->format('Y-m-d');
|
||||
|
||||
if (is_numeric($startDate)) {
|
||||
$startDateCarbon = Carbon::createFromTimestampMs($startDate);
|
||||
$startDate = Carbon::createFromTimestampMs($startDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
if (is_numeric($endDate)) {
|
||||
$endDateCarbon = Carbon::createFromTimestampMs($endDate);
|
||||
$endDate = Carbon::createFromTimestampMs($endDate)->setTimezone('Asia/Yakutsk')->format('Y-m-d');
|
||||
}
|
||||
|
||||
$model = new MisMedicalHistory();
|
||||
$misDepartmentId = $request->user()->department->rf_mis_department_id;
|
||||
if ($status === 'plan') {
|
||||
$count = MisMedicalHistory::select($model->getFillable())
|
||||
->plan()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else if ($status === 'emergency') {
|
||||
$count = MisMedicalHistory::select($model->getFillable())
|
||||
->emergency()
|
||||
->inDepartment($misDepartmentId, $startDate, $endDate)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
|
||||
// Получаем ID отделения
|
||||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
|
||||
if (!$branchId) {
|
||||
return response()->json(0);
|
||||
}
|
||||
|
||||
if ($user->isHeadOfDepartment()) {
|
||||
// Получаем ID медицинских историй по миграциям
|
||||
$medicalHistoryIds = MisMigrationPatient::whereInDepartment($branchId)
|
||||
->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||||
})
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return response()->json(0);
|
||||
}
|
||||
|
||||
// Подсчет в зависимости от статуса
|
||||
if ($status === 'plan') {
|
||||
$count = MisMedicalHistory::plan()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else if ($status === 'emergency') {
|
||||
$count = MisMedicalHistory::emergency()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
} else {
|
||||
// Получаем ID медицинских историй по миграциям
|
||||
$medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId)
|
||||
->pluck('rf_MedicalHistoryID')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return response()->json(0);
|
||||
}
|
||||
|
||||
// Подсчет в зависимости от статуса
|
||||
if ($status === 'plan') {
|
||||
$count = MisMedicalHistory::plan()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else if ($status === 'emergency') {
|
||||
$count = MisMedicalHistory::emergency()
|
||||
->whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->currentlyHospitalized()
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->count();
|
||||
} else {
|
||||
$count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json($count);
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Inertia\Inertia;
|
||||
|
||||
@@ -53,4 +54,22 @@ class AuthController extends Controller
|
||||
|
||||
return Inertia::location(route('start'));
|
||||
}
|
||||
|
||||
public function changeRole(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (!$user) return null;
|
||||
|
||||
$data = $request->validate([
|
||||
'role_id' => 'required|integer|exists:roles,role_id'
|
||||
]);
|
||||
|
||||
$sessionKey = 'user_' . $user->id . '_current_role';
|
||||
|
||||
$user->current_role_id = $data['role_id'];
|
||||
$user->save();
|
||||
|
||||
return redirect()->route('start')->setStatusCode(302);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class HandleInertiaRequests extends Middleware
|
||||
'token' => Session::get('token'),
|
||||
'permissions' => $user->permissions(),
|
||||
'role' => $user->currentRole(),
|
||||
'available_roles' => $user->roles,
|
||||
'available_departments' => $user->availableDepartments(),
|
||||
'current_department' => $user->department
|
||||
] : null,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Resources\Mis;
|
||||
|
||||
use App\Models\MisSurgicalOperation;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Illuminate\Support\Carbon;
|
||||
@@ -25,6 +26,15 @@ class FormattedPatientResource extends JsonResource
|
||||
'name' => $this->migrations()->first()->diagnosis()->first()?->mkb()->first()->NAME ?? null,
|
||||
];
|
||||
}),
|
||||
'operations' => $this->whenLoaded('surgicalOperations', function () {
|
||||
return $this->surgicalOperations()->where('rf_StationarBranchID', $this->misStationarBranchId)
|
||||
->get()
|
||||
->map(function (MisSurgicalOperation $operation) {
|
||||
return [
|
||||
'code' => $operation->serviceMedical->ServiceMedicalCode ?? null,
|
||||
];
|
||||
});
|
||||
}),
|
||||
'fullname' => Str::ucwords(Str::lower("$this->FAMILY $this->Name $this->OT")),
|
||||
'age' => Carbon::parse($this->BD)->diff(Carbon::now())->format('%y'),
|
||||
'birth_date' => Carbon::parse($this->BD)->format('d.m.Y'),
|
||||
|
||||
@@ -24,6 +24,22 @@ class MisMedicalHistory extends Model
|
||||
'DateRecipient' => 'datetime'
|
||||
];
|
||||
|
||||
public function observationPatient()
|
||||
{
|
||||
return $this->belongsTo(ObservationPatient::class, 'MedicalHistoryID', 'rf_medicalhistory_id');
|
||||
}
|
||||
|
||||
public function surgicalOperations()
|
||||
{
|
||||
return $this->hasMany(MisSurgicalOperation::class, 'rf_MedicalHistoryID', 'MedicalHistoryID');
|
||||
}
|
||||
|
||||
public function scopeCurrentlyHospitalized($query)
|
||||
{
|
||||
return $query->whereDate('DateExtract', '1900-01-01')
|
||||
->where('MedicalHistoryID', '<>', 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Истории со срочностью - Плановая
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class MisMigrationPatient extends Model
|
||||
{
|
||||
@@ -23,4 +24,45 @@ class MisMigrationPatient extends Model
|
||||
{
|
||||
return $this->hasOne(MisMKB::class, 'MKBID', 'rf_MKBID');
|
||||
}
|
||||
|
||||
public function scopeCurrentlyInTreatment($query, $branchId = null)
|
||||
{
|
||||
$query->where('rf_kl_VisitResultID', 0)
|
||||
->where('rf_MedicalHistoryID', '<>', 0);
|
||||
|
||||
if ($branchId) {
|
||||
$query->where('rf_StationarBranchID', $branchId);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function scopeWhereInDepartment($query, $branchId = null)
|
||||
{
|
||||
$query->where('rf_MedicalHistoryID', '<>', 0);
|
||||
|
||||
if ($branchId) {
|
||||
$query->where('rf_StationarBranchID', $branchId);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function scopeExtractedToday($query, $branchId = null, $startDate = null, $endDate = null)
|
||||
{
|
||||
if (is_null($startDate)) $startDate = Carbon::now()->addDays(-1)->format('Y-m-d');
|
||||
if (is_null($endDate)) $endDate = Carbon::now()->format('Y-m-d');
|
||||
|
||||
$query->where('rf_kl_VisitResultID', '<>', 0)
|
||||
->where('rf_MedicalHistoryID', '<>', 0)
|
||||
->when($startDate && $endDate, function($query) use ($startDate, $endDate) {
|
||||
return $query->whereBetween('DateOut', [$startDate, $endDate]);
|
||||
});
|
||||
|
||||
if ($branchId) {
|
||||
$query->where('rf_StationarBranchID', $branchId);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
||||
16
app/Models/MisServiceMedical.php
Normal file
16
app/Models/MisServiceMedical.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MisServiceMedical extends Model
|
||||
{
|
||||
protected $table = 'oms_servicemedical';
|
||||
protected $primaryKey = 'ServiceMedicalID';
|
||||
|
||||
public function surgicalOperations()
|
||||
{
|
||||
return $this->hsaMany(MisServiceMedical::class, 'ServiceMedicalID', 'rf_ServiceMedicalID');
|
||||
}
|
||||
}
|
||||
16
app/Models/MisSurgicalOperation.php
Normal file
16
app/Models/MisSurgicalOperation.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MisSurgicalOperation extends Model
|
||||
{
|
||||
protected $table = 'stt_surgicaloperation';
|
||||
protected $primaryKey = 'SurgicalOperationID';
|
||||
|
||||
public function serviceMedical()
|
||||
{
|
||||
return $this->belongsTo(MisServiceMedical::class, 'rf_kl_ServiceMedicalID', 'ServiceMedicalID');
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ class ObservationPatient extends Model
|
||||
'rf_mkab_id',
|
||||
'rf_department_id',
|
||||
'rf_report_id',
|
||||
'comment'
|
||||
];
|
||||
|
||||
public function history()
|
||||
|
||||
15
app/Models/UnwantedEvent.php
Normal file
15
app/Models/UnwantedEvent.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UnwantedEvent extends Model
|
||||
{
|
||||
protected $primaryKey = 'unwanted_event_id';
|
||||
|
||||
protected $fillable = [
|
||||
'rf_report_id',
|
||||
'comment'
|
||||
];
|
||||
}
|
||||
@@ -28,6 +28,7 @@ class User extends Authenticatable
|
||||
'password',
|
||||
'rf_lpudoctor_id',
|
||||
'rf_department_id',
|
||||
'current_role_id'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -78,7 +79,8 @@ class User extends Authenticatable
|
||||
public function currentRole()
|
||||
{
|
||||
$defaultRoleId = $this->roles()->where('is_default', true)->first()->role_id;
|
||||
$roleId = session('currentRoleId', $defaultRoleId);
|
||||
$sessionKey = 'user_' . $this->id . '_current_role';
|
||||
$roleId = $this->current_role_id ?? $defaultRoleId;
|
||||
|
||||
$role = Role::where('role_id', $roleId)->first();
|
||||
|
||||
@@ -101,11 +103,6 @@ class User extends Authenticatable
|
||||
return $this->currentRole()->slug === 'head_of_department';
|
||||
}
|
||||
|
||||
public function isStatistician()
|
||||
{
|
||||
return $this->currentRole()->slug === 'statistician';
|
||||
}
|
||||
|
||||
// Получение доступных отделений
|
||||
public function availableDepartments()
|
||||
{
|
||||
@@ -134,11 +131,6 @@ class User extends Authenticatable
|
||||
$permissions['manage_users'] = $this->isAdmin();
|
||||
}
|
||||
|
||||
if ($this->isStatistician()) {
|
||||
$permissions['view_statistics'] = true;
|
||||
$permissions['export_data'] = true;
|
||||
}
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('observation_patients', function (Blueprint $table) {
|
||||
$table->text('comment')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('observation_patients', function (Blueprint $table) {
|
||||
$table->dropColumn('comment');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('current_role_id')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('current_role_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('unwanted_events', function (Blueprint $table) {
|
||||
$table->id('unwanted_event_id');
|
||||
$table->foreignIdFor(\App\Models\Report::class, 'rf_report_id');
|
||||
$table->text('comment');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('unwanted_events');
|
||||
}
|
||||
};
|
||||
22
resources/js/Components/DepartmentSelect.vue
Normal file
22
resources/js/Components/DepartmentSelect.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup>
|
||||
import {useAuthStore} from "../Stores/auth.js";
|
||||
import {NSelect} from "naive-ui";
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const value = ref(authStore.userDepartment.department_id)
|
||||
|
||||
const departments = computed(() => authStore.availableDepartments.map(item => ({
|
||||
label: item.name_full,
|
||||
value: item.department_id
|
||||
})))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSelect v-model:value="value" :options="departments" class="max-w-[280px]" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -23,10 +23,10 @@ const { timestampCurrentRange } = storeToRefs(reportStore)
|
||||
|
||||
<template>
|
||||
<NDatePicker :theme-overrides="themeOverride"
|
||||
v-model:value="timestampCurrentRange"
|
||||
v-model:value="reportStore.timestampCurrentRange"
|
||||
format="dd.MM.YYYY"
|
||||
type="daterange"
|
||||
@update-value="reportStore.getDataOnReportDate"
|
||||
@update-value="value => reportStore.getDataOnReportDate(value)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -7,18 +7,13 @@ import AppHeaderRole from "./AppHeaderRole.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NFlex justify="space-between" align="center" class="px-4 w-full h-full">
|
||||
<NFlex align="center">
|
||||
<NButton :tag="Link" text href="/">
|
||||
Метрика
|
||||
</NButton>
|
||||
<!-- <NDivider vertical />-->
|
||||
<!-- <ReportSelectDate />-->
|
||||
</NFlex>
|
||||
<NFlex align="center">
|
||||
<AppUserButton />
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
<div class="grid grid-cols-[auto_1fr_auto] px-4 w-full h-full">
|
||||
<NButton :tag="Link" text href="/">
|
||||
Метрика
|
||||
</NButton>
|
||||
<div></div>
|
||||
<AppUserButton />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,14 +1,35 @@
|
||||
<script setup>
|
||||
import {useAuthStore} from "../../Stores/auth.js";
|
||||
import {NDropdown, NButton, NText} from 'naive-ui'
|
||||
import {NSelect, NFlex, NText} from 'naive-ui'
|
||||
import {computed} from "vue";
|
||||
import {router, useForm} from "@inertiajs/vue3";
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const userOptions = [
|
||||
{
|
||||
label: 'Выход',
|
||||
key: 'exit',
|
||||
},
|
||||
]
|
||||
const userOptions = computed(() => {
|
||||
return authStore.availableRoles.map(itm => {
|
||||
return {
|
||||
label: itm.name,
|
||||
value: itm.role_id
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const formRole = useForm({
|
||||
role_id: authStore.user.role.role_id
|
||||
})
|
||||
const onChangeRole = (roleId) => {
|
||||
console.log(roleId)
|
||||
formRole.post('/user/role/change', {
|
||||
onSuccess: () => {
|
||||
router.visit(window.location.pathname, {
|
||||
preserveScroll: true,
|
||||
preserveState: false, // Это важно - сбрасывает состояние
|
||||
only: ['user', 'auth'], // Указываем какие данные обновить
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const themeOverride = {
|
||||
border: null,
|
||||
borderHover: null,
|
||||
@@ -20,9 +41,17 @@ const themeOverride = {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NText>
|
||||
{{ authStore.user?.name }}
|
||||
</NText>
|
||||
<NFlex align="center" :wrap="false">
|
||||
<div class="min-w-[220px]">
|
||||
<NSelect :options="userOptions"
|
||||
v-model:value="formRole.role_id"
|
||||
@update:value="value => onChangeRole(value)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{{ authStore.user?.name }}
|
||||
</div>
|
||||
</NFlex>
|
||||
<!-- <NDropdown :options="userOptions" placement="bottom-end">-->
|
||||
<!-- <NButton :theme-overrides="themeOverride">-->
|
||||
<!-- {{ authStore.user?.name }}-->
|
||||
|
||||
@@ -27,7 +27,7 @@ const onSubmit = () => {
|
||||
<NFlex vertical class="max-w-6xl mx-auto mt-6 mb-4 w-full">
|
||||
<ReportHeader :mode="mode" />
|
||||
|
||||
<ReportFormInput />
|
||||
<ReportFormInput v-if="mode === 'fillable'" />
|
||||
|
||||
<ReportSection label="Планово" />
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ import {useAuthStore} from "../../../Stores/auth.js";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {RiAddCircleLine} from 'vue-icons-plus/ri'
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import ReportSelectDate from "../../../Components/ReportSelectDate.vue";
|
||||
import DepartmentSelect from "../../../Components/DepartmentSelect.vue";
|
||||
import UnwantedEventModal from "./UnwantedEventModal.vue";
|
||||
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
@@ -34,6 +37,8 @@ const {reportInfo} = storeToRefs(reportStore)
|
||||
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
|
||||
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
|
||||
const openUnwantedEventModal = ref(false)
|
||||
|
||||
const selectDepartment = ref(0)
|
||||
|
||||
const currentDate = computed(() => {
|
||||
@@ -48,17 +53,17 @@ const currentDate = computed(() => {
|
||||
<template>
|
||||
<NCard>
|
||||
<NFlex vertical>
|
||||
<NFlex align="center" justify="space-between">
|
||||
<NH2 v-if="isFillableMode" class="mb-0!">
|
||||
{{ currentDate }}
|
||||
</NH2>
|
||||
<NDatePicker v-if="isReadonlyMode" />
|
||||
<NFlex align="center" justify="space-between" :wrap="false">
|
||||
<NTag v-if="isFillableMode" type="info" :bordered="false">
|
||||
{{ authStore.userDepartment.name_full }}
|
||||
</NTag>
|
||||
<DepartmentSelect v-if="isReadonlyMode" />
|
||||
|
||||
<NFlex align="center" :wrap="false">
|
||||
<NTag v-if="isFillableMode" type="info" :bordered="false">
|
||||
{{ authStore.userDepartment.name_full }}
|
||||
</NTag>
|
||||
<NSelect v-if="isReadonlyMode" v-model:value="selectDepartment" :options="departments" />
|
||||
<NH2 v-if="isFillableMode" class="mb-0!">
|
||||
{{ currentDate }}
|
||||
</NH2>
|
||||
<ReportSelectDate v-if="isReadonlyMode" />
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
|
||||
@@ -80,9 +85,33 @@ const currentDate = computed(() => {
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
<NCol :span="5">
|
||||
<NStatistic label="Поступило">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.recipientCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
<NCol :span="5">
|
||||
<NStatistic label="Выбыло">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.extractCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
<NCol :span="5">
|
||||
<NStatistic label="Состоит">
|
||||
<template #default>
|
||||
<NSkeleton v-if="reportStore.isLoadReportInfo" round class="w-[70px]! mt-2 h-[29px]!" />
|
||||
<span v-else>{{ reportStore.reportInfo?.department.currentCount }}</span>
|
||||
</template>
|
||||
</NStatistic>
|
||||
</NCol>
|
||||
</NRow>
|
||||
|
||||
<NButton type="primary" secondary>
|
||||
<NButton type="error" secondary @click="openUnwantedEventModal = true">
|
||||
<template #icon>
|
||||
<RiAddCircleLine />
|
||||
</template>
|
||||
@@ -91,6 +120,8 @@ const currentDate = computed(() => {
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
</NCard>
|
||||
|
||||
<UnwantedEventModal v-model:open="openUnwantedEventModal" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -17,7 +17,7 @@ const reportStore = useReportStore()
|
||||
const {patientsData} = storeToRefs(reportStore)
|
||||
|
||||
const handleItemDragged = (event) => {
|
||||
console.log('Начато перетаскивание:', event)
|
||||
// console.log('Начато перетаскивание:', event)
|
||||
}
|
||||
|
||||
// Обработка события drop
|
||||
@@ -47,6 +47,8 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
<ReportSectionHeader title="Планово" status="plan" />
|
||||
</template>
|
||||
<ReportSectionItem status="plan"
|
||||
:accent-ids="reportStore.reportInfo?.department.recipientIds"
|
||||
is-draggable
|
||||
@item-dragged="handleItemDragged"
|
||||
/>
|
||||
</NCollapseItem>
|
||||
@@ -55,17 +57,20 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
<ReportSectionHeader title="Экстренно" status="emergency" />
|
||||
</template>
|
||||
<ReportSectionItem status="emergency"
|
||||
:accent-ids="reportStore.reportInfo?.department.recipientIds"
|
||||
is-draggable
|
||||
@item-dragged="handleItemDragged"
|
||||
/>
|
||||
</NCollapseItem>
|
||||
<NCollapseItem name="3">
|
||||
<template #header>
|
||||
<ReportSectionHeader title="Наблюдение" status="observation" />
|
||||
<ReportSectionHeader title="Находятся на контроле" status="observation" />
|
||||
</template>
|
||||
<NFlex :size="12">
|
||||
<ReportSectionItem status="observation"
|
||||
@item-dragged="handleItemDragged"
|
||||
@item-dropped="handleItemDropped"
|
||||
is-removable
|
||||
/>
|
||||
<NAlert v-if="isFillableMode" type="info" class="w-full">
|
||||
Перетаскивайте строки из верхних таблиц, что бы добавить в наблюдение
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {NSkeleton, NText} from 'naive-ui'
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
@@ -13,14 +14,19 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const reportStore = useReportStore()
|
||||
|
||||
const isLoading = ref(true)
|
||||
const countPatient = ref(null)
|
||||
const fetchPatientCount = async () => {
|
||||
if (props.status === 'plan' || props.status === 'emergency') {
|
||||
isLoading.value = true
|
||||
await axios.post('/api/mis/patients/count', {
|
||||
status: props.status
|
||||
}).then((res) => {
|
||||
const data = {
|
||||
status: props.status,
|
||||
startAt: reportStore.timestampCurrentRange[0],
|
||||
endAt: reportStore.timestampCurrentRange[1]
|
||||
}
|
||||
await axios.post('/api/mis/patients/count', data).then((res) => {
|
||||
countPatient.value = res.data
|
||||
}).finally(() => {
|
||||
isLoading.value = false
|
||||
@@ -41,6 +47,10 @@ const computedHeader = computed(() => {
|
||||
onMounted(async () => {
|
||||
await fetchPatientCount()
|
||||
})
|
||||
|
||||
watch(() => reportStore.timestampCurrentRange, (newRange) => {
|
||||
if (newRange) fetchPatientCount()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import {NIcon, NDataTable} from "naive-ui";
|
||||
import {NIcon, NText, NDataTable, NButton} from "naive-ui";
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import {computed, h, onMounted, ref, watch} from "vue";
|
||||
import { VueDraggableNext } from 'vue-draggable-next'
|
||||
@@ -18,12 +18,26 @@ const props = defineProps({
|
||||
status: {
|
||||
type: String,
|
||||
default: null // 'plan'
|
||||
},
|
||||
isRemovable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isDraggable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
accentIds: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
})
|
||||
|
||||
const isFillableMode = computed(() => props.mode.toLowerCase() === 'fillable')
|
||||
const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
|
||||
|
||||
const tableRef = ref()
|
||||
|
||||
const emit = defineEmits(['item-dragged', 'item-dropped'])
|
||||
|
||||
const reportStore = useReportStore()
|
||||
@@ -37,6 +51,8 @@ const isLoading = ref(true)
|
||||
const columns = computed(() => {
|
||||
if (!isFillableMode.value) return baseColumns
|
||||
|
||||
const newColumns = []
|
||||
|
||||
const dragColumn = {
|
||||
title: '',
|
||||
key: 'drag',
|
||||
@@ -59,7 +75,46 @@ const columns = computed(() => {
|
||||
)
|
||||
}
|
||||
|
||||
return [dragColumn, ...baseColumns]
|
||||
const removeColumn = {
|
||||
title: '',
|
||||
key: 'remove',
|
||||
render: (row) => h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
onClick: () => {
|
||||
alert('message')
|
||||
}
|
||||
},
|
||||
[
|
||||
'Снять с наблюдения'
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
if (props.isDraggable) newColumns.push(dragColumn)
|
||||
newColumns.push(...baseColumns)
|
||||
if (props.isRemovable) newColumns.push(removeColumn)
|
||||
|
||||
if (props.status === 'emergency') {
|
||||
const operationColumn = {
|
||||
title: 'Операции',
|
||||
key: 'operations',
|
||||
render: (row) => row.operations.length ?
|
||||
h(
|
||||
NText,
|
||||
{},
|
||||
[
|
||||
row.operations.map(itm => {
|
||||
return `${itm.code}; `
|
||||
})
|
||||
]
|
||||
) : h('div', {}, '-')
|
||||
}
|
||||
newColumns.push(operationColumn)
|
||||
}
|
||||
|
||||
return newColumns
|
||||
})
|
||||
|
||||
const handleDragStart = (e, row) => {
|
||||
@@ -108,9 +163,12 @@ const handleDrop = (e) => {
|
||||
|
||||
const fetchPatients = async () => {
|
||||
isLoading.value = true
|
||||
await axios.post('/api/mis/patients', {
|
||||
status: props.status
|
||||
}).then((res) => {
|
||||
const data = {
|
||||
status: props.status,
|
||||
startAt: reportStore.timestampCurrentRange[0],
|
||||
endAt: reportStore.timestampCurrentRange[1],
|
||||
}
|
||||
await axios.post('/api/mis/patients', data).then((res) => {
|
||||
patientsData.value[props.status] = res.data
|
||||
}).finally(() => {
|
||||
isLoading.value = false
|
||||
@@ -118,19 +176,35 @@ const fetchPatients = async () => {
|
||||
}
|
||||
|
||||
function rowProps(row) {
|
||||
const style = []
|
||||
const classes = []
|
||||
|
||||
style.push(props.isDraggable ? 'cursor: grab;' : 'cursor: arrow;')
|
||||
|
||||
if (props.accentIds.length) {
|
||||
console.log(props.accentIds.includes(row.id))
|
||||
if (props.accentIds.includes(row.id)) {
|
||||
style.push('--n-merged-td-color: #047857')
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
draggable: true,
|
||||
style: 'cursor: grab;',
|
||||
draggable: props.isDraggable,
|
||||
style: style,
|
||||
onDragstart: (e) => {
|
||||
if (!props.isDraggable) return
|
||||
handleDragStart(e, row)
|
||||
},
|
||||
onDragend: (e) => {
|
||||
if (!props.isDraggable) return
|
||||
handleDragEnd(e)
|
||||
},
|
||||
onDragover: (e) => {
|
||||
if (!props.isDraggable) return
|
||||
handleDragOver(e)
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (!props.isDraggable) return
|
||||
handleDrop(e)
|
||||
}
|
||||
}
|
||||
@@ -143,6 +217,7 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<NDataTable :columns="columns"
|
||||
ref="tableRef"
|
||||
:data="patientsData[status]"
|
||||
size="small"
|
||||
@drop="handleDrop"
|
||||
|
||||
50
resources/js/Pages/Report/Components/UnwantedEventModal.vue
Normal file
50
resources/js/Pages/Report/Components/UnwantedEventModal.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<script setup>
|
||||
import {NModal, NForm, NFormItem, NInput, NFlex, NButton} from 'naive-ui'
|
||||
import {useForm} from "@inertiajs/vue3";
|
||||
import {useReportStore} from "../../../Stores/report.js";
|
||||
import {ref} from "vue";
|
||||
const open = defineModel('open')
|
||||
|
||||
const reportStore = useReportStore()
|
||||
const formRef = ref()
|
||||
const rules = {
|
||||
comment: {
|
||||
required: true,
|
||||
message: 'Заполните этот блок',
|
||||
trigger: 'blur'
|
||||
}
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
open.value = false
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal v-model:show="open" title="Нежелательное событие" preset="card" class="max-w-xl">
|
||||
<NForm ref="formRef" :model="reportStore.reportForm" :rules="rules">
|
||||
<NFormItem :show-label="false" path="comment">
|
||||
<NInput type="textarea" :rows="8" v-model:value="reportStore.reportForm.comment" />
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
|
||||
<template #action>
|
||||
<NFlex align="center" justify="end">
|
||||
<NButton type="primary" tertiary @click="onSubmit">
|
||||
Сохранить
|
||||
</NButton>
|
||||
</NFlex>
|
||||
</template>
|
||||
</NModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -2,17 +2,26 @@
|
||||
import AppLayout from "../../Layouts/AppLayout.vue";
|
||||
import ReportForm from "./Components/ReportForm.vue";
|
||||
import {useReportStore} from "../../Stores/report.js";
|
||||
import {onMounted} from "vue";
|
||||
import {computed, onMounted} from "vue";
|
||||
import {useAuthStore} from "../../Stores/auth.js";
|
||||
|
||||
const reportStore = useReportStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
onMounted(async () => {
|
||||
await reportStore.getReportInfo()
|
||||
})
|
||||
|
||||
const mode = computed(() => {
|
||||
if (authStore.isHeadOfDepartment)
|
||||
return 'readonly'
|
||||
return 'fillable'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout>
|
||||
<ReportForm />
|
||||
<ReportForm :mode />
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import {ref, computed, watch} from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import axios from 'axios'
|
||||
import {usePage} from "@inertiajs/vue3";
|
||||
|
||||
export const useAuthStore = defineStore('authStore', () => {
|
||||
const user = usePage().props.user
|
||||
const token = user?.token
|
||||
const permissions = user?.permissions
|
||||
const availableDepartments = ref(user?.available_departments)
|
||||
const page = usePage()
|
||||
const user = ref(page.props.user)
|
||||
const token = computed(() => user.value?.token)
|
||||
const role = computed(() => user.value?.role)
|
||||
const permissions = computed(() => user.value?.permissions)
|
||||
const availableDepartments = computed(() => user.value?.available_departments)
|
||||
const availableRoles = computed(() => user.value?.available_roles)
|
||||
|
||||
watch(
|
||||
() => page.props.user,
|
||||
(newUser) => {
|
||||
user.value = newUser
|
||||
},
|
||||
{ deep: true, immediate: true })
|
||||
|
||||
// Инициализация axios с токеном
|
||||
if (token?.value) {
|
||||
@@ -16,12 +26,10 @@ export const useAuthStore = defineStore('authStore', () => {
|
||||
|
||||
// Вычисляемые свойства
|
||||
const isAuthenticated = computed(() => !!user.value && !!token.value)
|
||||
const isAdmin = computed(() => user.role === 'admin')
|
||||
const isDoctor = computed(() => user.role === 'doctor')
|
||||
const isNurse = computed(() => user.role === 'nurse')
|
||||
const isHeadOfDepartment = computed(() => user.role === 'head_of_department')
|
||||
const isStatistician = computed(() => user.role === 'statistician')
|
||||
const userDepartment = computed(() => user.current_department || '')
|
||||
const isAdmin = computed(() => role.value?.slug === 'admin')
|
||||
const isDoctor = computed(() => role.value?.slug === 'doctor')
|
||||
const isHeadOfDepartment = computed(() => role.value?.slug === 'head_of_department')
|
||||
const userDepartment = computed(() => user.value?.current_department || '')
|
||||
|
||||
const clearAuthData = () => {
|
||||
user.value = null
|
||||
@@ -59,12 +67,11 @@ export const useAuthStore = defineStore('authStore', () => {
|
||||
token,
|
||||
permissions,
|
||||
availableDepartments,
|
||||
availableRoles,
|
||||
isAuthenticated,
|
||||
isAdmin,
|
||||
isDoctor,
|
||||
isNurse,
|
||||
isHeadOfDepartment,
|
||||
isStatistician,
|
||||
userDepartment,
|
||||
|
||||
clearAuthData,
|
||||
|
||||
@@ -19,7 +19,7 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
}
|
||||
})
|
||||
|
||||
const timestampCurrentRange = ref([timestampNow.value, timestampNow.value])
|
||||
const timestampCurrentRange = ref([null, null])
|
||||
|
||||
const dataOnReport = ref(null)
|
||||
|
||||
@@ -74,6 +74,9 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
const form = {
|
||||
metrics: reportForm.value,
|
||||
observationPatients: patientsData.value['observation'],
|
||||
unwantedEvent: {
|
||||
comment: reportForm.comment
|
||||
},
|
||||
...assignForm
|
||||
}
|
||||
|
||||
@@ -99,21 +102,40 @@ export const useReportStore = defineStore('reportStore', () => {
|
||||
await axios.get('/api/report')
|
||||
.then((res) => {
|
||||
reportInfo.value = res.data
|
||||
|
||||
reportForm.value.metrika_item_3 = reportInfo.value.department?.recipientCount
|
||||
reportForm.value.metrika_item_7 = reportInfo.value.department?.extractCount
|
||||
reportForm.value.metrika_item_8 = reportInfo.value.department?.currentCount
|
||||
|
||||
timestampCurrentRange.value = [
|
||||
reportInfo.value.dates.startAt,
|
||||
reportInfo.value.dates.endAt,
|
||||
]
|
||||
})
|
||||
.finally(() => {
|
||||
isLoadReportInfo.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const getDataOnReportDate = async () => {
|
||||
await axios.get(`/api/metric-forms/1/report-by-date?sent_at=${timestampCurrentRange.value}`)
|
||||
.then(res => {
|
||||
dataOnReport.value = res.data
|
||||
})
|
||||
.catch(err => {
|
||||
// Отчета на выбранную дату не найдено
|
||||
if (err.code === 404) {}
|
||||
})
|
||||
const getDataOnReportDate = async (dateRange) => {
|
||||
isLoadReportInfo.value = true
|
||||
timestampCurrentRange.value = dateRange
|
||||
await axios.get(`/api/report?startAt=${timestampCurrentRange.value[0]}&endAt=${timestampCurrentRange.value[1]}`)
|
||||
.then((res) => {
|
||||
reportInfo.value = res.data
|
||||
|
||||
reportForm.value.metrika_item_3 = reportInfo.value.department?.recipientCount
|
||||
reportForm.value.metrika_item_7 = reportInfo.value.department?.extractCount
|
||||
reportForm.value.metrika_item_8 = reportInfo.value.department?.currentCount
|
||||
|
||||
timestampCurrentRange.value = [
|
||||
reportInfo.value.dates.startAt,
|
||||
reportInfo.value.dates.endAt,
|
||||
]
|
||||
})
|
||||
.finally(() => {
|
||||
isLoadReportInfo.value = false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -27,6 +27,11 @@ Route::get('/report', [\App\Http\Controllers\Web\ReportController::class, 'index
|
||||
Route::get('/statistic', [\App\Http\Controllers\Web\StatisticController::class, 'index'])
|
||||
->middleware(['auth'])
|
||||
->name('statistic');
|
||||
|
||||
Route::post('/user/role/change', [\App\Http\Controllers\AuthController::class, 'changeRole'])
|
||||
->middleware(['auth'])
|
||||
->name('user.role.change');
|
||||
|
||||
Route::get('/path/patient', function () {
|
||||
return \Inertia\Inertia::render('Path/Patient');
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user