update
This commit is contained in:
@@ -7,7 +7,9 @@ use App\CriticalValueSample;
|
||||
use App\Organisms;
|
||||
use App\Periksa;
|
||||
use App\PeriksaSYNC;
|
||||
use App\Paslab;
|
||||
use App\Riwayat;
|
||||
use App\SIMBHPReport;
|
||||
use App\Subjawaban;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
@@ -15,6 +17,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class MobileApiController extends Controller
|
||||
@@ -154,6 +157,7 @@ class MobileApiController extends Controller
|
||||
'klinisi' => $row->klinisi,
|
||||
'klinis' => $row->klinis,
|
||||
'nmdokter' => $row->nmdokter,
|
||||
'kd_spesimen' => $row->kd_spesimen,
|
||||
'nm_spesimen' => $row->nm_spesimen,
|
||||
'kesimpulan' => $row->kesimpulan,
|
||||
'dlp' => $row->dlp,
|
||||
@@ -230,19 +234,187 @@ class MobileApiController extends Controller
|
||||
'butuh_verifikasi' => Periksa::where('status', 'like', '%Un Verified%')->count(),
|
||||
'antrian_hari_ini' => Periksa::whereDate('daftar', Carbon::today())->count(),
|
||||
'antrian_sinkron' => PeriksaSYNC::where('created_by', $user->username)->where('status', '')->count(),
|
||||
'criticalNotificationCount' => CriticalValueSample::whereNull('followed_up_at')->count(),
|
||||
],
|
||||
'books' => $books,
|
||||
'early_warning_groups' => $this->earlyWarningGroups(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function criticalValueNotifications(Request $request)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
$range = $this->resolveCriticalValueReportRange($request);
|
||||
|
||||
return response()->json([
|
||||
'count' => CriticalValueSample::whereNull('followed_up_at')->count(),
|
||||
'pending_items' => $this->criticalValueItems(
|
||||
CriticalValueSample::whereNull('followed_up_at')
|
||||
->orderBy('critical_set_at', 'asc')
|
||||
->limit(100)
|
||||
->get()
|
||||
),
|
||||
'followed_items' => $this->criticalValueItems(
|
||||
CriticalValueSample::whereNotNull('followed_up_at')
|
||||
->where('followed_up_at', '>=', $range['start_at'])
|
||||
->where('followed_up_at', '<=', $range['end_at'])
|
||||
->orderBy('followed_up_at', 'desc')
|
||||
->limit(100)
|
||||
->get()
|
||||
),
|
||||
'start_date' => $range['start_date'],
|
||||
'end_date' => $range['end_date'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function criticalValueNotificationMarkRead(Request $request, int $id)
|
||||
{
|
||||
$user = $this->requireUser($request);
|
||||
$criticalSample = CriticalValueSample::find($id);
|
||||
abort_if(!$criticalSample, 404, 'Sample nilai kritis tidak ditemukan.');
|
||||
|
||||
if (!empty($criticalSample->followed_up_at)) {
|
||||
return response()->json([
|
||||
'message' => 'Sample nilai kritis ini sudah ditindaklanjuti sebelumnya.',
|
||||
'item' => $this->criticalValueItem($criticalSample),
|
||||
]);
|
||||
}
|
||||
|
||||
$followUpMethod = trim((string) $request->input('caratindaklanjut', ''));
|
||||
$followUpRecipient = trim((string) $request->input('penerima_laporan', ''));
|
||||
$followUpReason = trim((string) $request->input('alasan_belum_laporkan', ''));
|
||||
|
||||
if ($followUpMethod === '') {
|
||||
if ($followUpReason === '') {
|
||||
return response()->json([
|
||||
'message' => 'Alasan belum dilaporkan wajib diisi jika belum dilaporkan.',
|
||||
], 422);
|
||||
}
|
||||
} else {
|
||||
$allowed = ['Telpon', 'Whatshap', 'Email', 'Ketemu di Jalan'];
|
||||
if (!in_array($followUpMethod, $allowed, true)) {
|
||||
return response()->json(['message' => 'Cara tindak lanjut tidak valid.'], 422);
|
||||
}
|
||||
if ($followUpRecipient === '') {
|
||||
return response()->json([
|
||||
'message' => 'Penerima laporan wajib diisi jika sudah dilaporkan.',
|
||||
], 422);
|
||||
}
|
||||
}
|
||||
|
||||
$criticalSample->followed_up_at = Carbon::now();
|
||||
$criticalSample->followed_up_by_user_id = $user->id;
|
||||
$criticalSample->followed_up_by_name = $user->nama;
|
||||
$criticalSample->follow_up_status = $followUpMethod === '' ? 'not_reported' : 'reported';
|
||||
$criticalSample->follow_up_method = $followUpMethod !== '' ? $followUpMethod : null;
|
||||
$criticalSample->follow_up_recipient = $followUpRecipient !== '' ? $followUpRecipient : null;
|
||||
$criticalSample->follow_up_reason = $followUpReason !== '' ? $followUpReason : null;
|
||||
$criticalSample->save();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Sample nilai kritis sudah ditandai sudah ditindaklanjuti.',
|
||||
'item' => $this->criticalValueItem($criticalSample),
|
||||
'count' => CriticalValueSample::whereNull('followed_up_at')->count(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function resolveCriticalValueReportRange(Request $request): array
|
||||
{
|
||||
$defaultStart = Carbon::now()->startOfMonth()->toDateString();
|
||||
$defaultEnd = Carbon::now()->endOfMonth()->toDateString();
|
||||
$startDate = trim((string) $request->query('start_date', $defaultStart));
|
||||
$endDate = trim((string) $request->query('end_date', $defaultEnd));
|
||||
|
||||
try {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $startDate)->startOfDay();
|
||||
} catch (\Throwable $e) {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $defaultStart)->startOfDay();
|
||||
$startDate = $defaultStart;
|
||||
}
|
||||
|
||||
try {
|
||||
$end = Carbon::createFromFormat('Y-m-d', $endDate)->endOfDay();
|
||||
} catch (\Throwable $e) {
|
||||
$end = Carbon::createFromFormat('Y-m-d', $defaultEnd)->endOfDay();
|
||||
$endDate = $defaultEnd;
|
||||
}
|
||||
|
||||
if ($start->gt($end)) {
|
||||
[$start, $end] = [$end->copy()->startOfDay(), $start->copy()->endOfDay()];
|
||||
$startDate = $start->toDateString();
|
||||
$endDate = $end->toDateString();
|
||||
}
|
||||
|
||||
return [
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
'start_at' => $start,
|
||||
'end_at' => $end,
|
||||
];
|
||||
}
|
||||
|
||||
protected function criticalValueItems($items): array
|
||||
{
|
||||
return $items->map(fn ($item) => $this->criticalValueItem($item))->values()->all();
|
||||
}
|
||||
|
||||
protected function criticalValueItem(CriticalValueSample $item): array
|
||||
{
|
||||
$tatMinutes = null;
|
||||
$tatDurationLabel = '-';
|
||||
$tatStatusLabel = '-';
|
||||
|
||||
if (!empty($item->critical_set_at) && !empty($item->followed_up_at)) {
|
||||
$criticalSetAt = Carbon::parse($item->critical_set_at);
|
||||
$followedUpAt = Carbon::parse($item->followed_up_at);
|
||||
$tatMinutes = $criticalSetAt->diffInMinutes($followedUpAt);
|
||||
$tatDurationLabel = $this->formatCriticalValueTatDuration($tatMinutes);
|
||||
$tatStatusLabel = $tatMinutes <= 30 ? 'Memenuhi TAT' : 'Tidak Memenuhi TAT';
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'periksa_id' => $item->periksa_id,
|
||||
'nofoto' => $item->nofoto,
|
||||
'noregister' => $item->noregister,
|
||||
'nmpasien' => $item->nmpasien,
|
||||
'asalpasien' => $item->asalpasien,
|
||||
'nm_spesimen' => $item->nm_spesimen,
|
||||
'critical_set_at' => $item->critical_set_at,
|
||||
'critical_set_by_name' => $item->critical_set_by_name,
|
||||
'followed_up_at' => $item->followed_up_at,
|
||||
'followed_up_by_name' => $item->followed_up_by_name,
|
||||
'tat_minutes' => $tatMinutes,
|
||||
'tat_duration_label' => $tatDurationLabel,
|
||||
'tat_status_label' => $tatStatusLabel,
|
||||
'follow_up_status' => $item->follow_up_status,
|
||||
'follow_up_method' => $item->follow_up_method,
|
||||
'follow_up_recipient' => $item->follow_up_recipient,
|
||||
'follow_up_reason' => $item->follow_up_reason,
|
||||
];
|
||||
}
|
||||
|
||||
protected function formatCriticalValueTatDuration(int $totalMinutes): string
|
||||
{
|
||||
$hours = intdiv($totalMinutes, 60);
|
||||
$minutes = $totalMinutes % 60;
|
||||
|
||||
if ($hours > 0) {
|
||||
return $hours.' jam '.$minutes.' menit';
|
||||
}
|
||||
|
||||
return $minutes.' menit';
|
||||
}
|
||||
|
||||
public function examinations(Request $request, string $master)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
$query = $this->activeExaminationQuery();
|
||||
$mapped = collect($this->bookPoliMap())->flatten()->all();
|
||||
|
||||
if ($master === 'buku0') {
|
||||
if ($master === 'ALL') {
|
||||
// Semua spesimen: tidak dibatasi kategori buku/poli.
|
||||
} elseif ($master === 'buku0') {
|
||||
$query->whereNotIn('poli_id', $mapped);
|
||||
} elseif (isset($this->bookPoliMap()[$master])) {
|
||||
$query->whereIn('poli_id', $this->bookPoliMap()[$master]);
|
||||
@@ -260,15 +432,237 @@ class MobileApiController extends Controller
|
||||
});
|
||||
}
|
||||
|
||||
$items = $query->orderBy('daftar', 'ASC')->limit(250)->get()->map(fn ($row) => $this->examinationPayload($row));
|
||||
$query->orderBy('daftar', 'ASC');
|
||||
if ($master !== 'ALL') {
|
||||
$query->limit(250);
|
||||
}
|
||||
$items = $query->get()->map(fn ($row) => $this->examinationPayload($row));
|
||||
|
||||
return response()->json([
|
||||
'master' => $master,
|
||||
'label' => $this->bookLabels[$master],
|
||||
'label' => $master === 'ALL' ? 'Semua Spesimen' : $this->bookLabels[$master],
|
||||
'items' => $items,
|
||||
]);
|
||||
}
|
||||
|
||||
public function searchExamination(Request $request)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
$search = trim((string) $request->query('search', ''));
|
||||
abort_if($search === '', 422, 'Kata kunci pencarian wajib diisi.');
|
||||
$exactColumns = $this->availablePeriksaColumns(['nofoto', 'noregister', 'orderid', 'acc_number', 'barcode']);
|
||||
$likeColumns = $this->availablePeriksaColumns(['nofoto', 'noregister', 'nmpasien', 'reques', 'orderid', 'acc_number', 'barcode']);
|
||||
|
||||
$row = $this->activeExaminationQuery()
|
||||
->where(function ($q) use ($search, $exactColumns) {
|
||||
foreach ($exactColumns as $index => $column) {
|
||||
$index === 0
|
||||
? $q->where($column, $search)
|
||||
: $q->orWhere($column, $search);
|
||||
}
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$row) {
|
||||
$row = $this->activeExaminationQuery()
|
||||
->where(function ($q) use ($search, $likeColumns) {
|
||||
foreach ($likeColumns as $index => $column) {
|
||||
$index === 0
|
||||
? $q->where($column, 'like', "%{$search}%")
|
||||
: $q->orWhere($column, 'like', "%{$search}%");
|
||||
}
|
||||
})
|
||||
->orderBy('daftar', 'desc')
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$row) {
|
||||
return response()->json(['message' => 'Data pemeriksaan tidak ditemukan.'], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'item' => $this->examinationPayload($row),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function availablePeriksaColumns(array $columns): array
|
||||
{
|
||||
return array_values(array_filter(
|
||||
$columns,
|
||||
fn ($column) => Schema::hasColumn('periksa', $column)
|
||||
));
|
||||
}
|
||||
|
||||
public function initialWorkSamples(Request $request)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
|
||||
$items = Periksa::query()
|
||||
->whereIn('status', [
|
||||
'Penerimaan Sampel',
|
||||
'Pemeriksaan Sampel',
|
||||
'Pemeriksaan Awal',
|
||||
'Pemeriksaan awal',
|
||||
])
|
||||
->orderBy('id', 'DESC')
|
||||
->limit(500)
|
||||
->get()
|
||||
->map(fn ($row) => $this->examinationPayload($row))
|
||||
->values();
|
||||
|
||||
return response()->json([
|
||||
'items' => $items,
|
||||
'total' => $items->count(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function initialWorkAccept(Request $request, int $id)
|
||||
{
|
||||
$user = $this->requireUser($request);
|
||||
$row = Periksa::find($id);
|
||||
abort_if(!$row, 404, 'Data pemeriksaan tidak ditemukan.');
|
||||
|
||||
$mediaTanam = $request->input('mediatanam', []);
|
||||
if (!is_array($mediaTanam)) {
|
||||
$mediaTanam = [$mediaTanam];
|
||||
}
|
||||
$mediaTanam = array_values(array_filter($mediaTanam, fn ($item) => trim((string) $item) !== ''));
|
||||
if (count($mediaTanam) === 0) {
|
||||
return response()->json([
|
||||
'message' => 'Media Tanam Yang di gunakan wajib dipilih.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$jenis = trim((string) $request->input('jenis', ''));
|
||||
$bulan = trim((string) $request->input('bulan', ''));
|
||||
if ($jenis !== '' && $jenis !== 'F' && $bulan === '') {
|
||||
return response()->json([
|
||||
'message' => 'Jika jenis pengobatan bukan Follow Up, Bulan Ke wajib diisi.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
if ($jenis !== '') {
|
||||
$this->acceptInitialWorkWithTreatmentCode($row, $user, $jenis, $bulan);
|
||||
} else {
|
||||
$this->acceptInitialWork($row, $user);
|
||||
}
|
||||
|
||||
$this->recordInitialWorkMediaUsage($row->fresh(), $mediaTanam, $user);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Sampel berhasil diterima.',
|
||||
'item' => $this->examinationPayload($row->fresh()),
|
||||
]);
|
||||
}
|
||||
|
||||
public function initialWorkReject(Request $request, int $id)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
$updated = Periksa::where('id', $id)->update([
|
||||
'status' => null,
|
||||
]);
|
||||
|
||||
if (!$updated) {
|
||||
return response()->json([
|
||||
'message' => 'Data pemeriksaan tidak ditemukan atau tidak dapat ditolak.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Sampel dikembalikan ke loket.',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function acceptInitialWork(Periksa $row, User $user): void
|
||||
{
|
||||
$row->status = 'Pemeriksaan awal';
|
||||
$row->tgldraft = Carbon::now();
|
||||
if (empty($row->mulai)) {
|
||||
$row->mulai = Carbon::now();
|
||||
}
|
||||
$row->excutor = $user->id;
|
||||
$row->nmppdsmiddle2 = $user->nama;
|
||||
$row->save();
|
||||
}
|
||||
|
||||
protected function acceptInitialWorkWithTreatmentCode(Periksa $row, User $user, string $jenis, string $bulan): void
|
||||
{
|
||||
$nofoto = $row->nofoto.$jenis.$bulan;
|
||||
Paslab::updateOrCreate(
|
||||
['rnoreg' => $nofoto],
|
||||
[
|
||||
'nama' => $row->nmpasien,
|
||||
'norm' => $row->noregister,
|
||||
'rtglast' => $row->daftar,
|
||||
'alamat' => $row->alamatpasien,
|
||||
'rjenis' => $row->jkpasien,
|
||||
'umur' => $row->usia,
|
||||
'namadok' => $row->ktp,
|
||||
'ruangan' => $row->asalpasien,
|
||||
'tes' => $row->reques,
|
||||
'alat' => 'ALL',
|
||||
'kd_spesimen' => $row->kd_spesimen,
|
||||
'nm_spesimen' => $row->nm_spesimen,
|
||||
'tgllahir' => $row->tgllahirpasien,
|
||||
'flg_vitek1' => true,
|
||||
'flg_vitek2' => true,
|
||||
'flg_bd1' => true,
|
||||
'flg_bd2' => false,
|
||||
'flg_gxp1' => true,
|
||||
'flg_gxp2' => true,
|
||||
'flg_gxp3' => true,
|
||||
'flg_vitek3' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$row->nofoto = $nofoto;
|
||||
$row->status = 'Pemeriksaan awal';
|
||||
$row->tgldraft = Carbon::now();
|
||||
$row->mulai = Carbon::now();
|
||||
$row->excutor = $user->id;
|
||||
$row->nmppdsmiddle2 = $user->nama;
|
||||
$row->save();
|
||||
}
|
||||
|
||||
protected function recordInitialWorkMediaUsage(?Periksa $row, array $mediaTanam, User $user): void
|
||||
{
|
||||
if (!$row) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($mediaTanam as $media) {
|
||||
$jenis = $this->mediaTanamReportName((string) $media);
|
||||
if ($jenis === '') {
|
||||
continue;
|
||||
}
|
||||
$today = Carbon::today();
|
||||
SIMBHPReport::create([
|
||||
'tanggal' => (int) $today->format('d'),
|
||||
'bulan' => (int) $today->format('m'),
|
||||
'tahun' => (int) $today->format('Y'),
|
||||
'deskripsi' => 'Pemeriksaan Awal Nomor Lab.'.$row->nofoto.' petugas '.$user->nama,
|
||||
'pemasukan' => null,
|
||||
'pengeluaran' => 1,
|
||||
'qty_base' => 1,
|
||||
'satuan_transaksi' => 'besar',
|
||||
'jenis' => $jenis,
|
||||
'keterangan' => '',
|
||||
'marking' => '',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function mediaTanamReportName(string $media): string
|
||||
{
|
||||
return match ($media) {
|
||||
'Media BAP' => 'PLATE BAP (Blood Agar Plate) MEDIA',
|
||||
'Media CAP' => 'PLATE CAP (Chocolate Agar Plate) Media',
|
||||
'Media Mc Conkey' => 'PLATE MC (Mac Conkey Agar Plate) MEDIA',
|
||||
'Media SDA R1', 'Media SDA R2', 'Media SDA I1', 'Media SDA I2' => 'PLATE SDA (Saboroud Dextrose Agar Plate) MEDIA',
|
||||
default => '',
|
||||
};
|
||||
}
|
||||
|
||||
public function examination(Request $request, int $id)
|
||||
{
|
||||
$this->requireUser($request);
|
||||
|
||||
Reference in New Issue
Block a user