Perbarui cetak dan stok barcode

This commit is contained in:
Dwi Swandhana
2026-03-13 12:24:10 +07:00
parent 52ee41e50c
commit 6fb3f5a629
11 changed files with 2239 additions and 191 deletions
File diff suppressed because it is too large Load Diff
@@ -7,8 +7,10 @@
<meta content="{{ config('global.namaapps') }}" name="description" />
<meta content="{{ config('global.domainapps') }}" name="author" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="csrf-token" content="{{ csrf_token() }}">
<link rel="shortcut icon" href="{{ asset('favicon.ico') }}">
@include('base.partials.css-plain')
@livewireStyles
@stack('styles')
<!--
Programmer : Dwi Swandhana
@@ -30,6 +32,7 @@
</div>
</footer>
@include('base.partials.js-plain')
@livewireScripts
@stack('script')
</body>
</html>
@@ -96,12 +96,11 @@
<li><a href="/mikro/buku0">Selainnya</a></li>
</ul>
</li>
<li><a href="/report"><i class="fa fa-hospital-o"></i>Report</a></li>
<li><a href="/biorepository"><i class="fa fa-archive"></i>Biorepository</a></li>
<li><a href="/pengambilan"><i class="fa fa-stethoscope"></i>Pengambilan</a></li>
<li class="has-submenu">
<a href="#"><i class="fa fa-user-md"></i>Logbook</a>
<a href="#"><i class="fa fa-user-md"></i>Report</a>
<ul class="submenu">
<li><a href="/pengambilan">Pengambilan</a></li>
<li><a href="/report">Report</a></li>
<li><a href="/logbookmenu">Logbook Menu</a></li>
<li><a href="/logbookstatistik">Report and Statistik</a></li>
</ul>
@@ -115,6 +114,7 @@
<li><a href="/user">User Management</a></li>
<li><a href="/template">Expertise Template</a></li>
<li><a href="/sirab">Database Antibiotik</a></li>
<li><a href="/biorepository">Biorepository</a></li>
<li><a href="/gudang">Gudang</a></li>
<li><a href="/backup">Backup</a></li>
</ul>
@@ -143,11 +143,11 @@
<li><a href="/mikro/buku0">Selainnya</a></li>
</ul>
</li>
<li><a href="/report"><i class="fa fa-hospital-o"></i>Report</a></li>
<li><a href="/pengambilan"><i class="fa fa-stethoscope"></i>Pengambilan</a></li>
<li class="has-submenu">
<a href="#"><i class="fa fa-user-md"></i>Logbook</a>
<a href="#"><i class="fa fa-user-md"></i>Report</a>
<ul class="submenu">
<li><a href="/pengambilan">Pengambilan</a></li>
<li><a href="/report">Report</a></li>
<li><a href="/logbookmenu">Logbook Menu</a></li>
<li><a href="/logbookstatistik">Report and Statistik</a></li>
</ul>
@@ -187,12 +187,17 @@
</ul>
</li>
<li><a href="/pendaftaran"><i class="fa fa-h-square"></i>Registration</a></li>
<li><a href="/poli"><i class="fa fa-hospital-o"></i>Room and Request List</a></li>
<li><a href="/report"><i class="fa fa-hospital-o"></i>Report</a></li>
<li><a href="/pengambilan"><i class="fa fa-stethoscope"></i>Pengambilan</a></li>
<li class="has-submenu">
<a href="#"><i class="fa fa-user-md"></i>Report</a>
<ul class="submenu">
<li><a href="/pengambilan">Pengambilan</a></li>
<li><a href="/report">Report</a></li>
</ul>
</li>
<li class="has-submenu">
<a href="#"><i class="fa fa-medkit"></i>Settings</a>
<ul class="submenu">
<li><a href="/poli">Room and Request List</a></li>
<li><a href="/pasien">Patient</a></li>
<li><a href="/template">Database</a></li>
<li><a href="/user">User Management</a></li>
@@ -0,0 +1,215 @@
<div>
<div class="row">
<div class="col-lg-7">
<div class="card-box">
<div class="row">
<div class="col-md-7">
<h4 class="m-t-0">List Barang</h4>
<small class="text-muted">Scan barcode di atas list, atau klik item untuk input qty/satuan.</small>
</div>
<div class="col-md-5">
<input type="text" class="form-control" placeholder="Cari kode / nama..." wire:model.live.debounce.300ms="search">
</div>
</div>
<div class="m-t-10">
<input id="gudangpos_scan" type="text" class="form-control"
placeholder="Scan barcode lalu Enter"
wire:model.live="scan"
wire:keydown.enter.prevent="scanLookup">
</div>
<hr class="m-t-10 m-b-10">
<div class="row">
@forelse($products as $p)
@php
$saldoBase = (int) ($stockMap[$p->jenis] ?? 0);
$warning = $saldoBase <= (int) ($p->stok_minimum ?? 0);
@endphp
<div class="col-lg-4 col-md-6">
<div class="card-box" style="border:1px solid #eee; cursor:pointer;" wire:click="selectProduct('{{ $p->kodejenis }}')">
<div class="d-flex justify-content-between">
<div>
<div><b>{{ $p->jenis }}</b></div>
<div><span class="badge badge-success">{{ $p->kodejenis }}</span></div>
</div>
<div class="text-right">
@if($warning)
<span class="badge badge-danger">LOW</span>
@else
<span class="badge badge-info">OK</span>
@endif
</div>
</div>
<div class="m-t-10">
<small class="text-muted">Stok (base): {{ number_format($saldoBase, 0, '.', ',') }}</small>
</div>
<div class="m-t-5">
<small class="text-muted">Satuan: {{ $p->satuan }} @if(($p->satuan_kecil ?? '') !== '') / {{ $p->satuan_kecil }} @endif</small>
</div>
</div>
</div>
@empty
<div class="col-12">
<div class="alert alert-warning m-b-0">Produk tidak ditemukan.</div>
</div>
@endforelse
</div>
<div class="m-t-10">
{{ $products->links('pagination::bootstrap-4') }}
</div>
</div>
</div>
<div class="col-lg-5">
<div class="card-box">
<h4 class="m-t-0">Keranjang</h4>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Tanggal</label>
<input type="date" class="form-control" wire:model.live="tanggal">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Penerima</label>
<select class="form-control" wire:model.live="penerimaId">
@foreach($users as $u)
<option value="{{ $u->id }}">{{ $u->nama }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped m-b-0">
<thead>
<tr>
<th style="width: 110px">Kode</th>
<th>Barang</th>
<th style="width: 90px">Qty</th>
<th style="width: 80px">Sat</th>
<th style="width: 60px">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($cart as $i => $line)
<tr>
<td class="text-center"><code>{{ $line['kode'] }}</code></td>
<td>{{ $line['jenis'] }}</td>
<td class="text-right">{{ number_format((int) ($line['qty'] ?? 0), 0, '.', ',') }}</td>
<td class="text-center">{{ strtoupper($line['satuan_transaksi'] ?? '-') }}</td>
<td class="text-center">
<button type="button" class="btn btn-sm btn-danger" wire:click="removeLine({{ $i }})">X</button>
</td>
</tr>
@empty
<tr><td colspan="5" class="text-center text-muted">Keranjang masih kosong.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div class="m-t-10">
<button type="button" class="btn btn-custom btn-block" wire:click="processCart" @if(count($cart)===0) disabled @endif>Proses Barang Keluar</button>
</div>
<small class="text-muted d-block m-t-10">Tidak ada pembayaran; hanya penerima barang.</small>
</div>
</div>
</div>
<div wire:ignore.self class="modal fade" id="gudangposModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Input Qty & Satuan</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Kode</label>
<input type="text" class="form-control" wire:model.live="selectedKode" readonly>
</div>
@if($selectedJenis)
<div class="alert alert-info">
<div><b>{{ $selectedJenis->jenis }}</b></div>
<div>Stok: <b>{{ $selectedStockDisplay }}</b></div>
</div>
@endif
<div class="form-group">
<label>Satuan</label>
<select class="form-control" wire:model.live="satuanTransaksi">
<option value="besar">Satuan Besar</option>
<option value="kecil" @if(!($selectedSetting['has_breakdown'] ?? false)) disabled @endif>Satuan Kecil (Pecah Satuan)</option>
</select>
</div>
<div class="form-group m-b-0">
<label>Jumlah</label>
<input id="gudangpos_qty" type="number" min="1" class="form-control" wire:model.live="qty" wire:keydown.enter.prevent="addSelected">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<button type="button" class="btn btn-success" wire:click="addSelected">Tambah</button>
</div>
</div>
</div>
</div>
@once
@push('script')
<script>
document.addEventListener('livewire:init', () => {
Livewire.on('gudangpos-toast', (e) => {
const type = (e.type || 'info').toString();
const icon = (type === 'success') ? 'success' : (type === 'error' ? 'error' : 'info');
const loaderBg = (type === 'success') ? '#5ba035' : (type === 'error' ? '#bf441d' : '#3b98b5');
if (window.$ && $.toast) {
$.toast({
heading: type.toUpperCase(),
text: e.message || '',
position: 'top-right',
loaderBg,
icon,
hideAfter: 3500,
stack: 1
});
} else {
alert(e.message || '');
}
});
Livewire.on('gudangpos-focus', (e) => {
const field = (e.field || '').toString();
const id = (field === 'qty') ? 'gudangpos_qty' : 'gudangpos_scan';
setTimeout(() => {
const el = document.getElementById(id);
if (el) el.focus();
}, 50);
});
Livewire.on('gudangpos-open-modal', () => {
if (window.$) {
$('#gudangposModal').modal('show');
}
setTimeout(() => {
const el = document.getElementById('gudangpos_qty');
if (el) el.focus();
}, 200);
});
Livewire.on('gudangpos-close-modal', () => {
if (window.$) {
$('#gudangposModal').modal('hide');
}
});
});
</script>
@endpush
@endonce
</div>