Много чего

This commit is contained in:
brusnitsyn
2025-12-25 17:30:50 +09:00
parent c4bb7ec6f9
commit a5209f45c8
25 changed files with 1521 additions and 574 deletions

View File

@@ -6,6 +6,7 @@ use App\Http\Resources\ArchiveHistoryResource;
use App\Http\Resources\ArchiveInfoResource;
use App\Models\ArchiveHistory;
use App\Models\ArchiveInfo;
use App\Models\SI\SttMedicalHistory;
use App\Rules\DateTimeOrStringOrNumber;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
@@ -21,7 +22,10 @@ class ArchiveHistoryController extends Controller
{
$archiveHistory = ArchiveHistory::find($id);
return response()->json($archiveHistory);
return response()->json([
...$archiveHistory->toArray(),
'type' => $archiveHistory->historyType()
]);
}
public function moveStore(Request $request)
@@ -34,36 +38,46 @@ class ArchiveHistoryController extends Controller
'employee_post' => 'nullable|string',
'comment' => 'nullable|string',
'has_lost' => 'boolean',
'historyable_id' => 'nullable|numeric',
'historyable_type' => 'required|string',
'archive_info_id' => 'required|numeric',
'type' => 'required|string',
]);
// Преобразуем timestamp в дату, если пришли числа
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])->format('Y-m-d');
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])
->setTimezone(config('app.timezone'))
->format('Y-m-d');
}
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])->format('Y-m-d');
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])
->setTimezone(config('app.timezone'))
->format('Y-m-d');
}
$archiveHistory = ArchiveHistory::create($data);
// Если переданы данные для полиморфной связи
if ($request->filled('historyable_id') && $request->filled('historyable_type')) {
// Найти связанную модель
$historyableClass = $request->input('historyable_type');
// Проверяем, существует ли класс модели
if (class_exists($historyableClass)) {
$historyableModel = $historyableClass::find($request->input('historyable_id'));
if ($historyableModel) {
// Связываем модели
$archiveHistory->historyable()->associate($historyableModel);
$archiveHistory->save();
}
}
$archiveInfo = ArchiveInfo::whereId($data['archive_info_id'])->first();
if ($data['type'] === 'mis') {
$archiveHistory = $archiveInfo->misHistory->archiveHistory()->create([
'issue_at' => $data['issue_at'],
'return_at' => $data['return_at'],
'org_id' => $data['org_id'],
'employee_name' => $data['employee_name'],
'employee_post' => $data['employee_post'],
'comment' => $data['comment'],
'has_lost' => $data['has_lost'],
'mis_history_id' => $archiveInfo->mis_history_id
]);
} else {
$archiveHistory = $archiveInfo->foxproHistory->archiveHistory()->create([
'issue_at' => $data['issue_at'],
'return_at' => $data['return_at'],
'org_id' => $data['org_id'],
'employee_name' => $data['employee_name'],
'employee_post' => $data['employee_post'],
'comment' => $data['comment'],
'has_lost' => $data['has_lost'],
'foxpro_history_id' => $archiveInfo->foxpro_history_id,
]);
}
return response()->json(ArchiveHistoryResource::make($archiveHistory));
@@ -79,17 +93,20 @@ class ArchiveHistoryController extends Controller
'employee_post' => 'nullable|string',
'comment' => 'nullable|string',
'has_lost' => 'boolean',
'historyable_id' => 'nullable|numeric',
'historyable_type' => 'required|string',
'type' => 'required|string',
]);
// Преобразуем timestamp в дату, если пришли числа
if (isset($data['issue_at']) && is_numeric($data['issue_at'])) {
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])->format('Y-m-d');
$data['issue_at'] = Carbon::createFromTimestampMs($data['issue_at'])
->setTimezone(config('app.timezone'))
->format('Y-m-d');
}
if (isset($data['return_at']) && is_numeric($data['return_at'])) {
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])->format('Y-m-d');
$data['return_at'] = Carbon::createFromTimestampMs($data['return_at'])
->setTimezone(config('app.timezone'))
->format('Y-m-d');
}
$archiveHistory = ArchiveHistory::find($id);
@@ -105,7 +122,8 @@ class ArchiveHistoryController extends Controller
'id' => 'required|numeric',
'num' => 'nullable|string',
'post_in' => ['nullable', new DateTimeOrStringOrNumber],
'historyable_type' => 'required|string',
'status' => 'nullable',
'type' => 'nullable'
]);
// Преобразуем timestamp в дату, если пришли числа
@@ -113,25 +131,16 @@ class ArchiveHistoryController extends Controller
$data['post_in'] = Carbon::createFromTimestampMs($data['post_in'])->format('Y-m-d');
}
if ($patientId && $request->filled('historyable_type')) {
// Найти связанную модель
$historyableClass = $request->input('historyable_type');
$archiveInfo = ArchiveInfo::whereId($patientId)->first();
// Проверяем, существует ли класс модели
if (class_exists($historyableClass)) {
$historyableModel = $historyableClass::find($patientId);
$archiveInfo->updateOrCreate(
['id' => $patientId],
[
'archive_num' => $data['num'],
'post_in' => $data['post_in'],
]
);
if ($historyableModel) {
// Связываем модели
$historyableModel->archiveInfo()->updateOrCreate([
'historyable_type' => $historyableClass,
'historyable_id' => $patientId,
], $data);
return response()->json(ArchiveInfoResource::make($historyableModel->archiveInfo));
}
}
}
return response()->json()->setStatusCode(500);
return response()->json()->setStatusCode(200);
}
}

View File

@@ -25,58 +25,15 @@ class IndexController extends Controller
$searchText = $request->get('search', null);
$dateExtractFrom = $request->get('date_extract_from', null);
$dateExtractTo = $request->get('date_extract_to', null);
$database = $request->get('database', 'separate'); // si, mis
$status = $request->get('status', null);
$data = [];
$databaseStats = $this->repository->getDatabaseStats();
switch ($database) {
case 'si':
$paginator = $this->repository->searchInPostgres(
$searchText,
$dateExtractFrom,
$dateExtractTo,
$pageSize
);
$data['si'] = SiSttMedicalHistoryResource::collection($paginator);
break;
case 'mis':
$paginator = $this->repository->searchInMssql(
$searchText,
$dateExtractFrom,
$dateExtractTo,
$pageSize
);
$data['mis'] = MisSttMedicalHistoryResource::collection($paginator);
break;
case 'smart':
$paginator = $this->repository->smartSearch(
$searchText,
$dateExtractFrom,
$dateExtractTo,
$pageSize
);
$data['smart'] = SiSttMedicalHistoryResource::collection($paginator);
break;
case 'separate':
$separateResults = $this->repository->separateSearch(
$searchText,
$dateExtractFrom,
$dateExtractTo,
$status,
$pageSize
);
$data = [
'si' => SiSttMedicalHistoryResource::collection($separateResults['si']),
'mis' => MisSttMedicalHistoryResource::collection($separateResults['mis']),
'stats' => $separateResults['stats'],
];
break;
}
$data = $this->repository->unifiedSearch(
$searchText,
$dateExtractFrom,
$dateExtractTo,
$status,
$pageSize
);
$statuses = ArchiveStatus::all()->map(function ($status) {
return [
@@ -91,35 +48,13 @@ class IndexController extends Controller
]);
return Inertia::render('Home/Index', [
'cards' => $data,
'cards' => MisSttMedicalHistoryResource::collection($data),
'statuses' => $statuses,
'databaseStats' => $databaseStats,
'filters' => array_merge($request->only([
'search', 'date_extract_from', 'date_extract_to',
'page_size', 'page', 'view_type', 'database', 'status'
'page_size', 'page', 'status'
]))
]);
// $cardsQuery = SttMedicalHistory::query();
//
// if (!empty($searchText)) {
// $cardsQuery = $cardsQuery->search($searchText);
// }
//
// if (!empty($dateExtractFrom)) {
// $cardsQuery = $cardsQuery->whereDate('dateextract', '>=', $dateExtractFrom);
// if (!empty($dateExtractTo)) {
// $cardsQuery = $cardsQuery->whereDate('dateextract', '<=', $dateExtractTo);
// }
// }
//
// $cards = SttMedicalHistoryResource::collection($cardsQuery->paginate($pageSize));
//
// return Inertia::render('Home/Index', [
// 'cards' => $cards,
// 'filters' => $request->only([
// 'search', 'date_extract_from', 'date_extract_to', 'page_size', 'page', 'view_type'
// ]),
// ]);
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Http\Resources\ArchiveHistoryResource;
use App\Http\Resources\ArchiveInfoResource;
use App\Http\Resources\PatientInfoResource;
use App\Models\ArchiveInfo;
use App\Models\SI\SttMedicalHistory as SiSttMedicalHistory;
use App\Models\Mis\SttMedicalHistory as MisSttMedicalHistory;
use App\Repositories\MedicalHistoryRepository;
@@ -14,24 +15,25 @@ class MedicalHistoryController extends Controller
{
public function patient($id, Request $request)
{
$viewType = $request->get('view_type', 'si');
$viewType = $request->get('view_type', 'mis');
$patientId = $request->get('patient_id');
$patientInfo = null;
if ($viewType == 'si') $patient = SiSttMedicalHistory::where('id', $id)->first();
else $patient = MisSttMedicalHistory::where('MedicalHistoryID', $id)->first();
$archiveJournal = $patient->archiveHistory ? ArchiveHistoryResource::collection($patient->archiveHistory) : null;
$archiveInfo = ArchiveInfo::whereId($id)->first()->load('status');
if ($viewType == 'foxpro') $patient = $archiveInfo->foxproHistory;
else $patient = $archiveInfo->misHistory;
if (!empty($patient->archiveInfo)) {
$archiveInfo = ArchiveInfoResource::make($patient->archiveInfo)->toArray(request());
$archiveJournal = $patient->archiveHistory ? ArchiveHistoryResource::collection($patient->archiveHistory) : null;
// dd($archiveInfo);
if (!empty($archiveInfo)) {
$archiveInfo = ArchiveInfoResource::make($archiveInfo)->toArray(request());
} else {
$archiveInfo = null;
}
$patientInfo = [
'historyable_type' => $viewType == 'si' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
'historyable_type' => $viewType == 'foxpro' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
'info' => [
'historyable_type' => $viewType == 'si' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
'historyable_type' => $viewType == 'foxpro' ? SiSttMedicalHistory::class : MisSttMedicalHistory::class,
...PatientInfoResource::make($patient)->toArray(request()),
'can_be_issued' => $patient->canBeIssued()
],

View File

@@ -21,7 +21,7 @@ class ArchiveHistoryResource extends JsonResource
'return_at' => $this->return_at ? Carbon::parse($this->return_at)->format('d.m.Y') : null,
'comment' => $this->comment,
'org_id' => $this->org_id,
'org' => $this->org->name,
'org' => $this->org?->name,
'employee_name' => $this->employee_name,
'employee_post' => $this->employee_post,
'has_lost' => $this->has_lost,

View File

@@ -16,11 +16,12 @@ class ArchiveInfoResource extends JsonResource
{
return [
'id' => $this->id,
'num' => $this->num,
'num' => $this->archive_num,
'post_in' => $this->post_in,
'status' => $this->status,
'historyable_id' => $this->historyable_id,
'historyable_type' => $this->historyable_type,
'foxpro_num' => $this->foxpro_num,
'mis_num' => $this->mis_num,
'type' => $this->historyType()
];
}
}

View File

@@ -2,9 +2,9 @@
namespace App\Http\Resources\Mis;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Carbon;
class SttMedicalHistoryResource extends JsonResource
{
@@ -15,17 +15,114 @@ class SttMedicalHistoryResource extends JsonResource
*/
public function toArray(Request $request): array
{
// Определяем источник данных
$isFromArchive = $this->resource['in_archive'] ?? false;
$isTemporary = $this->resource['is_temporary'] ?? false;
$historyType = $this->resource['history_type'] ?? 'mis';
// Формируем ФИО
$family = $this->resource['family'] ?? '';
$name = $this->resource['name'] ?? '';
$ot = $this->resource['ot'] ?? '';
// Для временных записей (не в архиве) используем данные из MIS
if ($isTemporary) {
// Данные из stt_medicalhistory (не в архиве)
$fullName = trim("{$family} {$name} {$ot}");
$birthDate = $this->resource['birth_date'] ?? null;
$dateExtract = $this->resource['date_extract'] ?? null;
$dateRecipient = null; // Для MIS записей не в архиве может не быть
$cardNumber = $this->resource['card_number'] ?? null;
$archiveNum = null;
$postIn = null;
$status = $this->resource['status_text'] ?? 'Не в архиве';
} else {
// Данные из archive_infos (в архиве)
$fullName = trim("{$family} {$name} {$ot}");
$birthDate = $this->resource['birth_date'] ?? null;
// Для архивных записей date_extract может быть из MIS или FoxPro
$dateExtract = $this->resource['date_extract'] ?? null;
// Для MIS записей в архиве
if ($historyType === 'mis') {
$dateRecipient = $this->resource['date_recipient'] ?? null;
} else {
// Для FoxPro записей в архиве
$dateRecipient = $this->resource['mpostdate'] ?? null;
}
$cardNumber = $this->resource['card_number'] ?? null;
$archiveNum = $this->resource['archive_num'] ?? null;
$postIn = $this->resource['post_in'] ?? null;
$status = $this->resource['status_text'] ?? 'Неизвестно';
}
// Форматирование дат
$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;
return [
'id' => $this->MedicalHistoryID,
'fullname' => $this->getFullNameAttribute(),
'daterecipient' => Carbon::parse($this->DateRecipient)->format('d.m.Y'),
'dateextract' => Carbon::parse($this->DateExtract)->format('d.m.Y'),
'card_num' => $this->archiveInfo->num ?? null,
'status' => $this->archiveInfo->status ?? null,
'datearhiv' => $this->whenLoaded('archiveInfo') ? Carbon::parse($this->archiveInfo->post_in)->format('d.m.Y') : null,
'medcardnum' => $this->MedCardNum,
'dr' => Carbon::parse($this->BD)->format('d.m.Y'),
'can_be_issue' => $this->canBeIssued()
'id' => $this->resource['id'],
'history_type' => $historyType,
'in_archive' => $isFromArchive,
'is_temporary' => $isTemporary,
'source' => $this->resource['source'] ?? 'archive',
// Основные данные
'fullname' => $fullName,
'family' => $family,
'name' => $name,
'ot' => $ot,
'dr' => $formattedBirthDate,
'daterecipient' => $formattedDateRecipient,
'dateextract' => $formattedDateExtract,
// Номера карт
'medcardnum' => $cardNumber, // MIS номер или FoxPro номер
'mis_card_number' => $this->resource['mis_card_number'] ?? null, // Оригинальный MIS номер
'foxpro_card_number' => $this->resource['foxpro_card_number'] ?? null, // Оригинальный 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,
// Дополнительные идентификаторы
'mis_history_id' => $this->resource['mis_history_id'] ?? null,
'foxpro_history_id' => $this->resource['foxpro_history_id'] ?? null,
// Дополнительные данные
'snils' => $this->resource['snils'] ?? null,
'enp' => $this->resource['enp'] ?? null,
// 'created_at' => $this->resource->created_at ? Carbon::parse($this->resource->created_at)->format('d.m.Y H:i') : null,
// 'updated_at' => $this->resource->updated_at ? Carbon::parse($this->resource->updated_at)->format('d.m.Y H:i') : null,
// Стили для фронта
'row_class' => $this->resource['row_class'] ?? '',
'status_color' => $this->getStatusColor($this->resource['status_id'] ?? 0, $isFromArchive),
];
}
/**
* Получение цвета статуса для фронта
*/
private function getStatusColor(int $statusId, bool $inArchive): string
{
if (!$inArchive) {
return 'warning'; // Желтый для не в архиве
}
return match($statusId) {
1 => 'success', // Зеленый для в архиве
2 => 'info', // Синий для выдано
3, 4 => 'danger', // Красный для утрачено/списано
default => 'secondary',
};
}
}

View File

@@ -15,10 +15,10 @@ class PatientInfoResource extends JsonResource
public function toArray(Request $request): array
{
return [
'id' => $this->id ?? $this->MedicalHistoryID,
'medcardnum' => $this->medcardnum ?? $this->MedCardNum,
'family' => $this->family ?? $this->FAMILY,
'name' => $this->name ?? $this->Name,
'id' => $this->keykarta ?? $this->MedicalHistoryID,
'medcardnum' => $this->nkarta ?? $this->MedCardNum,
'family' => $this->fam ?? $this->FAMILY,
'name' => $this->im ?? $this->Name,
'ot' => $this->ot ?? $this->OT,
];
}