diff --git a/app/Http/Controllers/ArchiveHistoryController.php b/app/Http/Controllers/ArchiveHistoryController.php
index 543e2b9..417b971 100644
--- a/app/Http/Controllers/ArchiveHistoryController.php
+++ b/app/Http/Controllers/ArchiveHistoryController.php
@@ -38,7 +38,7 @@ class ArchiveHistoryController extends Controller
'employee_post' => 'nullable|string',
'comment' => 'nullable|string',
'has_lost' => 'boolean',
- 'archive_info_id' => 'required|numeric',
+ 'history_id' => 'required',
'type' => 'required|string',
]);
@@ -55,9 +55,16 @@ class ArchiveHistoryController extends Controller
->format('Y-m-d');
}
- $archiveInfo = ArchiveInfo::whereId($data['archive_info_id'])->first();
if ($data['type'] === 'mis') {
- $archiveHistory = $archiveInfo->misHistory->archiveHistory()->create([
+ $patient = \App\Models\Mis\SttMedicalHistory::where('MedicalHistoryID', $data['history_id'])->first();
+ } else {
+ $patient = \App\Models\Si\SttMedicalHistory::where('keykarta', $data['history_id'])->first();
+ }
+
+// $archiveInfo = ArchiveInfo::whereId($data['archive_info_id'])->first();
+
+ if ($data['type'] === 'mis') {
+ $archiveHistory = $patient->archiveHistory()->create([
'issue_at' => $data['issue_at'],
'return_at' => $data['return_at'],
'org_id' => $data['org_id'],
@@ -65,10 +72,10 @@ class ArchiveHistoryController extends Controller
'employee_post' => $data['employee_post'],
'comment' => $data['comment'],
'has_lost' => $data['has_lost'],
- 'mis_history_id' => $archiveInfo->mis_history_id
+ 'mis_history_id' => $patient->MedicalHistoryID
]);
} else {
- $archiveHistory = $archiveInfo->foxproHistory->archiveHistory()->create([
+ $archiveHistory = $patient->archiveHistory()->create([
'issue_at' => $data['issue_at'],
'return_at' => $data['return_at'],
'org_id' => $data['org_id'],
@@ -76,7 +83,7 @@ class ArchiveHistoryController extends Controller
'employee_post' => $data['employee_post'],
'comment' => $data['comment'],
'has_lost' => $data['has_lost'],
- 'foxpro_history_id' => $archiveInfo->foxpro_history_id,
+ 'foxpro_history_id' => $patient->keykarta,
]);
}
@@ -131,10 +138,9 @@ class ArchiveHistoryController extends Controller
$data['post_in'] = Carbon::createFromTimestampMs($data['post_in'])->format('Y-m-d');
}
- $archiveInfo = ArchiveInfo::whereId($patientId)->first();
+ $archiveInfo = ArchiveInfo::whereId($data['id'])->first();
- $archiveInfo->updateOrCreate(
- ['id' => $patientId],
+ $archiveInfo->update(
[
'archive_num' => $data['num'],
'post_in' => $data['post_in'],
diff --git a/app/Http/Controllers/ArchiveInfoController.php b/app/Http/Controllers/ArchiveInfoController.php
new file mode 100644
index 0000000..19417c2
--- /dev/null
+++ b/app/Http/Controllers/ArchiveInfoController.php
@@ -0,0 +1,38 @@
+validate([
+ 'id' => 'required',
+ 'num' => 'required',
+ 'post_in' => 'required'
+ ]);
+
+ // Преобразуем timestamp в дату, если пришли числа
+ if (isset($data['post_in']) && is_numeric($data['post_in'])) {
+ $data['post_in'] = Carbon::createFromTimestampMs($data['post_in'])
+ ->setTimezone(config('app.timezone'))
+ ->format('Y-m-d');
+ }
+
+ $history = SttMedicalHistory::where('MedicalHistoryID', $data['id'])->first();
+
+ $hasCreated = ArchiveInfo::create([
+ 'mis_num' => $history->MedCardNum,
+ 'mis_history_id' => $data['id'],
+ 'archive_num' => $data['num'],
+ 'post_in' => $data['post_in'],
+ ]);
+
+ return $hasCreated;
+ }
+}
diff --git a/app/Http/Controllers/IndexController.php b/app/Http/Controllers/IndexController.php
index 6346769..393be0b 100644
--- a/app/Http/Controllers/IndexController.php
+++ b/app/Http/Controllers/IndexController.php
@@ -2,21 +2,25 @@
namespace App\Http\Controllers;
+use App\Http\Resources\IndexSttMedicalHistoryResource;
use App\Http\Resources\SI\SttMedicalHistoryResource as SiSttMedicalHistoryResource;
use App\Http\Resources\Mis\SttMedicalHistoryResource as MisSttMedicalHistoryResource;
use App\Models\ArchiveStatus;
use App\Models\SI\SttMedicalHistory;
use App\Repositories\MedicalHistoryRepository;
+use App\Services\ArchiveCardService;
use Illuminate\Http\Request;
use Inertia\Inertia;
class IndexController extends Controller
{
private MedicalHistoryRepository $repository;
+ private ArchiveCardService $cardService;
- public function __construct(MedicalHistoryRepository $repository)
+ public function __construct(MedicalHistoryRepository $repository, ArchiveCardService $cardService)
{
$this->repository = $repository;
+ $this->cardService = $cardService;
}
public function index(Request $request)
@@ -27,7 +31,15 @@ class IndexController extends Controller
$dateExtractTo = $request->get('date_extract_to', null);
$status = $request->get('status', null);
- $data = $this->repository->unifiedSearch(
+// $data = $this->repository->unifiedSearch(
+// $searchText,
+// $dateExtractFrom,
+// $dateExtractTo,
+// $status,
+// $pageSize
+// );
+
+ $data = $this->cardService->get(
$searchText,
$dateExtractFrom,
$dateExtractTo,
@@ -35,6 +47,8 @@ class IndexController extends Controller
$pageSize
);
+// dd($data);
+
$statuses = ArchiveStatus::all()->map(function ($status) {
return [
'value' => $status->id,
@@ -42,13 +56,8 @@ class IndexController extends Controller
];
});
- $statuses->push([
- 'value' => 0,
- 'label' => 'Нет в архиве',
- ]);
-
return Inertia::render('Home/Index', [
- 'cards' => MisSttMedicalHistoryResource::collection($data),
+ 'cards' => IndexSttMedicalHistoryResource::collection($data),
'statuses' => $statuses,
'filters' => array_merge($request->only([
'search', 'date_extract_from', 'date_extract_to',
diff --git a/app/Http/Controllers/MedicalHistoryController.php b/app/Http/Controllers/MedicalHistoryController.php
index c67d3cc..be5b21d 100644
--- a/app/Http/Controllers/MedicalHistoryController.php
+++ b/app/Http/Controllers/MedicalHistoryController.php
@@ -33,7 +33,7 @@ class MedicalHistoryController extends Controller
'can_be_issued' => $patient->canBeIssued()
],
'journal' => $archiveJournal,
- 'archiveInfo' => $archiveInfo
+ 'archiveInfo' => $archiveInfo ? ArchiveInfoResource::make($archiveInfo) : null
];
return response()->json($patientInfo);
diff --git a/app/Http/Controllers/MisHistoryController.php b/app/Http/Controllers/MisHistoryController.php
new file mode 100644
index 0000000..d3d2a98
--- /dev/null
+++ b/app/Http/Controllers/MisHistoryController.php
@@ -0,0 +1,74 @@
+validate([
+ 'query' => 'required|string'
+ ]);
+
+ $searchText = $data['query'];
+ $searchParts = preg_split('/\s+/', trim($searchText));
+
+ $query = SttMedicalHistory::query();
+
+ // Проверяем, начинается ли строка с цифры (вероятно, это номер карты)
+ $isCardNumberSearch = is_numeric($searchParts[0]);
+
+ if ($isCardNumberSearch) {
+ // Паттерн: № Ф И О
+ $query->where('MedCardNum', 'ILIKE', "$searchParts[0]%");
+
+ // ФИО начинается со второй части
+ $fioStartIndex = 1;
+ } else {
+ // Паттерн: Ф И О (без номера)
+ $fioStartIndex = 0;
+ }
+
+ // Ищем ФИО в зависимости от количества оставшихся частей
+ $fioPartsCount = count($searchParts) - $fioStartIndex;
+
+ if ($fioPartsCount === 1) {
+ // Одно слово - ищем в фамилии, имени или отчестве
+ $query->where(function ($q) use ($searchParts, $fioStartIndex) {
+ $q->where('FAMILY', 'ILIKE', "{$searchParts[$fioStartIndex]}%")
+ ->orWhere('Name', 'ILIKE', "{$searchParts[$fioStartIndex]}%")
+ ->orWhere('OT', 'ILIKE', "{$searchParts[$fioStartIndex]}%");
+ });
+ } elseif ($fioPartsCount === 2) {
+ // Два слова - фамилия и инициал имени
+ $query->where(function ($q) use ($searchParts, $fioStartIndex) {
+ $q->where('FAMILY', 'ILIKE', "{$searchParts[$fioStartIndex]}%")
+ ->where('Name', 'ILIKE', "{$searchParts[$fioStartIndex + 1]}%");
+ });
+ } elseif ($fioPartsCount === 3) {
+ // Три слова - полное ФИО
+ $query->where(function ($q) use ($searchParts, $fioStartIndex) {
+ $q->where('FAMILY', 'ILIKE', "{$searchParts[$fioStartIndex]}%")
+ ->where('Name', 'ILIKE', "{$searchParts[$fioStartIndex + 1]}%")
+ ->where('OT', 'ILIKE', "{$searchParts[$fioStartIndex + 2]}%");
+ });
+ }
+
+ // Также ищем полную строку в объединенных полях
+ $query->orWhereRaw("CONCAT(\"MedCardNum\", ' ', \"FAMILY\", ' ', \"Name\", ' ', \"OT\") ILIKE ?", ["{$searchText}%"]);
+
+ $results = $query->select([
+ 'MedicalHistoryID', 'MedCardNum', 'FAMILY', 'Name', 'OT'
+ ])->get()->map(function ($item) {
+ return [
+ 'label' => "$item->MedCardNum - $item->FAMILY $item->Name $item->OT",
+ 'value' => $item->MedicalHistoryID
+ ];
+ });
+
+ return response()->json($results);
+ }
+}
diff --git a/app/Http/Resources/IndexSttMedicalHistoryResource.php b/app/Http/Resources/IndexSttMedicalHistoryResource.php
new file mode 100644
index 0000000..aed22d7
--- /dev/null
+++ b/app/Http/Resources/IndexSttMedicalHistoryResource.php
@@ -0,0 +1,85 @@
+
+ */
+ public function toArray(Request $request): array
+ {
+ // Получаем оригинальную модель
+ $model = $this->resource;
+
+ $archiveInfo = $model->archiveInfo;
+ $historyType = $archiveInfo->historyType();
+
+ $inArchive = $archiveInfo->exists;
+ $hasMisType = $historyType === 'mis';
+
+ $family = $hasMisType ? $model->FAMILY : $model->fam;
+ $im = $hasMisType ? $this->Name : $this->im;
+ $ot = $hasMisType ? $this->OT : $this->ot;
+
+ $fio = "$family $im $ot";
+
+ $birthDate = $hasMisType ? $this->BD : $this->dr;
+ $dateRecipient = $hasMisType ? $this->DateRecipient : $this->mpostdate;
+ $dateExtract = $hasMisType ? $this->DateExtract : $this->menddate;
+ $postIn = $inArchive ? $archiveInfo->post_in : null;
+
+ $formattedBirthDate = $birthDate ? Carbon::parse($birthDate)->format('d.m.Y') : null;
+ $formattedDateRecipient = $dateRecipient ? Carbon::parse($dateRecipient)->format('d.m.Y') : null;
+ $formattedDateExtract = $dateExtract ? Carbon::parse($dateExtract)->format('d.m.Y') : null;
+ $formattedPostIn = $postIn ? Carbon::parse($postIn)->format('d.m.Y') : null;
+
+ $id = $historyType === 'mis' ? $this->MedicalHistoryID : $this->keykarta;
+ $archiveNum = $inArchive ? $archiveInfo->archive_num : null;
+ $status = $inArchive ? $archiveInfo->status : ArchiveStatus::find(5)->first();
+
+ $misCardNumber = $this->MedCardNum;
+ $foxproCardNumber = $this->nkarta;
+
+ $archiveInfoMisCardNumber = $inArchive ? $archiveInfo->mis_num : null;
+ $archiveInfoFoxproCardNumber = $inArchive ? $archiveInfo->foxpro_num : null;
+
+ $hasDividerCardNumber = isset($archiveInfoMisCardNumber) && isset($archiveInfoFoxproCardNumber);
+
+ $cardNumber = $hasDividerCardNumber
+ ? "$archiveInfoMisCardNumber / $archiveInfoFoxproCardNumber"
+ : $archiveInfoMisCardNumber ?? $archiveInfoFoxproCardNumber;
+
+ return [
+ 'id' => $id,
+ 'history_type' => $historyType,
+
+ // Основные данные
+ 'fullname' => $fio,
+ 'family' => $family,
+ 'name' => $im,
+ 'ot' => $ot,
+ 'dr' => $formattedBirthDate,
+ 'daterecipient' => $formattedDateRecipient,
+ 'dateextract' => $formattedDateExtract,
+
+ // Номера карт
+ 'medcardnum' => $cardNumber, // MIS номер или FoxPro номер
+ 'card_num' => $archiveNum, // Архивный номер
+ 'datearhiv' => $formattedPostIn,
+
+ // Статус и возможности
+ 'status' => $status,
+ 'status_id' => $this->resource['status_id'] ?? 0,
+ 'can_be_issued' => $this->resource['can_be_issued'] ?? false,
+ 'can_add_to_archive' => $this->resource['can_add_to_archive'] ?? false,
+ ];
+ }
+}
diff --git a/app/Models/ArchiveHistory.php b/app/Models/ArchiveHistory.php
index 5c77800..61a27fc 100644
--- a/app/Models/ArchiveHistory.php
+++ b/app/Models/ArchiveHistory.php
@@ -23,16 +23,12 @@ class ArchiveHistory extends Model
public function updateArchiveInfoStatus()
{
- // Получаем связанную модель через морф
- $historyable = $this->historyable;
-
- if (!$historyable) {
- return;
- }
-
- // Проверяем, есть ли у модели архивная информация
- if (method_exists($historyable, 'archiveInfo') && $historyable->archiveInfo) {
- $historyable->archiveInfo->update([
+ if ($this->mis_history_id) {
+ $this->misHistory->archiveInfo->update([
+ 'status_id' => $this->determineStatusId()
+ ]);
+ } else {
+ $this->foxproHistory->archiveInfo->update([
'status_id' => $this->determineStatusId()
]);
}
@@ -70,12 +66,12 @@ class ArchiveHistory extends Model
public function foxproHistory()
{
- return $this->belongsTo(SiMedicalHistory::class, 'keykarta', 'foxpro_history_id');
+ return $this->belongsTo(SiMedicalHistory::class, 'foxpro_history_id', 'keykarta');
}
public function misHistory()
{
- return $this->belongsTo(MisMedicalHistory::class, 'MedicalHistoryID', 'mis_history_id');
+ return $this->belongsTo(MisMedicalHistory::class, 'mis_history_id', 'MedicalHistoryID');
}
public function historyType()
diff --git a/app/Services/ArchiveCardService.php b/app/Services/ArchiveCardService.php
new file mode 100644
index 0000000..bd9cc58
--- /dev/null
+++ b/app/Services/ArchiveCardService.php
@@ -0,0 +1,140 @@
+orderBy('post_in', 'desc');
+
+ // Поиск по тексту (если передан)
+ if (!empty($searchText)) {
+ $query->where(function ($q) use ($searchText) {
+ // Разбиваем строку поиска на части (по пробелам)
+ $searchParts = preg_split('/\s+/', trim($searchText));
+
+ $q->where(function ($subQuery) use ($searchParts, $searchText) {
+ // Сначала проверяем MIS историю
+ $subQuery->whereHas('misHistory', function ($misQuery) use ($searchParts, $searchText) {
+ $this->applySearchToHistory($misQuery, $searchParts, $searchText, 'mis');
+ });
+
+ // ИЛИ проверяем Foxpro историю (только если нет MIS истории)
+ $subQuery->orWhere(function ($orWhereSubQuery) use ($searchParts, $searchText) {
+ $orWhereSubQuery->whereNull('mis_history_id') // Нет MIS истории
+ ->whereHas('foxproHistory', function ($foxproQuery) use ($searchParts, $searchText) {
+ $this->applySearchToHistory($foxproQuery, $searchParts, $searchText, 'foxpro');
+ });
+ });
+ })
+ // Ищем по архивным номерам
+ ->orWhere('archive_num', 'ILIKE', "{$searchText}%")
+ ->orWhere('mis_num', 'ILIKE', "{$searchText}%")
+ ->orWhere('foxpro_num', 'ILIKE', "{$searchText}%");
+ });
+ }
+
+ // Фильтрация по дате выписки
+ if (!empty($dateExtractFrom)) {
+ $query->where(function ($q) use ($dateExtractFrom) {
+ $q->whereHas('misHistory', function ($misQuery) use ($dateExtractFrom) {
+ $misQuery->whereDate('DateExtract', '>=', $dateExtractFrom);
+ })->orWhereHas('foxproHistory', function ($foxproQuery) use ($dateExtractFrom) {
+ $foxproQuery->whereDate('menddate', '>=', $dateExtractFrom);
+ });
+ });
+ }
+
+ if (!empty($dateExtractTo)) {
+ $query->where(function ($q) use ($dateExtractTo) {
+ $q->whereHas('misHistory', function ($misQuery) use ($dateExtractTo) {
+ $misQuery->whereDate('DateExtract', '<=', $dateExtractTo);
+ })->orWhereHas('foxproHistory', function ($foxproQuery) use ($dateExtractTo) {
+ $foxproQuery->whereDate('menddate', '<=', $dateExtractTo);
+ });
+ });
+ }
+
+ // Фильтрация по статусу (если передан)
+ if (!empty($status)) {
+ $query->where('status_id', $status);
+ }
+
+ // Получаем результаты с пагинацией
+ $results = $query->paginate($pageSize)
+ ->through(function ($archiveInfo) {
+ // Приоритет MIS истории
+ if ($archiveInfo->misHistory) {
+ $history = $archiveInfo->misHistory;
+ $history->history_type = 'mis';
+ } else {
+ $history = $archiveInfo->foxproHistory;
+ $history->history_type = 'foxpro';
+ }
+
+ return $history;
+ });
+
+ return $results;
+ }
+
+ private function applySearchToHistory($query, $searchParts, $searchText, $type)
+ {
+ if ($type === 'mis') {
+ $query->where('MedCardNum', 'ILIKE', "{$searchText}%");
+
+ // Ищем ФИО в зависимости от количества частей
+ if (count($searchParts) === 1) {
+ $query->orWhere('FAMILY', 'ILIKE', "{$searchParts[0]}%")
+ ->orWhere('Name', 'ILIKE', "{$searchParts[0]}%")
+ ->orWhere('OT', 'ILIKE', "{$searchParts[0]}%");
+ } elseif (count($searchParts) === 2) {
+ $query->orWhere(function ($subQuery) use ($searchParts) {
+ $subQuery->where('FAMILY', 'ILIKE', "{$searchParts[0]}%")
+ ->where('Name', 'ILIKE', "{$searchParts[1]}%");
+ });
+ } elseif (count($searchParts) === 3) {
+ $query->orWhere(function ($subQuery) use ($searchParts) {
+ $subQuery->where('FAMILY', 'ILIKE', "{$searchParts[0]}%")
+ ->where('Name', 'LIKE', "{$searchParts[1]}%")
+ ->where('OT', 'ILIKE', "{$searchParts[2]}%");
+ });
+ }
+
+ $query->orWhereRaw("CONCAT(\"FAMILY\", ' ', \"Name\", ' ', \"OT\") ILIKE ?", ["{$searchText}%"]);
+ } else { // foxpro
+ $query->where('nkarta', 'ILIKE', "{$searchText}%");
+
+ if (count($searchParts) === 1) {
+ $query->orWhere('fam', 'ILIKE', "{$searchParts[0]}%")
+ ->orWhere('im', 'ILIKE', "{$searchParts[0]}%")
+ ->orWhere('ot', 'ILIKE', "{$searchParts[0]}%");
+ } elseif (count($searchParts) === 2) {
+ $query->orWhere(function ($subQuery) use ($searchParts) {
+ $subQuery->where('fam', 'ILIKE', "{$searchParts[0]}%")
+ ->where('im', 'ILIKE', "{$searchParts[1]}%");
+ });
+ } elseif (count($searchParts) === 3) {
+ $query->orWhere(function ($subQuery) use ($searchParts) {
+ $subQuery->where('fam', 'ILIKE', "{$searchParts[0]}%")
+ ->where('im', 'ILIKE', "{$searchParts[1]}%")
+ ->where('ot', 'ILIKE', "{$searchParts[2]}%");
+ });
+ }
+
+ $query->orWhereRaw("CONCAT(fam, ' ', im, ' ', ot) ILIKE ?", ["{$searchText}%"]);
+ }
+ }
+}
diff --git a/resources/js/Pages/Home/ArchiveHistoryCreateModal/Index.vue b/resources/js/Pages/Home/ArchiveHistoryCreateModal/Index.vue
new file mode 100644
index 0000000..e8b308b
--- /dev/null
+++ b/resources/js/Pages/Home/ArchiveHistoryCreateModal/Index.vue
@@ -0,0 +1,104 @@
+
+
+
+