diff --git a/htdocs/app/Http/Controllers/GudangController.php b/htdocs/app/Http/Controllers/GudangController.php index 7d033f02..2554db92 100644 --- a/htdocs/app/Http/Controllers/GudangController.php +++ b/htdocs/app/Http/Controllers/GudangController.php @@ -347,6 +347,238 @@ class GudangController extends Controller return response()->json($response, 200); } + public function jsonExpiredBatches(Request $request) + { + if (Session::get('previlage') == '') { + return response()->json(['message' => 'Unauthorized'], 401); + } + + $jenis = trim((string) $request->query('jenis', '')); + $query = SIMBHPReport::whereNotNull('pemasukan') + ->where('pemasukan', '>', 0); + + if ($jenis !== '') { + $query->where('jenis', $jenis); + } + + $rows = $query->orderByRaw('masa_expired IS NULL ASC') + ->orderBy('masa_expired', 'ASC') + ->orderBy('id', 'DESC') + ->limit(100) + ->get(); + + $items = []; + foreach ($rows as $row) { + $items[] = [ + 'id' => $row->id, + 'jenis' => $row->jenis, + 'deskripsi' => $row->deskripsi ?: '-', + 'tanggal_masuk' => sprintf('%02d-%02d-%04d', (int) $row->tanggal, (int) $row->bulan, (int) $row->tahun), + 'qty' => (int) ($row->pemasukan ?? 0), + 'satuan' => $row->satuan_transaksi ?: 'besar', + 'masa_expired' => $row->masa_expired ? date('d-m-Y', strtotime((string) $row->masa_expired)) : '', + ]; + } + + return response()->json(['data' => $items]); + } + + public function updateExpiredBatch(Request $request) + { + if (Session::get('previlage') == '') { + return response()->json(['message' => 'Unauthorized'], 401); + } + + $batchId = (int) $request->input('batch_id'); + $masaExpired = $this->normalizeDateInput($request->input('masa_expired')); + $alasan = trim((string) $request->input('alasan', 'Update expired barang terbuka')); + + if ($batchId <= 0 || is_null($masaExpired)) { + return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'Batch dan tanggal expired baru wajib diisi']); + } + + $row = SIMBHPReport::where('id', $batchId) + ->whereNotNull('pemasukan') + ->where('pemasukan', '>', 0) + ->first(); + + if (!$row) { + return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'Batch barang masuk tidak ditemukan']); + } + + $oldExpired = $row->masa_expired; + $keterangan = trim((string) ($row->keterangan ?? '')); + $suffix = 'Expired dibuka: '.($oldExpired ?: '-').' -> '.$masaExpired; + if ($alasan !== '') { + $suffix .= ' | '.$alasan; + } + + $row->masa_expired = $masaExpired; + $row->keterangan = $keterangan !== '' ? $keterangan.' | '.$suffix : $suffix; + $row->updated_at = date("Y-m-d H:i:s"); + $row->save(); + + return response()->json(['status' => 'Success', 'message' => 'Masa expired batch berhasil diupdate']); + } + + public function storeRacikan(Request $request) + { + if (Session::get('previlage') == '') { + return response()->json(['message' => 'Unauthorized'], 401); + } + + $tanggal = trim((string) $request->input('tanggal', date('Y-m-d'))); + $namaRacikan = trim((string) $request->input('nama_racikan', 'Racikan')); + $statusRacikan = strtolower(trim((string) $request->input('status_racikan', 'berhasil'))); + $bahan = $request->input('bahan', []); + if (is_string($bahan)) { + $decoded = json_decode($bahan, true); + $bahan = is_array($decoded) ? $decoded : []; + } + + if ($tanggal === '') { + $tanggal = date('Y-m-d'); + } + if ($namaRacikan === '') { + $namaRacikan = 'Racikan'; + } + if (!in_array($statusRacikan, ['berhasil', 'rusak'], true)) { + return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'Status racikan tidak valid']); + } + if (!is_array($bahan) || count($bahan) === 0) { + return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'Minimal satu bahan racikan wajib diisi']); + } + + $parts = explode('-', $tanggal); + $tahun = (int) ($parts[0] ?? date('Y')); + $wulan = (int) ($parts[1] ?? date('m')); + $dino = (int) ($parts[2] ?? date('d')); + $marking = 'RACIK-'.date('YmdHis').'-'.random_int(100, 999); + + try { + DB::transaction(function () use ($request, $bahan, $statusRacikan, $namaRacikan, $marking, $dino, $wulan, $tahun) { + $service = app(SimbhpStockService::class); + $prepared = []; + $requiredByJenis = []; + + foreach ($bahan as $line) { + $jenisNama = trim((string) ($line['jenis'] ?? '')); + $qty = (int) str_replace(',', '', (string) ($line['qty'] ?? 0)); + $satuanTransaksi = (string) ($line['satuan_transaksi'] ?? 'besar'); + if (!in_array($satuanTransaksi, ['besar', 'kecil'], true)) { + $satuanTransaksi = 'besar'; + } + if ($jenisNama === '' || $qty <= 0) { + throw new \InvalidArgumentException('Bahan dan jumlah wajib diisi'); + } + + $jenis = SIMBHPJenis::where('jenis', $jenisNama)->first(); + if (!$jenis) { + throw new \InvalidArgumentException('Bahan '.$jenisNama.' tidak ditemukan'); + } + $setting = $service->getUnitSetting($jenis); + if ($satuanTransaksi === 'kecil' && !($setting['has_breakdown'] ?? false)) { + throw new \InvalidArgumentException('Satuan kecil tidak tersedia untuk '.$jenisNama); + } + + $qtyBase = $service->calculateBaseQty($jenis, $qty, $satuanTransaksi); + $requiredByJenis[$jenisNama] = ($requiredByJenis[$jenisNama] ?? 0) + $qtyBase; + $prepared[] = [ + 'jenis' => $jenis, + 'qty' => $qty, + 'qty_base' => $qtyBase, + 'satuan_transaksi' => $satuanTransaksi, + 'batch_id' => (int) ($line['batch_id'] ?? 0), + 'expired_baru' => $this->normalizeDateInput($line['expired_baru'] ?? null), + ]; + } + + foreach ($requiredByJenis as $jenisNama => $requiredBase) { + $stok = $service->getStockBaseByJenis($jenisNama); + if ($requiredBase > $stok) { + throw new \InvalidArgumentException('Stok bahan '.$jenisNama.' tidak cukup'); + } + } + + foreach ($prepared as $line) { + $keterangan = $statusRacikan === 'berhasil' ? 'Bahan racikan berhasil' : 'Bahan racikan rusak'; + if ($line['expired_baru'] && $line['batch_id'] > 0) { + $batch = SIMBHPReport::where('id', $line['batch_id']) + ->where('jenis', $line['jenis']->jenis) + ->whereNotNull('pemasukan') + ->where('pemasukan', '>', 0) + ->first(); + if (!$batch) { + throw new \InvalidArgumentException('Batch expired untuk '.$line['jenis']->jenis.' tidak ditemukan'); + } + $oldExpired = $batch->masa_expired; + $oldKeterangan = trim((string) ($batch->keterangan ?? '')); + $expiredNote = 'Expired dibuka racikan '.$marking.': '.($oldExpired ?: '-').' -> '.$line['expired_baru']; + $batch->masa_expired = $line['expired_baru']; + $batch->keterangan = $oldKeterangan !== '' ? $oldKeterangan.' | '.$expiredNote : $expiredNote; + $batch->updated_at = date("Y-m-d H:i:s"); + $batch->save(); + $keterangan .= ' | Expired dibuka: '.($oldExpired ?: '-').' -> '.$line['expired_baru']; + } + + SIMBHPReport::create([ + 'tanggal' => $dino, + 'bulan' => $wulan, + 'tahun' => $tahun, + 'deskripsi' => 'Racikan '.$namaRacikan.' - bahan', + 'pemasukan' => null, + 'pengeluaran' => $line['qty'], + 'qty_base' => $line['qty_base'], + 'satuan_transaksi' => $line['satuan_transaksi'], + 'jenis' => $line['jenis']->jenis, + 'keterangan' => $keterangan, + 'marking' => $marking, + ]); + } + + if ($statusRacikan === 'berhasil') { + $hasil = $this->resolveRacikanOutputJenis($request); + $qtyHasil = (int) str_replace(',', '', (string) $request->input('hasil_qty', 0)); + $satuanHasil = (string) $request->input('hasil_satuan_transaksi', 'besar'); + if (!in_array($satuanHasil, ['besar', 'kecil'], true)) { + $satuanHasil = 'besar'; + } + if ($qtyHasil <= 0) { + throw new \InvalidArgumentException('Jumlah hasil racikan wajib diisi'); + } + $setting = $service->getUnitSetting($hasil); + if ($satuanHasil === 'kecil' && !($setting['has_breakdown'] ?? false)) { + throw new \InvalidArgumentException('Satuan kecil tidak tersedia untuk hasil racikan'); + } + $qtyBaseHasil = $service->calculateBaseQty($hasil, $qtyHasil, $satuanHasil); + + SIMBHPReport::create([ + 'tanggal' => $dino, + 'bulan' => $wulan, + 'tahun' => $tahun, + 'deskripsi' => 'Hasil racikan '.$namaRacikan, + 'pemasukan' => $qtyHasil, + 'pengeluaran' => null, + 'qty_base' => $qtyBaseHasil, + 'satuan_transaksi' => $satuanHasil, + 'masa_expired' => $this->normalizeDateInput($request->input('hasil_masa_expired')), + 'jenis' => $hasil->jenis, + 'keterangan' => 'Hasil racikan berhasil', + 'marking' => $marking, + ]); + } + }); + } catch (\Throwable $e) { + return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => $e->getMessage()]); + } + + $message = $statusRacikan === 'berhasil' + ? 'Racikan berhasil disimpan dan hasil masuk stok' + : 'Racikan rusak disimpan sebagai pengurangan bahan'; + + return response()->json(['status' => 'Success', 'message' => $message]); + } + public function exAddbarang(Request $request) { $deskripsi = $request->input('set01'); $pos = $request->input('set02'); @@ -919,6 +1151,82 @@ class GudangController extends Controller return null; } + private function resolveRacikanOutputJenis(Request $request): SIMBHPJenis + { + $mode = (string) $request->input('hasil_mode', 'existing'); + if ($mode === 'new') { + $nama = trim((string) $request->input('hasil_new_jenis')); + $satuan = trim((string) $request->input('hasil_new_satuan')); + $kode = trim((string) $request->input('hasil_new_kode')); + $satuanKecil = trim((string) $request->input('hasil_new_satuan_kecil')); + $konversi = (int) $request->input('hasil_new_konversi', 1); + $stokMinimum = (int) $request->input('hasil_new_stok_minimum', 0); + + if ($nama === '' || $satuan === '') { + throw new \InvalidArgumentException('Nama dan satuan hasil racikan baru wajib diisi'); + } + if ($konversi <= 0) { + $konversi = 1; + } + if ($stokMinimum < 0) { + $stokMinimum = 0; + } + if ($satuanKecil !== '' && $konversi <= 1) { + throw new \InvalidArgumentException('Konversi hasil racikan baru harus lebih dari 1 jika memakai satuan kecil'); + } + + if ($kode !== '') { + $kode = strtoupper($kode); + $kode = preg_replace('/\s+/', '', $kode); + $kode = preg_replace('/[^A-Z0-9._-]/', '', $kode); + } else { + $kode = strtoupper($nama); + $kode = preg_replace('/\s+/', '', $kode); + $kode = preg_replace('/[^A-Z0-9._-]/', '', $kode); + } + if ($kode === '' || strlen($kode) < 2 || strlen($kode) > 40) { + throw new \InvalidArgumentException('Kode hasil racikan wajib 2-40 karakter'); + } + + $existing = SIMBHPJenis::where('kodejenis', $kode)->first(); + if ($existing) { + return $existing; + } + + $jenis = SIMBHPJenis::create([ + 'kodejenis' => $kode, + 'jenis' => $nama, + 'satuan' => $satuan, + 'satuan_kecil' => $satuanKecil, + 'konversi_kecil' => $konversi, + 'stok_minimum' => $stokMinimum, + ]); + + if (Schema::hasColumn('simbhpjenis', 'barcode_besar')) { + $service = app(SimbhpStockService::class); + $setting = $service->getUnitSetting($jenis); + $jenis->update([ + 'barcode_besar' => $service->makeBarcodeValue((int) $jenis->id, 'besar'), + 'barcode_kecil' => ($setting['has_breakdown'] ?? false) ? $service->makeBarcodeValue((int) $jenis->id, 'kecil') : null, + ]); + } + + return $jenis; + } + + $jenisNama = trim((string) $request->input('hasil_jenis')); + if ($jenisNama === '') { + throw new \InvalidArgumentException('Barang hasil racikan wajib dipilih'); + } + + $jenis = SIMBHPJenis::where('jenis', $jenisNama)->first(); + if (!$jenis) { + throw new \InvalidArgumentException('Barang hasil racikan tidak ditemukan'); + } + + return $jenis; + } + private function getJenisRows() { $rows = []; diff --git a/htdocs/app/Http/Controllers/PasienController.php b/htdocs/app/Http/Controllers/PasienController.php index e5d26791..1af69a98 100644 --- a/htdocs/app/Http/Controllers/PasienController.php +++ b/htdocs/app/Http/Controllers/PasienController.php @@ -106,7 +106,7 @@ class PasienController extends Controller } else { try { $client = new Client(); - $res = $client->request('GET', 'https://gomed.rssa.my.id/api/account/pasien', ['query' => ['limit' => 10, 'nomedis' => $norm]]); + $res = $client->request('GET', 'http://10.10.123.204/api/account/pasien', ['query' => ['limit' => 10, 'nomedis' => $norm]]); $response_data = json_decode($res->getBody()->getContents()); if (isset($response_data->response[0])) { $hasil = $response_data->response[0]; diff --git a/htdocs/resources/views/admin/gudang.blade.php b/htdocs/resources/views/admin/gudang.blade.php index be15a639..6cf423e5 100644 --- a/htdocs/resources/views/admin/gudang.blade.php +++ b/htdocs/resources/views/admin/gudang.blade.php @@ -28,6 +28,9 @@ + @@ -246,6 +249,190 @@ +
+
+
+
+

Proses Racikan

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+

Update Expired Barang Terbuka

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+

Daftar Bahan Racikan

+
+ + + + + + + + + + + + + + +
KodeBahanQtySatuanExpired DibukaAksi
Belum ada bahan.
+
+
+
+

Hasil Racikan

+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ + +
+
+ +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+
@@ -759,8 +946,12 @@ $("#edit_tanggal").datepicker({format: 'yyyy-mm-dd'}); $("#op_in_tanggal").datepicker({format: 'yyyy-mm-dd'}); $("#op_adj_tanggal").datepicker({format: 'yyyy-mm-dd'}); + $("#racik_tanggal").datepicker({format: 'yyyy-mm-dd'}); $("#in_masa_expired").datepicker({format: 'dd-mm-yyyy'}); $("#op_in_masa_expired").datepicker({format: 'dd-mm-yyyy'}); + $("#racik_bahan_expired_baru").datepicker({format: 'dd-mm-yyyy'}); + $("#racik_hasil_expired").datepicker({format: 'dd-mm-yyyy'}); + $("#expired_update_date").datepicker({format: 'dd-mm-yyyy'}); $("#edit_masa_expired").datepicker({format: 'dd-mm-yyyy'}); $("#mulai").datepicker({format: 'yyyy-mm-dd'}); $("#akhir").datepicker({format: 'yyyy-mm-dd'}); @@ -884,6 +1075,7 @@ var jenisRows = @json($jenisRows ?? []); var opInLines = []; var opAdjLines = []; + var racikLines = []; var currentDetail = null; function escapeHtml(value){ @@ -1128,6 +1320,32 @@ } syncOpAdjSelected(); + var currentRacikBahan = $('#racik_bahan_pos').val(); + var htmlRacikBahan = ''; + items.forEach(function(r){ htmlRacikBahan += makeOption(r); }); + $('#racik_bahan_pos').html(htmlRacikBahan); + if(currentRacikBahan){ + $('#racik_bahan_pos').val(currentRacikBahan); + } + syncRacikBahanSelected(); + + var currentRacikHasil = $('#racik_hasil_pos').val(); + var htmlRacikHasil = ''; + items.forEach(function(r){ htmlRacikHasil += makeOption(r); }); + $('#racik_hasil_pos').html(htmlRacikHasil); + if(currentRacikHasil){ + $('#racik_hasil_pos').val(currentRacikHasil); + } + syncRacikHasilSelected(); + + var currentExpiredUpdate = $('#expired_update_pos').val(); + var htmlExpiredUpdate = ''; + items.forEach(function(r){ htmlExpiredUpdate += makeOption(r); }); + $('#expired_update_pos').html(htmlExpiredUpdate); + if(currentExpiredUpdate){ + $('#expired_update_pos').val(currentExpiredUpdate); + } + // Legacy selects (modal lama / editor) var legacyIds = ['#in_pos', '#out_pos']; legacyIds.forEach(function(sel){ @@ -1323,10 +1541,14 @@ $('#out_pos').on('change', function(){ syncSatuanMode('#out_pos', '#out_satuan_transaksi'); }); $('#op_in_pos').on('change', function(){ syncSatuanMode('#op_in_pos', '#op_in_satuan_transaksi'); }); $('#op_adj_pos').on('change', function(){ syncSatuanMode('#op_adj_pos', '#op_adj_satuan_transaksi'); }); + $('#racik_bahan_pos').on('change', function(){ syncRacikBahanSelected(); }); + $('#racik_hasil_pos').on('change', function(){ syncRacikHasilSelected(); }); syncSatuanMode('#in_pos', '#in_satuan_transaksi'); syncSatuanMode('#out_pos', '#out_satuan_transaksi'); syncSatuanMode('#op_in_pos', '#op_in_satuan_transaksi'); syncSatuanMode('#op_adj_pos', '#op_adj_satuan_transaksi'); + syncSatuanMode('#racik_bahan_pos', '#racik_bahan_satuan'); + syncSatuanMode('#racik_hasil_pos', '#racik_hasil_satuan'); function syncOpInSelected(){ var val = $('#op_in_pos').val(); @@ -1371,6 +1593,56 @@ }); syncOpAdjSelected(); + function loadExpiredBatches(jenis, targetSelect, selectedId){ + var $target = $(targetSelect); + $target.html(''); + if(!jenis){ + $target.html(''); + return; + } + $.ajax({ + url: "{{ route('simbhp.expiredBatches') }}", + method: 'GET', + data: { jenis: jenis } + }).done(function(resp){ + var rows = (resp && resp.data) ? resp.data : []; + var html = ''; + rows.forEach(function(row){ + var label = (row.tanggal_masuk || '-') + ' | exp: ' + (row.masa_expired || '-') + ' | ' + (row.qty || 0) + ' ' + (row.satuan || '') + ' | ' + (row.deskripsi || '-'); + html += ''; + }); + $target.html(html); + if(selectedId){ + $target.val(selectedId); + } + }).fail(function(){ + $target.html(''); + }); + } + + function syncRacikBahanSelected(){ + syncSatuanMode('#racik_bahan_pos', '#racik_bahan_satuan'); + loadExpiredBatches($('#racik_bahan_pos').val(), '#racik_bahan_batch'); + } + + function syncRacikHasilSelected(){ + syncSatuanMode('#racik_hasil_pos', '#racik_hasil_satuan'); + } + + syncRacikBahanSelected(); + syncRacikHasilSelected(); + + $('#expired_update_pos').on('change', function(){ + loadExpiredBatches($(this).val(), '#expired_update_batch'); + }); + + $('#expired_update_batch').on('change', function(){ + var oldExpired = $(this).find('option:selected').data('expired') || ''; + if(oldExpired && !$('#expired_update_date').val()){ + $('#expired_update_date').val(oldExpired); + } + }); + $('#op_in_kode_barang').on('input', function(){ if($('#op_in_pos').val() !== '__NEW__'){ return; } $(this).val(normalizeKode($(this).val())); @@ -1390,6 +1662,38 @@ $('#op_in_new_satuan_kecil').on('input', syncOpInNewSatuanAvailability); $('#op_in_new_konversi').on('input', syncOpInNewSatuanAvailability); + function syncRacikHasilMode(){ + var isNew = $('#racik_hasil_mode').val() === 'new'; + $('#racik_hasil_existing_fields').toggle(!isNew); + $('#racik_hasil_new_fields').toggle(isNew); + if(isNew){ + var satuanKecil = ($('#racik_hasil_new_satuan_kecil').val() || '').toString().trim(); + var konv = parseInt($('#racik_hasil_new_konversi').val() || 1, 10); + var hasBreakdown = satuanKecil !== '' && konv > 1; + $('#racik_hasil_satuan option[value="kecil"]').prop('disabled', !hasBreakdown); + if(!hasBreakdown && $('#racik_hasil_satuan').val() === 'kecil'){ + $('#racik_hasil_satuan').val('besar'); + } + }else{ + syncRacikHasilSelected(); + } + } + + $('#racik_hasil_mode').on('change', syncRacikHasilMode); + $('#racik_status').on('change', function(){ + var isRusak = $(this).val() === 'rusak'; + $('#racik_hasil_mode, #racik_hasil_pos, #racik_hasil_expired, #racik_hasil_qty, #racik_hasil_satuan').prop('disabled', isRusak); + $('#racik_hasil_new_fields input').prop('disabled', isRusak); + }); + $('#racik_hasil_new_satuan_kecil, #racik_hasil_new_konversi').on('input', syncRacikHasilMode); + $('#racik_hasil_new_kode').on('input', function(){ $(this).val(normalizeKode($(this).val())); }); + $('#racik_hasil_new_jenis').on('input', function(){ + if(($('#racik_hasil_new_kode').val() || '') === ''){ + $('#racik_hasil_new_kode').val(normalizeKode($(this).val())); + } + }); + syncRacikHasilMode(); + $('#op_in_satuan_transaksi').on('change', function(){ if($('#op_in_pos').val() === '__NEW__'){ return; } var selected = $('#op_in_pos option:selected'); @@ -1713,6 +2017,8 @@ $("#out_total").autoNumeric( 'init', {aSep: ',', mDec: '0', vMax: '99999999999999999999999999'} ); $("#op_in_total").autoNumeric( 'init', {aSep: ',', mDec: '0', vMax: '99999999999999999999999999'} ); $("#op_adj_total").autoNumeric( 'init', {aSep: ',', mDec: '0', vMax: '99999999999999999999999999'} ); + $("#racik_bahan_qty").autoNumeric( 'init', {aSep: ',', mDec: '0', vMax: '99999999999999999999999999'} ); + $("#racik_hasil_qty").autoNumeric( 'init', {aSep: ',', mDec: '0', vMax: '99999999999999999999999999'} ); function renderOpInLines(){ if(!opInLines.length){ @@ -1752,6 +2058,29 @@ $('#op_adj_lines').html(html); } + function renderRacikLines(){ + if(!racikLines.length){ + $('#racik_lines').html('Belum ada bahan.'); + return; + } + var html = ''; + racikLines.forEach(function(line, idx){ + var expiredInfo = '-'; + if(line.batch_label || line.expired_baru){ + expiredInfo = (line.batch_label || '-') + (line.expired_baru ? '
baru: ' + escapeHtml(line.expired_baru) + '' : ''); + } + html += '' + + '' + escapeHtml(line.kode || '') + '' + + '' + escapeHtml(line.jenis || '') + '' + + '' + escapeHtml(line.qty || '') + '' + + '' + escapeHtml(line.satuan_transaksi || '') + '' + + '' + expiredInfo + '' + + '' + + ''; + }); + $('#racik_lines').html(html); + } + function getSelectedKode(selectId){ var selected = $(selectId).find('option:selected'); return normalizeKode(selected.data('kodejenis') || ''); @@ -1904,6 +2233,43 @@ if(!isNaN(idx)){ opAdjLines.splice(idx, 1); renderOpAdjLines(); } }); + $('#btn_racik_add_bahan').on('click', function(){ + var jenis = $('#racik_bahan_pos').val(); + var qty = $('#racik_bahan_qty').val(); + var satuanTransaksi = $('#racik_bahan_satuan').val() || 'besar'; + var kode = getSelectedKode('#racik_bahan_pos'); + var batchId = $('#racik_bahan_batch').val(); + var batchLabel = batchId ? $('#racik_bahan_batch option:selected').text() : ''; + var expiredBaru = $('#racik_bahan_expired_baru').val(); + + if(!jenis || !qty){ + $.toast({ heading: 'Gagal', text: 'Bahan dan jumlah wajib diisi', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 3000, stack: 1 }); + return; + } + if(expiredBaru && !batchId){ + $.toast({ heading: 'Gagal', text: 'Pilih batch yang dibuka jika mengisi expired baru', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 3500, stack: 1 }); + return; + } + + racikLines.push({ + jenis: jenis, + kode: kode, + qty: qty, + satuan_transaksi: satuanTransaksi, + batch_id: batchId, + batch_label: batchLabel, + expired_baru: expiredBaru + }); + $('#racik_bahan_qty').val(''); + $('#racik_bahan_expired_baru').val(''); + renderRacikLines(); + }); + + $(document).on('click', '.btn_racik_remove', function(){ + var idx = parseInt($(this).data('index'), 10); + if(!isNaN(idx)){ racikLines.splice(idx, 1); renderRacikLines(); } + }); + function runBatchPost(lines, buildPayload, onDone){ var i = 0; function next(){ @@ -2083,8 +2449,120 @@ nextAdj(); }); + $('#btn_racik_commit').on('click', function(){ + if(!racikLines.length){ + $.toast({ heading: 'Info', text: 'Daftar bahan racikan masih kosong', position: 'top-right', loaderBg: '#3b98b5', icon: 'info', hideAfter: 2500, stack: 1 }); + return; + } + + var statusRacikan = $('#racik_status').val(); + var payload = { + _token: token, + tanggal: $('#racik_tanggal').val(), + nama_racikan: $('#racik_nama').val(), + status_racikan: statusRacikan, + bahan: JSON.stringify(racikLines), + hasil_mode: $('#racik_hasil_mode').val(), + hasil_jenis: $('#racik_hasil_pos').val(), + hasil_qty: $('#racik_hasil_qty').val(), + hasil_satuan_transaksi: $('#racik_hasil_satuan').val(), + hasil_masa_expired: $('#racik_hasil_expired').val(), + hasil_new_kode: $('#racik_hasil_new_kode').val(), + hasil_new_jenis: $('#racik_hasil_new_jenis').val(), + hasil_new_satuan: $('#racik_hasil_new_satuan').val(), + hasil_new_satuan_kecil: $('#racik_hasil_new_satuan_kecil').val(), + hasil_new_konversi: $('#racik_hasil_new_konversi').val(), + hasil_new_stok_minimum: $('#racik_hasil_new_stok_minimum').val() + }; + + if(statusRacikan === 'berhasil'){ + if(payload.hasil_mode === 'existing' && !payload.hasil_jenis){ + $.toast({ heading: 'Gagal', text: 'Barang hasil racikan wajib dipilih', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 3000, stack: 1 }); + return; + } + if(!payload.hasil_qty){ + $.toast({ heading: 'Gagal', text: 'Jumlah hasil racikan wajib diisi', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 3000, stack: 1 }); + return; + } + } + + var $btn = $(this); + $btn.prop('disabled', true).text('Menyimpan...'); + $.ajax({ url: "{{ route('simbhp.racikan') }}", method: 'POST', data: payload }) + .done(function(resp){ + var ok = resp && resp.status && resp.status.toString().toLowerCase() === 'success'; + $.toast({ + heading: ok ? 'Success' : 'Gagal', + text: (resp && resp.message) ? resp.message : (ok ? 'Racikan tersimpan' : 'Gagal menyimpan racikan'), + position: 'top-right', + loaderBg: ok ? '#5ba035' : '#bf441d', + icon: ok ? 'success' : 'error', + hideAfter: 4500, + stack: 1 + }); + if(ok){ + racikLines = []; + renderRacikLines(); + $('#racik_hasil_qty').val(''); + $('#racik_hasil_expired').val(''); + if(typeof window.gudangRefresh === 'function'){ + window.gudangRefresh(); + } + } + }) + .fail(function(){ + $.toast({ heading: 'Gagal', text: 'Request gagal', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 4500, stack: 1 }); + }) + .always(function(){ + $btn.prop('disabled', false).text('Simpan Proses Racikan'); + }); + }); + + $('#btn_expired_update').on('click', function(){ + var batchId = $('#expired_update_batch').val(); + var newDate = $('#expired_update_date').val(); + if(!batchId || !newDate){ + $.toast({ heading: 'Gagal', text: 'Batch dan expired baru wajib diisi', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 3000, stack: 1 }); + return; + } + var $btn = $(this); + $btn.prop('disabled', true).text('Menyimpan...'); + $.ajax({ + url: "{{ route('simbhp.updateExpired') }}", + method: 'POST', + data: { + _token: token, + batch_id: batchId, + masa_expired: newDate, + alasan: $('#expired_update_note').val() + } + }).done(function(resp){ + var ok = resp && resp.status && resp.status.toString().toLowerCase() === 'success'; + $.toast({ + heading: ok ? 'Success' : 'Gagal', + text: (resp && resp.message) ? resp.message : 'Gagal update expired', + position: 'top-right', + loaderBg: ok ? '#5ba035' : '#bf441d', + icon: ok ? 'success' : 'error', + hideAfter: 3500, + stack: 1 + }); + if(ok){ + loadExpiredBatches($('#expired_update_pos').val(), '#expired_update_batch'); + if(typeof window.gudangRefresh === 'function'){ + window.gudangRefresh(); + } + } + }).fail(function(){ + $.toast({ heading: 'Gagal', text: 'Request gagal', position: 'top-right', loaderBg: '#bf441d', icon: 'error', hideAfter: 4500, stack: 1 }); + }).always(function(){ + $btn.prop('disabled', false).text('Update Expired Batch'); + }); + }); + renderOpInLines(); renderOpAdjLines(); + renderRacikLines(); $('#btnexportreport').click(function(){ var gridContent = $("#gridreportblnini").jqxGrid('exportdata', 'json'); data = $.parseJSON(gridContent); diff --git a/htdocs/resources/views/dokter/mikro-expertise.blade.php b/htdocs/resources/views/dokter/mikro-expertise.blade.php index 90777303..3ed3bc81 100644 --- a/htdocs/resources/views/dokter/mikro-expertise.blade.php +++ b/htdocs/resources/views/dokter/mikro-expertise.blade.php @@ -123,23 +123,28 @@ }, 150); } - $('#gridpemeriksaan').off('bindingcomplete.mikro-expertise').on('bindingcomplete.mikro-expertise', function () { - if (!hasRequestedFilteredLoad) { - hasRequestedFilteredLoad = true; - setInitialFilters(); - setTimeout(function () { - if (typeof openedpage === 'function') { - openedpage(); - } else { - $('#divawal').show(); - } - }, 0); + function requestFilteredLoad() { + if (hasRequestedFilteredLoad) { return; } + hasRequestedFilteredLoad = true; + setInitialFilters(); + if (typeof openedpage === 'function') { + openedpage(); + } else { + $('#divawal').show(); + } + } + + $('#gridpemeriksaan').off('bindingcomplete.mikro-expertise').on('bindingcomplete.mikro-expertise', function () { openFocusedPeriksa(); }); + $(window).off('load.mikro-expertise').on('load.mikro-expertise', function () { + requestFilteredLoad(); + }); + $('#btnkembali2').off('click.mikro-expertise').on('click.mikro-expertise', function () { window.location.href = returnUrl; }); diff --git a/htdocs/resources/views/dokter/ppdsdeveloper.blade.php b/htdocs/resources/views/dokter/ppdsdeveloper.blade.php index 32d0573f..b1a672bb 100644 --- a/htdocs/resources/views/dokter/ppdsdeveloper.blade.php +++ b/htdocs/resources/views/dokter/ppdsdeveloper.blade.php @@ -5761,7 +5761,9 @@ $("html, body").animate({ scrollTop: 0 }, "slow"); } $(window).on('load', function () { - openedpage(); + if (!@json((bool) ($openExpertiseOnLoad ?? false))) { + openedpage(); + } }); var start = new Date(); CountDownTimer(start, 'timeremaining'); diff --git a/htdocs/routes/web.php b/htdocs/routes/web.php index 163c0023..c514d87f 100644 --- a/htdocs/routes/web.php +++ b/htdocs/routes/web.php @@ -78,6 +78,9 @@ Route::group(['middleware' => 'project.ipg'], function() { Route::post('biorepository/delete-cabinet/{id}', [BiorepositoryController::class, 'deleteCabinet'])->name('biorepository.deleteCabinet'); Route::post('simbhp/exaddbarang', [GudangController::class, 'exAddbarang'])->name('exAddBarang'); Route::get('simbhp/snapshot', [GudangController::class, 'jsonSnapshot'])->name('simbhp.snapshot'); + Route::get('simbhp/expired-batches', [GudangController::class, 'jsonExpiredBatches'])->name('simbhp.expiredBatches'); + Route::post('simbhp/racikan', [GudangController::class, 'storeRacikan'])->name('simbhp.racikan'); + Route::post('simbhp/update-expired', [GudangController::class, 'updateExpiredBatch'])->name('simbhp.updateExpired'); Route::post('simbhp/reportbhp', [GudangController::class, 'jsonReportbhp'])->name('reportBHP'); Route::get('simbhp/reportbhp/export', [GudangController::class, 'exportReportbhp'])->name('reportBHPExport'); Route::post('simbhp/kwitansi', [GudangController::class, 'exKwitansi'])->name('kwitansiBHP');