From 1a1d58e60a021aa3de8992ace3019f02cfdb7873 Mon Sep 17 00:00:00 2001 From: Dwi Swandhana Date: Thu, 23 Apr 2026 13:55:32 +0700 Subject: [PATCH] update --- .../app/Http/Controllers/GudangController.php | 12 ++++++++- .../app/Http/Controllers/ReportController.php | 4 --- htdocs/app/Livewire/GudangPos.php | 23 ++++++++++++++++ htdocs/resources/views/admin/gudang.blade.php | 27 ++++++++++--------- .../views/livewire/gudang-pos.blade.php | 5 ++++ listener/app.py | 26 ++++++++++++++---- 6 files changed, 74 insertions(+), 23 deletions(-) diff --git a/htdocs/app/Http/Controllers/GudangController.php b/htdocs/app/Http/Controllers/GudangController.php index 58c05a21..9361046f 100644 --- a/htdocs/app/Http/Controllers/GudangController.php +++ b/htdocs/app/Http/Controllers/GudangController.php @@ -845,10 +845,12 @@ class GudangController extends Controller $rows = $query->get(); $grouped = []; + $jenisNames = []; foreach ($rows as $row) { $jenis = $row->jenis ?: 'Tidak Diketahui'; if (!isset($grouped[$jenis])) { - $grouped[$jenis] = ['jenis' => $jenis, 'masuk' => 0, 'keluar' => 0]; + $grouped[$jenis] = ['jenis' => $jenis, 'masuk' => 0, 'keluar' => 0, 'sisa' => 0]; + $jenisNames[] = $jenis; } if (!is_null($row->pemasukan) && (int)$row->pemasukan > 0) { $grouped[$jenis]['masuk'] += $this->extractBaseQty($row, 'pemasukan'); @@ -858,6 +860,14 @@ class GudangController extends Controller } } + if (!empty($jenisNames)) { + $stockMap = app(SimbhpStockService::class)->getStockBaseByJenisMany($jenisNames); + foreach ($grouped as $jenis => &$item) { + $item['sisa'] = (int) ($stockMap[$jenis] ?? 0); + } + unset($item); + } + return array_values($grouped); } diff --git a/htdocs/app/Http/Controllers/ReportController.php b/htdocs/app/Http/Controllers/ReportController.php index ac5a35e5..bf005926 100644 --- a/htdocs/app/Http/Controllers/ReportController.php +++ b/htdocs/app/Http/Controllers/ReportController.php @@ -868,14 +868,10 @@ class ReportController extends Controller $bulan = str_replace('bulan=', '', $bulan); $tahun = str_replace('tahun=', '', $tahun); } - - // Query Periksa $query = Periksa::query()->where('dlp', 'Kultur')->whereNotNull('dokter_id')->whereYear('daftar', $tahun); if ($bulan != 'ALL' && $bulan != 'Pick Month') { $query->whereMonth('daftar', $bulan); } - - // Preview dibuat paginated agar aman saat filter setahun. $orderbydate = $query->orderBy('daftar', 'ASC')->orderBy('id', 'ASC')->paginate(50); $orderbydate->appends(['bulan' => $bulan, 'tahun' => $tahun]); diff --git a/htdocs/app/Livewire/GudangPos.php b/htdocs/app/Livewire/GudangPos.php index d10c1252..8567eb80 100644 --- a/htdocs/app/Livewire/GudangPos.php +++ b/htdocs/app/Livewire/GudangPos.php @@ -329,10 +329,30 @@ class GudangPos extends Component $jenisNames = $products->getCollection()->pluck('jenis')->filter()->values()->all(); $stockMap = $service->getStockBaseByJenisMany($jenisNames); + $latestExpiredMap = []; + if (count($jenisNames) > 0) { + $expiredRows = SIMBHPReport::query() + ->select('jenis', DB::raw('MAX(masa_expired) as latest_expired')) + ->whereIn('jenis', $jenisNames) + ->whereNotNull('masa_expired') + ->whereNotNull('pemasukan') + ->where('pemasukan', '>', 0) + ->groupBy('jenis') + ->get(); + + foreach ($expiredRows as $row) { + $jenisNama = (string) ($row->jenis ?? ''); + $expired = (string) ($row->latest_expired ?? ''); + if ($jenisNama !== '' && $expired !== '') { + $latestExpiredMap[$jenisNama] = Carbon::parse($expired)->format('d-m-Y'); + } + } + } $selectedJenis = null; $selectedStockDisplay = null; $selectedSetting = null; + $selectedLatestExpired = null; $kode = $service->sanitizeKode($this->selectedKode); if ($kode !== '') { $selectedJenis = $service->getJenisByKode($kode); @@ -345,6 +365,7 @@ class GudangPos extends Component (string) ($selectedJenis->satuan_kecil ?? ''), (int) ($selectedJenis->konversi_kecil ?? 1), ); + $selectedLatestExpired = $latestExpiredMap[(string) $selectedJenis->jenis] ?? null; } } @@ -352,9 +373,11 @@ class GudangPos extends Component 'users' => $users, 'products' => $products, 'stockMap' => $stockMap, + 'latestExpiredMap' => $latestExpiredMap, 'selectedJenis' => $selectedJenis, 'selectedStockDisplay' => $selectedStockDisplay, 'selectedSetting' => $selectedSetting, + 'selectedLatestExpired' => $selectedLatestExpired, ]); } } diff --git a/htdocs/resources/views/admin/gudang.blade.php b/htdocs/resources/views/admin/gudang.blade.php index f7fea0cc..82e6c07d 100644 --- a/htdocs/resources/views/admin/gudang.blade.php +++ b/htdocs/resources/views/admin/gudang.blade.php @@ -124,9 +124,6 @@
-
- -
@@ -150,6 +147,9 @@
Catatan: sistem akan menyimpan per-item menjadi baris transaksi (mirip stok opname). +
+ +
@@ -207,12 +207,12 @@
- + @forelse($stat_perjenis_harian ?? [] as $row) - + @empty - + @endforelse
JenisMasukKeluar
JenisMasukKeluarSisa Stok
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}{{ number_format($row['sisa'] ?? 0,0,'.',',') }}
Belum ada transaksi
Belum ada transaksi
@@ -227,12 +227,12 @@
- + @forelse($stat_perjenis_bulanan ?? [] as $row) - + @empty - + @endforelse
JenisMasukKeluar
JenisMasukKeluarSisa Stok
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}{{ number_format($row['sisa'] ?? 0,0,'.',',') }}
Belum ada transaksi
Belum ada transaksi
@@ -247,12 +247,12 @@
- + @forelse($stat_perjenis_tahunan ?? [] as $row) - + @empty - + @endforelse
JenisMasukKeluar
JenisMasukKeluarSisa Stok
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}
{{ $row['jenis'] }}{{ number_format($row['masuk'],0,'.',',') }}{{ number_format($row['keluar'],0,'.',',') }}{{ number_format($row['sisa'] ?? 0,0,'.',',') }}
Belum ada transaksi
Belum ada transaksi
@@ -869,10 +869,11 @@ '' + escapeHtml(r.jenis || '-') + '' + '' + formatInt(r.masuk || 0) + '' + '' + formatInt(r.keluar || 0) + '' + + '' + formatInt(r.sisa || 0) + '' + ''; }); if(!html){ - html = 'Belum ada transaksi'; + html = 'Belum ada transaksi'; } $(tbodyId).html(html); } diff --git a/htdocs/resources/views/livewire/gudang-pos.blade.php b/htdocs/resources/views/livewire/gudang-pos.blade.php index 7af69519..64f18fa6 100644 --- a/htdocs/resources/views/livewire/gudang-pos.blade.php +++ b/htdocs/resources/views/livewire/gudang-pos.blade.php @@ -24,6 +24,7 @@ @php $saldoBase = (int) ($stockMap[$p->jenis] ?? 0); $warning = $saldoBase <= (int) ($p->stok_minimum ?? 0); + $latestExpired = $latestExpiredMap[$p->jenis] ?? null; @endphp
@@ -46,6 +47,9 @@
Satuan: {{ $p->satuan }} @if(($p->satuan_kecil ?? '') !== '') / {{ $p->satuan_kecil }} @endif
+
+ Expired terakhir: {{ $latestExpired ?: '-' }} +
@empty @@ -139,6 +143,7 @@
{{ $selectedJenis->jenis }}
Stok: {{ $selectedStockDisplay }}
+
Expired terakhir: {{ $selectedLatestExpired ?: '-' }}
@endif
diff --git a/listener/app.py b/listener/app.py index 2d8c3ba2..476c6f95 100644 --- a/listener/app.py +++ b/listener/app.py @@ -474,9 +474,9 @@ def create_genexpert_rsp_z02_response(orders, incoming_hl7, ip_addr=None): segments.append(f"PID|{patient_idx}||{patient_id}||{patient_name}||{dob}|{sex}|||{address}") segments.append(f"ORC|NW|1|||||||{order_ts}") - segments.append(f"OBR|1|||{assay_code}^{requested_test_name}^L|||||||A") + segments.append(f"OBR|1|||{assay_code}|||||||A") segments.append("TQ1|||||||||R") - segments.append(f"SPM|1|{sample_id}^{sample_id}||{specimen_type}|||||||P") + segments.append(f"SPM|1|{sample_id}^||ORH|||||||P") return "\r".join(segments) + "\r" @@ -595,6 +595,15 @@ def send_genexpert_response(conn, ip_addr, hl7_message, framing, label=""): ) conn.sendall(payload) +def send_genexpert_transport_ack(conn, ip_addr, framing, reason="frame-received"): + if framing != "astm": + return + try: + conn.sendall(b"\x06") + print(f"[GENEXPERT-DEBUG] Transport ACK sent ip={ip_addr}, framing={framing}, reason={reason}") + except Exception as exc: + print(f"[GENEXPERT-DEBUG] Transport ACK gagal ip={ip_addr}, framing={framing}, reason={reason}, error={exc}") + def debug_genexpert_order_message(hl7_message, ip_addr=None): segments = parse_hl7_segments(hl7_message) current_pid = "" @@ -2109,10 +2118,10 @@ def handle_genexpert_client(conn, addr): msg_complete = True elif b'\x03' in buffer: # Pola ASTM (Ada Checksum setelahnya) # ASTM: ...CS - # Kita cari \x03, lalu tambah 4 byte (CS + CRLF) untuk aman + # Kita cari \x03, lalu ambil ETX + 2 checksum + CRLF secara penuh. pos = buffer.find(b'\x03') - if len(buffer) >= pos + 4: - end_marker_pos = pos + 4 + if len(buffer) >= pos + 5: + end_marker_pos = pos + 5 msg_complete = True elif b'\x04' in buffer: # Pola EOT (Putus Koneksi/Selesai) end_marker_pos = buffer.find(b'\x04') @@ -2126,6 +2135,13 @@ def handle_genexpert_client(conn, addr): full_message_bytes = buffer[:end_marker_pos] response_framing = detect_genexpert_message_framing(full_message_bytes) + + send_genexpert_transport_ack( + conn, + addr[0], + response_framing, + reason="incoming-frame-complete" + ) # Sisa buffer (jika ada paket nempel di belakangnya) disimpan untuk loop berikutnya buffer = buffer[end_marker_pos:]