Update besar apk finance

This commit is contained in:
Wian Drs
2026-09-11 16:03:00 +07:00
parent d42483b350
commit 4ef15c22ae
897 changed files with 98056 additions and 15979 deletions
+54 -92
View File
@@ -1,3 +1,4 @@
<?php $inventory_title='Kelola Barcode & Serial';$inventory_subtitle='Lengkapi serial unit pending sebelum diaktifkan.';$this->load->view('inventory_professional/_module_nav',get_defined_vars());?>
<style>
body {
background: #f5f7fb;
@@ -21,13 +22,13 @@ body {
.header-gradient {
background: linear-gradient(135deg, #f59e0b, #d97706);
color: #fff;
padding: 22px 28px;
padding: 14px 28px;
}
.info-box {
background: rgba(255,255,255,.18);
border-radius: 12px;
padding: 12px 16px;
padding: 10px 16px;
}
.progress {
@@ -140,10 +141,10 @@ body {
<div class="header-gradient">
<div class="row align-items-center">
<div class="col-md-8">
<h3 class="mb-1">
<h5 class="mb-1">
<i class="fa fa-barcode"></i>
Input Serial Number
</h3>
</h5>
<div class="small">
Silahkan scan Serial Number perangkat.
Data akan otomatis tersimpan.
@@ -154,9 +155,9 @@ body {
<div class="small">
Progress
</div>
<h5 class="font-weight-bold mb-2" id="progress_text">
<h6 class="font-weight-bold mb-2" id="progress_text">
0 / 0 Barcode
</h5>
</h6>
<div class="progress">
<div class="progress-bar bg-success" style="width:35%"></div>
</div>
@@ -259,13 +260,21 @@ body {
<div class="col-lg-8">
<div class="card table-card">
<div class="card-header bg-white">
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2">
<h5 class="mb-0">
Daftar Barcode
</h5>
<span class="badge badge-warning px-3 py-2">
20 Data
</span>
<div class="d-flex align-items-center gap-2">
<input type="search" id="barcodeSearch" class="form-control form-control-sm" placeholder="Cari barcode / SN" autocomplete="off">
<span class="badge badge-warning px-3 py-2" id="barcodeCount">0 Data</span>
</div>
</div>
</div>
<div class="card-footer bg-white d-flex justify-content-between align-items-center">
<small id="barcodePageInfo" class="text-muted">Memuat data...</small>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-secondary" id="barcodePrev">Sebelumnya</button>
<button type="button" class="btn btn-outline-secondary" id="barcodeNext">Berikutnya</button>
</div>
</div>
<div class="table-responsive">
@@ -277,7 +286,7 @@ body {
<th>Barcode</th>
<th>Serial Number</th>
<th width="120">Status</th>
<th width="80" class="text-center">Action</th>
<th width="150" class="text-center">Action</th>
</tr>
</thead>
<tbody>
@@ -313,9 +322,18 @@ body {
let ITEM_ID = `<?= $item_id; ?>` ;
let isSaving = false;
let barcodeStart = 0;
const barcodeLength = 50;
let barcodeSearchTimer = null;
$(document).ready(function () {
loadData();
$("#barcodeSearch").on("input", function () {
clearTimeout(barcodeSearchTimer);
barcodeSearchTimer = setTimeout(function () { barcodeStart = 0; loadData(); }, 300);
});
$("#barcodePrev").on("click", function () { barcodeStart = Math.max(0, barcodeStart - barcodeLength); loadData(); });
$("#barcodeNext").on("click", function () { barcodeStart += barcodeLength; loadData(); });
$("#serial_number").focus();
$("#serial_number").on("keypress", function (e) {
if (e.which == 13) {
@@ -328,7 +346,11 @@ $(document).ready(function () {
});
function loadData() {
$.getJSON( "<?= base_url(); ?>" + "items/load_data_barcode/" + ITEM_ID)
$.getJSON( "<?= base_url(); ?>" + "items/load_data_barcode/" + ITEM_ID, {
start: barcodeStart,
length: barcodeLength,
search: $("#barcodeSearch").val() || ""
})
.done(function (r) {
render(r);
})
@@ -360,7 +382,7 @@ function saveSerial() {
},
success: function (r) {
isSaving = false;
render(r);
if (r.status) loadData(); else render(r);
},
error: function () {
isSaving = false;
@@ -455,18 +477,20 @@ function render(r) {
// =======================
let html = "";
const escapeHtml = function (value) { return $("<div>").text(value == null ? "" : String(value)).html(); };
$.each(r.list, function (i, v) {
html += "<tr>";
html += "<td>" + (i + 1) + "</td>";
html += "<td><strong>" + v.barcode + "</strong></td>";
html += "<td>" + (v.serial_number ? v.serial_number : "-") + "</td>";
html += "<td>" + (r.start + i + 1) + "</td>";
html += "<td><strong>" + escapeHtml(v.barcode) + "</strong></td>";
html += "<td>" + escapeHtml(v.serial_number ? v.serial_number : "-") + "</td>";
html += "<td>";
if (v.serial_number) {
html += '<span class="badge-success-soft"><i class="fa fa-check mr-1"></i>Selesai</span>';
if (v.status === 'available') {
html += '<span class="badge-success-soft"><i class="fa fa-check mr-1"></i>Aktif</span>';
} else if (v.serial_number) {
html += '<span class="badge-warning-soft">Siap Diposting</span>';
} else {
html += '<span class="badge-warning-soft">Menunggu</span>';
}
@@ -475,14 +499,12 @@ function render(r) {
html += '<td class="text-center">';
if (r.item_status == "draft") {
html += '<button class="btn btn-sm btn-outline-danger btnDelete" data-id="' + v.id + '">Delete</button>';
if (v.status === 'available') {
html += '<button class="btn btn-sm btn-outline-secondary" disabled>Sudah Aktif</button>';
} else if (v.serial_number) {
html += '<button class="btn btn-sm btn-outline-danger btnDelete" data-id="' + v.id + '">Hapus SN</button>';
} else {
html += '<button class="btn btn-sm btn-outline-secondary" disabled>Locked</button>';
html += '<button class="btn btn-sm btn-outline-secondary" disabled>Belum Siap</button>';
}
html += "</td>";
@@ -491,75 +513,15 @@ function render(r) {
});
$("#tableBarcode tbody").html(html);
$("#barcodeCount").text(r.total + " Data");
const shownTo = Math.min(r.start + r.list.length, r.filtered);
$("#barcodePageInfo").text(r.filtered ? ((r.start + 1) + "–" + shownTo + " dari " + r.filtered) : "Tidak ada data");
$("#barcodePrev").prop("disabled", r.start <= 0);
$("#barcodeNext").prop("disabled", r.start + r.length >= r.filtered);
}
// function render(r) {
// if (!r.status) {
// $("#serial_number")
// .val("")
// .prop("disabled", false)
// .focus();
// Swal.fire({
// icon: "error",
// title: "Oops...",
// text: r.message
// });
// return;
// }
// if (r.next == null) {
// $("#barcode_id").val("");
// $(".barcode-code").html("SELESAI");
// $("#serial_number")
// .val("")
// .prop("disabled", true);
// $(".progress-bar")
// .css("width", "100%");
// $("#progress_text").html(r.done + " / " + r.total);
// Swal.fire({
// icon: "success",
// title: "Selesai",
// text: "Semua Serial Number berhasil diinput."
// });
// return;
// }
// // Barcode Aktif
// $("#barcode_id").val(r.next.id);
// $(".barcode-code").text(r.next.barcode);
// // Progress
// $("#progress_text").text(r.done + " / " + r.total);
// $(".progress-bar")
// .css("width", r.percent + "%");
// // Table
// let html = "";
// $.each(r.list, function (i, v) {
// html += "<tr>";
// html += "<td>" + (i + 1) + "</td>";
// html += "<td><strong>" + v.barcode + "</strong></td>";
// html += "<td>" + (v.serial_number ? v.serial_number : "-") + "</td>";
// html += "<td>";
// if (v.serial_number) {
// html += '<span class="badge-success-soft"><i class="fa fa-check mr-1"></i>Selesai</span>';
// } else {
// html += '<span class="badge-warning-soft">Menunggu</span>';
// }
// html += "</td>";
// html += '<td class="text-center">';
// html += '<button class="btn btn-sm btn-outline-danger btnDelete" data-id="' + v.id + '">';
// html += 'Delete';
// html += '</button>';
// html += '</td>';
// html += "</tr>";
// });
// $("#tableBarcode tbody").html(html);
// // Reset Input
// $("#serial_number")
// .val("")
// .prop("disabled", false)
// .focus();
// }
$(document).on("click", ".btnDelete", function () {
let id = $(this).data("id");
Swal.fire({
@@ -576,7 +538,7 @@ $(document).on("click", ".btnDelete", function () {
barcode_id: id
},
function (r) {
render(r);
if (r.status) loadData(); else render(r);
},
"json"
);
+13 -878
View File
@@ -1,881 +1,16 @@
<div class="container mt-4">
<div class="card modern-card shadow-sm border-0 rounded-4">
<div class="card-body p-4">
<div class="d-flex justify-content-between mb-3">
<h5>Data Barang Dalam Perjalanan</h5>
<div class="text-end">
<button class="btn btn-warning btn-add btn-add-item mr-2">Tambah Barang</button>
</div>
</div>
<div class="table-responsive">
<table id="tableItems" class="table modern-table w-100">
<thead>
<tr>
<th>No</th>
<th>Tanggal Beli</th>
<th>Kode Barang</th>
<th>Nama</th>
<th style="max-width: 150px;">Gudang</th>
<th>Stok</th>
<th>Harga Beli</th>
<th>Harga Jual</th>
<th>Create at</th>
<th>Aksi</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
<!-- MODAL -->
<div class="modal fade" id="modalItem">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content">
<div class="modal-header bg-warning text-white">
<h5>Item</h5>
</div>
<div class="modal-body">
<input type="hidden" id="id">
<div class="row">
<div class="col-md-6">
<div id="group_tanggal">
<label>Tanggal Pembelian</label>
<input type="date" id="tanggal_beli" class="form-control">
</div>
</div>
<div class="col-md-6">
<div id="group_kode">
<label class="mt-2">Kode Barang</label>
<select id="kode_barang" class="form-control select-search"></select>
</div>
</div>
</div>
<label>Nama Barang</label>
<input type="text" id="nama_barang" class="form-control">
<div class="row">
<div class="col-md-2">
<div id="group_qty">
<label class="mt-2">Jumlah Barang</label>
<input type="number" id="qty" class="form-control">
</div>
</div>
<div class="col-md-2">
<div id="group_tracking_qty">
<label class="mt-2">Jml / (Roll, Box, Dus)</label>
<input type="number" id="tracking_qty" class="form-control">
</div>
</div>
<div class="col-md-4">
<label class="mt-2">Harga Beli</label>
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="text" id="harga_beli" class="form-control format-rupiah">
</div>
</div>
<div class="col-md-4">
<label class="mt-2">Harga Jual</label>
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="text" id="harga_jual" class="form-control format-rupiah">
</div>
</div>
</div>
<div id="group_warehouse">
<label class="mt-2">Gudang</label>
<select id="warehouse_id" class="form-control"></select>
</div>
<!-- <div class="row">
<label class="mt-2">Akun Kas</label>
<div class="col-md-7">
<div id="group_account">
<select id="account_kas" class="form-control"></select>
</div>
</div>
<div class="col-md-5">
<div class="input-group">
<span class="input-group-text">Rp</span>
<input type="text" id="account[]" class="form-control format-rupiah">
</div>
</div>
</div>
<button class="btn btn-warning btn-sm mt-4">Tambah Account</button> -->
<hr>
<label class="font-weight-bold">
Pembayaran
</label>
<div id="accountContainer">
<div class="row account-row mb-2">
<div class="col-md-6">
<select
name="account_kas[]"
class="form-control account_kas">
</select>
</div>
<div class="col-md-4">
<div class="input-group">
<span class="input-group-text">Rp</span>
<input
type="text"
name="nominal[]"
class="form-control nominal format-rupiah">
</div>
</div>
<div class="col-md-2">
<button
type="button"
class="btn btn-sm btn-danger btn-remove-account w-100"
disabled>
Hapus
</button>
</div>
</div>
</div>
<div class="mt-2">
<button
type="button"
id="btnTambahAccount"
class="btn btn-warning btn-sm">
+ Tambah Account
</button>
</div>
<div class="mt-3">
<div class="row">
<div class="col-md-4">
<!-- total qty * harga beli -->
<h5>
Total :
<span id="totalHppBarang">
Rp 0
</span>
</h5>
</div>
<div class="col-md-4">
<!-- total accounting -->
<h5>
Total :
<span id="totalAccount">
Rp 0
</span>
</h5>
</div>
<div class="col-md-4">
<!-- balance accounting + total hpp barang -->
<h5>
Total :
<span id="totalAll">
Rp 0
</span>
</h5>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-warning" id="btnSimpan">Simpan</button>
</div>
</div>
</div>
</div>
<!-- MODAL DETAIL -->
<div class="modal fade" id="modalDetail">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-warning text-white">
<h5>Detail Item</h5>
</div>
<div class="modal-body" id="detailContent"></div>
</div>
</div>
</div>
<?php $inventory_title='Barang Pending';$inventory_subtitle='Penerimaan yang masih membutuhkan harga jual, serial number, atau aktivasi.';$this->load->view('inventory_professional/_module_nav',get_defined_vars());?>
<div class="alert alert-info border-0"><i class="bi bi-info-circle me-2"></i>Daftar ini hanya berisi barang yang sudah diterima gudang tetapi belum sepenuhnya siap. Master barang dibuat dari proses Purchase Request.</div>
<section class="inventory-card"><div class="inventory-card-head"><div><h5>Pekerjaan Aktivasi Barang</h5><p>Isi harga jual di tabel, lengkapi serial bila diwajibkan, lalu posting unit yang sudah siap.</p></div><a href="<?=base_url('purchases?step=request')?>" class="btn btn-outline-primary"><i class="bi bi-cart"></i> Purchase Workflow</a></div><div class="table-responsive"><table id="tableItems" class="table inventory-table align-middle w-100 mb-0"><thead><tr><th>No</th><th>Tanggal Terima</th><th>Kode</th><th>Barang</th><th>Gudang</th><th>Barcode / Stok</th><th>Harga Beli</th><th>Harga Jual</th><th>Dibuat</th><th>Aksi</th></tr></thead></table></div></section>
<div class="modal fade inventory-modal" id="pendingDetailModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered modal-xl"><div class="modal-content"><div class="modal-header"><div><small class="text-muted">BARANG PENDING</small><h5 class="modal-title">Detail Penerimaan Barang</h5></div><button class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body" id="pendingDetailBody"></div><div class="modal-footer"><button class="btn btn-light" data-bs-dismiss="modal">Tutup</button></div></div></div></div>
<div class="modal fade inventory-modal" id="barcodePrintModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered modal-xl"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Preview Barcode</h5><button class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body p-0" style="height:min(82vh,900px)"><iframe title="Preview Barcode" style="width:100%;height:100%;border:0"></iframe></div></div></div></div>
<script>
$(function(){
let action = 'add';
let selectedItemId = null;
let accountOption = '';
// ================= DATATABLE =================
let table = $('#tableItems').DataTable({
ajax: {
url: "<?= base_url('items/get_data'); ?>",
data: function (d) {
d.s = `draft`;
}
}
const csrf=()=>({[APP_CSRF.name]:APP_CSRF.value}),esc=v=>$('<div>').text(v==null?'-':v).html(),money=v=>'Rp '+Number(v||0).toLocaleString('id-ID',{minimumFractionDigits:2,maximumFractionDigits:2});
const table=$('#tableItems').DataTable({responsive:true,processing:true,serverSide:true,searchDelay:350,ajax:{url:'<?=base_url('items/get_data')?>',data:d=>{d.s='draft';d.server=1}},pageLength:25,language:{search:'Cari:',processing:'Memuat data...',lengthMenu:'Tampilkan _MENU_',info:'_START_–_END_ dari _TOTAL_',paginate:{previous:'Sebelumnya',next:'Berikutnya'}},initComplete:function(){let f=new URLSearchParams(location.search).get('focus');if(f)setTimeout(()=>$('.btn-detail[data-id="'+f+'"]').first().click(),300)}});
$(document).on('blur','.pending-sale-price',function(){let n=String(this.value).replace(/\./g,'').replace(',','.');if(Number(n)>0)this.value=Number(n).toLocaleString('id-ID',{minimumFractionDigits:2,maximumFractionDigits:2})});
$(document).on('click','.btn-updatePosting',function(){let id=$(this).data('id'),input=$('.pending-sale-price[data-id="'+id+'"]'),sale=Number(String(input.val()).replace(/\./g,'').replace(',','.')),buy=Number(input.data('buy')||0);if(!sale)return AppAlert.toast('Harga jual satuan wajib diisi.','warning');if(sale<buy)return AppAlert.toast('Harga jual tidak boleh lebih rendah dari harga beli.','error');let b=$(this);AppAlert.confirm({title:'Posting barang siap digunakan?',text:'Hanya barcode yang serialnya sudah lengkap yang akan diaktifkan.',confirmButtonText:'Posting Barang'}).then(r=>{if(!r.isConfirmed)return;b.prop('disabled',true);$.post('<?=base_url('items/posting')?>',Object.assign({id:id,harga_jual:sale},csrf())).done(x=>{if(!x.status)return AppAlert.toast(x.message,'error');table.ajax.reload(null,false);AppAlert.toast(x.message,'success')}).fail(()=>AppAlert.toast('Posting barang gagal.','error')).always(()=>b.prop('disabled',false))})});
$(document).on('click','.btn-detail',function(){let id=$(this).data('id');$('#pendingDetailBody').html('<div class="inventory-loading"><span class="spinner-border spinner-border-sm"></span> Memuat detail…</div>');bootstrap.Modal.getOrCreateInstance('#pendingDetailModal').show();$.get('<?=base_url('items/detail')?>/'+id).done(r=>{let rows=(r.logs||[]).map(x=>'<tr><td>'+esc(x.created_at)+'</td><td>'+esc(x.gudang)+'</td><td>'+esc(x.tipe)+'</td><td class="text-end">'+Number(x.qty||0).toLocaleString('id-ID',{maximumFractionDigits:4})+'</td><td>'+esc(x.keterangan)+'</td></tr>').join('');$('#pendingDetailBody').html('<div class="document-meta"><span>Kode<strong>'+esc(r.item.kode_detail)+'</strong></span><span>Barang<strong>'+esc(r.item.nama_barang)+'</strong></span><span>Harga Beli<strong>'+money(r.item.harga_beli)+'</strong></span><span>Harga Jual<strong>'+money(r.item.harga_jual)+'</strong></span><span>Stok Diterima<strong>'+Number(r.item.stok||0).toLocaleString('id-ID',{maximumFractionDigits:4})+'</strong></span><span>Status<strong><span class="status-chip status-submitted">PENDING</span></strong></span></div><div class="table-responsive mt-3"><table class="table inventory-table"><thead><tr><th>Tanggal</th><th>Gudang</th><th>Arah</th><th class="text-end">Qty</th><th>Keterangan</th></tr></thead><tbody>'+rows+'</tbody></table></div><button type="button" class="btn btn-sm btn-outline-danger stock-pdf" data-id="'+id+'"><i class="bi bi-file-earmark-pdf"></i> PDF Audit</button>')})});
$(document).on('click','.stock-pdf',function(){$('#barcodePrintModal .modal-title').text('PDF Kartu Stok');$('#barcodePrintModal iframe').attr('src','<?=base_url('items/stock_log_pdf')?>/'+$(this).data('id'));bootstrap.Modal.getOrCreateInstance(document.getElementById('barcodePrintModal')).show()});
$(document).on('click','.btn-print',function(){let id=$(this).data('id');AppAlert.prompt({title:'Preview Barcode',html:'<label class="form-label d-block text-start">Jumlah kolom</label><select id="printColumn" class="form-select mb-3"><option value="2">2</option><option value="3" selected>3</option><option value="4">4</option></select><label class="form-label d-block text-start">Salinan</label><input id="printCopies" type="number" min="1" max="20" value="1" class="form-control">',preConfirm:()=>({column:$('#printColumn').val(),duplicat:$('#printCopies').val()}),confirmButtonText:'Preview'}).then(r=>{if(!r.isConfirmed)return;$('#barcodePrintModal .modal-title').text('Preview Barcode');$('#barcodePrintModal iframe').attr('src','<?=base_url('items/print_barcode')?>/'+id+'?column='+r.value.column+'&duplicat='+r.value.duplicat+'&status=all');bootstrap.Modal.getOrCreateInstance(document.getElementById('barcodePrintModal')).show()})});
});
// ================= LOAD AKUN KAS =================
// function loadKas(){
// $.get("<?= base_url('items/get_accounts'); ?>",res=>{
// let opt='<option value="">-- PILIH KAS --</option>';
// res.forEach(a=>{
// opt += `<option value="${a.id}">${a.nama_akun}</option>`;
// });
// $('#account_kas').html(opt);
// },'json');
// }
function loadKas(){
$.get("<?= base_url('items/get_accounts'); ?>",function(res){
accountOption = '<option value="">-- PILIH KAS --</option>';
res.forEach(function(a){
accountOption += `
<option value="${a.id}">
${a.nama_akun}
</option>
`;
});
$('.account_kas').html(accountOption);
},'json');
}
// ================= LOAD GUDANG =================
function loadGudang(){
$.get("<?= base_url('warehouses/list'); ?>",res=>{
let opt='<option value="">-- PILIH GUDANG --</option>';
res.forEach(w=>{
opt += `<option value="${w.id}">${w.nama}</option>`;
});
$('#warehouse_id, #adjust_warehouse').html(opt);
},'json');
}
function loadKode() {
$.get("<?= base_url('kodebarang/list'); ?>", function(res) {
let opt = '<option value="">-- PILIH KODE --</option>';
res.forEach(function(a){
opt += `
<option value="${a.id}"
data-type="${a.tracking_type}">
${a.kode_barang} - ${a.nama}
</option>
`;
});
$('#kode_barang').html(opt).trigger('change');
}, 'json');
}
function addAccountRow(){
let html = `
<div class="row account-row mb-2">
<div class="col-md-6">
<select
name="account_kas[]"
class="form-control account_kas">
${accountOption}
</select>
</div>
<div class="col-md-4">
<div class="input-group">
<span class="input-group-text">
Rp
</span>
<input
type="text"
name="nominal[]"
class="form-control nominal format-rupiah">
</div>
</div>
<div class="col-md-2">
<button
type="button"
class="btn btn-sm btn-danger btn-remove-account w-100">
Hapus
</button>
</div>
</div>
`;
$('#accountContainer').append(html);
hitungTotal();
}
$(document).on('change', '#kode_barang', function () {
let type = $(this).find(':selected').data('type');
if(type == 'QTY'){
$('#group_tracking_qty').show();
}else{
$('#group_tracking_qty').hide();
$('#tracking_qty').val('');
}
});
$('#btnTambahAccount').click(function(){
addAccountRow();
});
$(document).on('click','.btn-remove-account',function(){
$(this).closest('.account-row').remove();
hitungTotal();
});
// function hitungTotal(){
// let total = 0;
// $('.nominal').each(function(){
// let angka = $(this)
// .val()
// .replace(/\./g,'')
// .replace(/,/g,'');
// total += Number(angka || 0);
// });
// $('#totalAccount').text(formatRupiah(total.toString()));
// }
$(document).on('keyup','.nominal',function(){
hitungTotal();
});
$(document).on('keyup','#harga_beli',function(){
hitungTotal();
});
$(document).on('keyup change','#qty',function(){
hitungTotal();
});
// ================= RESET FORM =================
function resetForm(){
$('#id').val('');
$('#nama_barang').val('');
$('#qty').val('');
$('#harga_beli').val('');
$('#harga_jual').val('');
$('#tanggal_beli').val('');
$('#tracking_qty').val('');
$('#group_tracking_qty').hide();
$('#accountContainer').html(`
<div class="row account-row mb-2">
<div class="col-md-6">
<select
name="account_kas[]"
class="form-control account_kas">
${accountOption}
</select>
</div>
<div class="col-md-4">
<div class="input-group">
<span class="input-group-text">Rp</span>
<input
type="text"
name="nominal[]"
class="form-control nominal format-rupiah">
</div>
</div>
<div class="col-md-2">
<button
class="btn btn-sm btn-danger btn-remove-account w-100"
disabled>
Hapus
</button>
</div>
</div>
`);
$('#totalAccount').text('Rp 0');
$('#totalHppBarang').text('Rp 0');
$('#totalAll')
.text('Balance')
.removeClass('text-danger')
.addClass('text-success');
$('#btnSimpan').prop('disabled',true);
}
// ================= INIT LOAD =================
loadGudang();
loadKas();
loadKode();
// ================= ADD =================
$('.btn-add-item').click(function(){
action='add';
resetForm();
$('#qty').closest('div').show();
$('#kode_barang').closest('div').show();
$('#warehouse_id').closest('div').show();
$('#account_kas').closest('div').show();
$('#modalItem').modal('show');
loadGudang();
loadKas();
loadKode();
});
// ================= EDIT =================
$(document).on('click','.btn-editItem',function(){
let id = $(this).data('id');
action='edit';
$.get("<?= base_url('items/detail_simple/'); ?>"+id,function(res){
$('#id').val(res.id);
$('#nama_barang').val(res.nama_barang);
$('#harga_beli').val(res.harga_beli);
$('#harga_jual').val(res.harga_jual);
// 🔥 FIX DI SINI
$('#group_qty').hide();
$('#group_account').hide();
$('#group_kode').hide();
$('#group_warehouse').hide();
$('#group_tanggal').hide();
$('#modalItem').modal('show');
},'json');
});
// ================= SAVE =================
$('#btnSimpan').click(function(){
let btn = $(this);
let qtys = parseFloat($('#qty').val()) || 0;
let totalHpp = qtys * rupiahToNumber($('#harga_beli').val());
let totalAccount = 0;
$('.nominal').each(function(){
totalAccount += rupiahToNumber($(this).val());
});
if(totalHpp != totalAccount){
Swal.fire({
icon:'warning',
title:'Belum Balance',
text:'Total pembayaran harus sama dengan Total Harga Beli.'
});
return;
}
let account = [];
$('.account-row').each(function(){
account.push({
account_id: $(this).find('.account_kas').val(),
nominal: $(this)
.find('.nominal')
.val()
});
});
// data.accounts = account;
let data = {
id: $('#id').val(),
kode_id: $('#kode_barang').val(),
nama_barang: $('#nama_barang').val(),
qty: $('#qty').val(),
harga_beli: $('#harga_beli').val(),
harga_jual: $('#harga_jual').val(),
warehouse_id: $('#warehouse_id').val(),
// account_kas: $('#account_kas').val(),
account_kas: account,
tanggal_beli: $('#tanggal_beli').val(),
tracking_qty: $('#tracking_qty').val(),
status: `draft`
};
let url = action==='add'
? "<?= base_url('items/save'); ?>"
: "<?= base_url('items/update'); ?>";
// 🔥 loading state
btn.prop('disabled', true).html('Menyimpan...');
$.post(url, data, function(res){
if(res.status){
$('#modalItem').modal('hide');
table.ajax.reload(null,false);
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: res.message || 'Data berhasil disimpan',
timer: 1500,
showConfirmButton: false
});
}else{
Swal.fire({
icon: 'error',
title: 'Gagal',
text: res.message || 'Terjadi kesalahan'
});
}
},'json')
.fail(function(){
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Koneksi ke server gagal'
});
})
.always(function(){
btn.prop('disabled', false).html('Simpan');
});
});
// ================= PRINT BARCODE =================
$(document).on('click', '.btn-print', function () {
let id = $(this).data('id');
Swal.fire({
title: 'Cetak Barcode',
html: `
<div class="text-left">
<div class="form-group">
<label for="print_column" class="font-weight-bold">
Jumlah Kolom
</label>
<select id="print_column" class="form-control">
<option value="1">1 Kolom</option>
<option value="2">2 Kolom</option>
<option value="3" selected>3 Kolom (Rekomendasi)</option>
</select>
</div>
<div class="form-group mb-0">
<label for="duplicat" class="font-weight-bold">
Jumlah Cetak per Barcode
</label>
<select id="duplicat" class="form-control">
<option value="1" selected>1 Label</option>
<option value="2">2 Label</option>
</select>
</div>
</div>
`,
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Cetak',
cancelButtonText: 'Batal',
confirmButtonColor: '#f0ad4e',
preConfirm: () => {
let column = $('#print_column').val();
let duplicat = $('#duplicat').val();
return {
column: column,
duplicat: duplicat
};
}
}).then((result) => {
if (!result.isConfirmed) {
return;
}
window.open(
"<?= base_url('items/print_barcode/'); ?>" +
id +
"?column=" + result.value.column +
"&duplicat=" + result.value.duplicat,
"_blank"
);
});
});
// ================= DELETE =================
$(document).on('click','.btn-delete',function(){
let id = $(this).data('id');
let btn = $(this);
Swal.fire({
title: 'Hapus data?',
text: "Data tidak bisa dikembalikan!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'Ya, hapus!',
cancelButtonText: 'Batal'
}).then((result) => {
if(result.isConfirmed){
btn.prop('disabled', true).html('Menghapus...');
$.get("<?= base_url('items/delete/'); ?>"+id,function(res){
if(res.status){
table.ajax.reload(null,false);
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: res.message || 'Data berhasil dihapus',
timer: 1500,
showConfirmButton: false
});
}else{
Swal.fire({
icon: 'error',
title: 'Gagal',
text: res.message || 'Gagal menghapus data'
});
}
},'json')
.fail(function(){
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Koneksi ke server gagal'
});
})
.always(function(){
btn.prop('disabled', false).html('Hapus');
});
}
});
});
// ================= POSTING =================
$(document).on('click','.btn-updatePosting',function(){
let id = $(this).data('id');
let btn = $(this);
if(btn.data('loading')) return;
Swal.fire({
title: 'Konfirmasi Penerimaan Barang',
text: 'Pastikan barang sudah diterima dan sesuai pesanan. Stok akan otomatis ditambahkan ke gudang.',
icon: 'info',
showCancelButton: true,
confirmButtonColor: '#28a745',
cancelButtonColor: '#6c757d',
confirmButtonText: 'Ya, Terima Barang',
cancelButtonText: 'Batal'
}).then((result) => {
if(result.isConfirmed){
btn.data('loading', true)
.prop('disabled', true)
.html('Memposting...');
$.post("<?= base_url('items/posting'); ?>", {
id: id
// tambahkan CSRF kalau perlu
}, function(res){
if(res && res.status){
table.ajax.reload(null,false);
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: res.message || 'Data berhasil diposting',
timer: 1500,
showConfirmButton: false
});
}else{
Swal.fire({
icon: 'error',
title: 'Gagal',
text: res?.message || 'Gagal memposting data'
});
}
},'json')
.fail(function(xhr){
Swal.fire({
icon: 'error',
title: 'Error',
text: xhr.responseJSON?.message || 'Server error ('+xhr.status+')'
});
})
.always(function(){
btn.prop('disabled', false)
.html('Posting')
.data('loading', false);
});
}
});
});
// ================= DETAIL =================
$(document).on('click','.btn-detail',function(){
let id = $(this).data('id');
$.get("<?= base_url('items/detail/'); ?>"+id,function(res){
let html = `
<b>Nama :</b> ${res.item.nama_barang}<br>
<b>Harga Beli :</b> ${formatRupiah(res.item.harga_beli)}<br>
<b>Harga Jual :</b> ${formatRupiah(res.item.harga_jual)}
<hr>
<h6>Riwayat Stok</h6>
<table class="table table-sm table-bordered">
<tr>
<th>Tanggal</th>
<th>Gudang</th>
<th>Qty</th>
<th>Tipe</th>
<th>Keterangan</th>
</tr>
`;
res.logs.forEach(l=>{
html += `
<tr>
<td>${l.created_at ?? '-'}</td>
<td>${l.gudang ?? '-'}</td>
<td>${l.qty}</td>
<td>${l.tipe}</td>
<td>${l.keterangan ?? ''}</td>
</tr>`;
});
html += `</table>`;
$('#detailContent').html(html);
$('#modalDetail').modal('show');
},'json');
});
function rupiahToNumber(value){
if(!value) return 0;
let s = value.toString().trim();
s = s.replace(/\.(?=\d{3}(\.|$))/g, '');
s = s.replace(/,/g, '');
return parseFloat(s) || 0;
}
function hitungTotal(){
// ==========================
// HPP BARANG
// ==========================
let qty = parseFloat($('#qty').val()) || 0;
let hargaBeli = rupiahToNumber($('#harga_beli').val());
let totalHpp = qty * hargaBeli;
// ==========================
// ACCOUNTING
// ==========================
let totalAccount = 0;
$('.nominal').each(function(){
totalAccount += rupiahToNumber($(this).val());
});
// ==========================
// BALANCE
// ==========================
let balance = totalAccount - totalHpp;
$('#totalHppBarang').text(formatRupiah(totalHpp.toString()));
$('#totalAccount').text(formatRupiah(totalAccount.toString()));
if(balance == 0){
$('#totalAll')
.removeClass('text-danger')
.addClass('text-success')
.text('Balance');
$('#btnSimpan').prop('disabled',false);
}else{
let prefix = balance > 0 ? '+' : '-';
$('#totalAll')
.removeClass('text-success')
.addClass('text-danger')
.text(prefix + ' ' + formatRupiah(Math.abs(balance).toString()));
$('#btnSimpan').prop('disabled',true);
}
}
});
</script>
</script>
+12 -402
View File
@@ -1,406 +1,16 @@
<style>
body {
background: #f5f7fb;
}
/* ===========================
CARD
=========================== */
.main-card,
.scanner-card,
.table-card {
border: none;
border-radius: 18px;
overflow: hidden;
/*box-shadow: 0 8px 25px rgba(0, 0, 0, .08);*/
}
/* ===========================
HEADER
=========================== */
.header-gradient {
background: linear-gradient(135deg, #f59e0b, #d97706);
color: #fff;
padding: 22px 28px;
}
.info-box {
background: rgba(255,255,255,.18);
border-radius: 12px;
padding: 12px 16px;
}
.progress {
height: 8px;
border-radius: 20px;
}
/* ===========================
SCANNER
=========================== */
.barcode-avatar {
width: 110px;
height: 110px;
margin: auto;
border-radius: 50%;
background: #fff7e6;
color: #f59e0b;
display: flex;
justify-content: center;
align-items: center;
font-size: 45px;
}
.barcode-code {
font-size: 22px;
font-weight: 700;
letter-spacing: 2px;
}
.form-control-lg {
height: 60px;
font-size: 22px;
border-radius: 12px;
}
.form-control:focus {
border-color: #f59e0b;
box-shadow: 0 0 0 .2rem rgba(245, 158, 11, .2);
}
.scan-note {
color: #6c757d;
font-size: 13px;
}
.camera-btn {
height: 55px;
border-radius: 12px;
font-size: 17px;
}
/* ===========================
TABLE
=========================== */
.table thead th {
background: #d97706;
color: #fff;
border: none;
vertical-align: middle;
}
.table tbody td {
vertical-align: middle;
}
.table tbody tr:hover {
background: #fffaf0;
}
/* ===========================
BADGE
=========================== */
.badge-success-soft {
display: inline-block;
padding: 6px 14px;
border-radius: 30px;
background: #d1fae5;
color: #065f46;
font-weight: 600;
}
.badge-danger-soft {
display: inline-block;
padding: 6px 14px;
border-radius: 30px;
background: #fee2e2;
color: #991b1b;
font-weight: 600;
}
.badge-warning-soft {
display: inline-block;
padding: 6px 14px;
border-radius: 30px;
background: #fef3c7;
color: #92400e;
font-weight: 600;
}
#reader{
width:100%;
min-height:280px;
border-radius:12px;
overflow:hidden;
}
</style>
<div class="container mt-4">
<div class="card main-card">
<!-- HEADER -->
<div class="header-gradient">
<div class="row align-items-center">
<div class="col-md-8">
<h3 class="mb-1">
<i class="fa fa-barcode"></i>
Riwayat Perpindahan Barang
</h3>
<div class="small">
Silahkan scan / input QR id Barang
</div>
</div>
<div class="col-md-4 text-right">
</div>
</div>
</div>
<!-- BODY -->
<div class="card-body">
<div class="row">
<!-- LEFT -->
<div class="col-lg-4 mb-4">
<div class="card scanner-card">
<div class="card-body">
<div class="barcode-avatar">
<i class="bi bi-qr-code-scan"></i>
</div>
<div class="text-center mt-3">
<div class="scan-note mt-2">
Scan QR ID
</div>
</div>
<hr>
<center>
<div id="scannerArea">
<input
type="text"
id="serial_number"
class="form-control form-control-lg text-center"
placeholder="Scan / Input QR ID"
autocomplete="off"
autofocus>
<small class="scan-note">
Scanner akan otomatis memanggil riwayat.
</small>
<button
type="button"
class="btn btn-warning btn-block camera-btn mt-4"
id="btnCamera">
<i class="fa fa-camera mr-2"></i>
Scan dengan Kamera
</button>
</div>
<div id="cameraArea" style="display:none;">
<div id="reader"></div>
<small class="scan-note d-block mt-2">
Arahkan QR Code ke kamera.
</small>
<button
type="button"
class="btn btn-secondary btn-block mt-3"
id="btnCloseCamera">
Tutup Kamera
</button>
</div>
</center>
<input type="hidden" id="barcode_id">
</div>
</div>
</div>
<!-- RIGHT -->
<div class="col-lg-8">
<div class="card table-card">
<div class="card-header bg-white">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0">
Riwayat Perpindahan Barang
</h5>
</div>
</div>
<div class="card-body border-bottom" id="itemInfo">
Belum ada data
</div>
<div class="table-responsive">
<table class="table table-hover mb-0" id="tableBarcode">
<thead>
<tr>
<th width="60">No</th>
<th>Date</th>
<th>Type</th>
<th>From</th>
<th>To</th>
<th>NOtes</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<?php $inventory_title='Riwayat Barcode & Serial';$inventory_subtitle='Scan atau cari barcode untuk melihat identitas, posisi, saldo, reservasi, dan seluruh perpindahannya.';$this->load->view('inventory_professional/_module_nav',get_defined_vars());?>
<div class="row g-3">
<div class="col-lg-4"><section class="inventory-card h-100"><div class="inventory-card-head"><div><h5>Pencarian Unit</h5><p>Gunakan barcode, QR, atau serial number.</p></div></div><div class="p-3"><label class="form-label">Barcode / Serial Number</label><div class="input-group"><input id="scanCode" class="form-control form-control-lg" autocomplete="off" placeholder="Scan atau ketik kode"><button class="btn btn-primary" id="findBarcode"><i class="bi bi-search"></i></button></div><button class="btn btn-outline-primary w-100 mt-3" id="openCamera"><i class="bi bi-camera"></i> Buka Kamera Scanner</button><small class="text-muted d-block mt-3">Scanner hanya membaca data. Mutasi barang tetap dilakukan melalui dokumen sumber yang sesuai.</small></div></section></div>
<div class="col-lg-8"><section class="inventory-card h-100"><div class="inventory-card-head"><div><h5>Identitas dan Posisi Barang</h5><p id="scanHint">Belum ada barcode yang dipilih.</p></div></div><div class="p-3" id="scanResult"><div class="inventory-empty"><i class="bi bi-upc-scan"></i><strong>Siap memindai</strong><small>Hasil akan tampil di sini tanpa membuka halaman baru.</small></div></div></section></div>
</div>
<section class="inventory-card mt-3"><div class="inventory-card-head"><div><h5>Riwayat Perpindahan</h5><p>Urutan terbaru dari barcode atau serial yang dipilih.</p></div></div><div class="table-responsive"><table class="table inventory-table align-middle mb-0"><thead><tr><th>Waktu</th><th>Jenis</th><th>Dari</th><th>Ke</th><th class="text-end">Qty</th><th>Dokumen Sumber</th><th>Keterangan</th></tr></thead><tbody id="movementRows"><tr><td colspan="7" class="text-center text-muted py-5">Scan barcode untuk melihat riwayat.</td></tr></tbody></table></div></section>
<div class="modal fade inventory-modal" id="cameraModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered modal-lg"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Scanner Barcode / QR</h5><button class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body"><div id="cameraReader"></div></div></div></div></div>
<script>
$("#serial_number").keypress(function(e){
if(e.which==13){
searchHistory();
}
$(function(){
const esc=v=>$('<div>').text(v==null||v===''?'-':v).html(),qty=v=>Number(v||0).toLocaleString('id-ID',{maximumFractionDigits:4});let scanner=null;
function location(type,id){if(!type)return'-';return esc(String(type).replaceAll('_',' '))+(id?' #'+esc(id):'')}
function find(){let code=$('#scanCode').val().trim();if(!code)return AppAlert.toast('Barcode atau serial wajib diisi.','warning');let b=$('#findBarcode').prop('disabled',true);$('#scanResult').html('<div class="inventory-loading"><span class="spinner-border spinner-border-sm"></span> Memuat identitas barang...</div>');$.get('<?=base_url('inventoryprofessional/scan')?>',{code:code}).done(function(r){let x=r.item,available=Math.max(0,Number(x.qty_sisa)-Number(x.reserved_qty)-Number(x.return_reserved_qty));$('#scanHint').text(x.kode_detail+' - '+x.nama_barang);$('#scanResult').html('<div class="scan-product"><span class="status-chip status-'+esc(x.status)+'">'+esc(String(x.status).replaceAll('_',' '))+'</span><h5>'+esc(x.kode_detail+' - '+x.nama_barang)+'</h5><div class="scan-grid"><span>Barcode<strong>'+esc(x.barcode)+'</strong></span><span>Serial Number<strong>'+esc(x.serial_number)+'</strong></span><span>Gudang<strong>'+esc(x.warehouse_name)+'</strong></span><span>Rak / Bin<strong>'+esc(x.bin_code)+'</strong></span><span>Batch<strong>'+esc(x.batch_no)+'</strong></span><span>Satuan<strong>'+esc(x.unit)+'</strong></span><span>Qty Fisik<strong>'+qty(x.qty_sisa)+'</strong></span><span>Reservasi / Retur<strong>'+qty(Number(x.reserved_qty)+Number(x.return_reserved_qty))+'</strong></span><span>Qty Tersedia<strong>'+qty(available)+'</strong></span></div></div>');$('#movementRows').html((x.history||[]).map(m=>'<tr><td>'+esc(m.created_at)+'</td><td><span class="status-chip">'+esc(String(m.movement_type||'-').replaceAll('_',' '))+'</span></td><td>'+location(m.from_type,m.from_id)+'</td><td>'+location(m.to_type,m.to_id)+'</td><td class="text-end">'+qty(m.qty)+'</td><td>'+esc(m.reference_type)+(m.reference_id?' #'+esc(m.reference_id):'')+'</td><td>'+esc(m.notes)+'</td></tr>').join('')||'<tr><td colspan="7" class="text-center text-muted py-4">Belum ada riwayat perpindahan.</td></tr>')}).fail(x=>{let m=x.responseJSON&&x.responseJSON.message||'Barcode tidak ditemukan.';$('#scanResult').html('<div class="inventory-empty"><i class="bi bi-exclamation-circle"></i><strong>'+esc(m)+'</strong></div>');$('#movementRows').html('<tr><td colspan="7" class="text-center text-muted py-4">Tidak ada data.</td></tr>');AppAlert.toast(m,'error')}).always(()=>b.prop('disabled',false))}
$('#findBarcode').on('click',find);$('#scanCode').on('keydown',e=>{if(e.key==='Enter'){e.preventDefault();find()}});
$('#openCamera').on('click',function(){let modal=bootstrap.Modal.getOrCreateInstance(document.getElementById('cameraModal'));modal.show();setTimeout(()=>{if(typeof Html5QrcodeScanner==='undefined')return AppAlert.toast('Library scanner belum tersedia. Gunakan input manual.','warning');scanner=new Html5QrcodeScanner('cameraReader',{fps:10,qrbox:{width:240,height:160}},false);scanner.render(code=>{$('#scanCode').val(code);scanner.clear().catch(()=>{});modal.hide();find()},()=>{})},250)});$('#cameraModal').on('hidden.bs.modal',function(){if(scanner)scanner.clear().catch(()=>{});scanner=null;$('#cameraReader').empty()});
});
function searchHistory(){
let barcode=$("#serial_number").val().trim();
if(barcode=="") return;
$.ajax({
url: `<?= base_url("items/scan_history"); ?>`,
type:"POST",
dataType:"json",
data:{
barcode:barcode
},
beforeSend:function(){
$("#serial_number").prop("disabled",true);
},
success:function(r){
$("#serial_number")
.prop("disabled",false)
.val("")
.focus();
if(!r.status){
Swal.fire({
icon:"error",
text:r.message
});
return;
}
renderItem(r.item);
renderHistory(r.history);
}
});
}
function renderItem(item){
let html='';
html+='<div class="row">';
html+=' <div class="col-md-6">';
html+=' <h4 class="mb-3"><b>'+item.nama_barang+'</b></h4>';
html+=' <div class="row mb-2">';
html+=' <div class="col-4 font-weight-bold">Kode</div>';
html+=' <div class="col-1">:</div>';
html+=' <div class="col-7">'+item.kode_detail+'</div>';
html+=' </div>';
html+=' <div class="row mb-2">';
html+=' <div class="col-4 font-weight-bold">Barcode</div>';
html+=' <div class="col-1">:</div>';
html+=' <div class="col-7">'+item.barcode+'</div>';
html+=' </div>';
html+=' </div>';
html+=' <div class="col-md-6">';
html+=' <div class="row mb-2">';
html+=' <div class="col-4 font-weight-bold">Serial Number</div>';
html+=' <div class="col-1">:</div>';
html+=' <div class="col-7">'+(item.serial_number ? item.serial_number : '-')+'</div>';
html+=' </div>';
html+=' <div class="row mb-2">';
html+=' <div class="col-4 font-weight-bold">Status</div>';
html+=' <div class="col-1">:</div>';
html+=' <div class="col-7">'+item.status+'</div>';
html+=' </div>';
html+=' <div class="row mb-2">';
html+=' <div class="col-4 font-weight-bold">Qty</div>';
html+=' <div class="col-1">:</div>';
html+=' <div class="col-7">'+item.qty_sisa+' / '+item.qty_awal+'</div>';
html+=' </div>';
html+=' </div>';
html+='</div>';
$("#itemInfo").html(html);
}
function renderHistory(list){
let html='';
$.each(list,function(i,v){
html+="<tr>";
html+="<td>"+(i+1)+"</td>";
html+="<td>"+v.created_at+"</td>";
html+="<td>"+v.movement_type+"</td>";
html+="<td>"+(v.from_warehouse??v.from_type)+"</td>";
html+="<td>"+(v.to_warehouse??v.to_type)+"</td>";
html+="<td>"+v.notes+"</td>";
html+="</tr>";
});
$("#tableBarcode tbody").html(html);
}
let html5QrCode=null;
$("#btnCamera").click(function(){
$("#scannerArea").hide();
$("#cameraArea").show();
html5QrCode=new Html5Qrcode("reader");
html5QrCode.start(
{
facingMode:"environment"
},
{
fps:10,
qrbox:220
},
function(decodedText){
html5QrCode.stop().then(function(){
$("#cameraArea").hide();
$("#scannerArea").show();
$("#serial_number")
.val(decodedText);
saveSerial();
});
}
);
});
$("#btnCloseCamera").click(function(){
if(html5QrCode){
html5QrCode.stop().then(function(){
$("#cameraArea").hide();
$("#scannerArea").show();
$("#serial_number").focus();
});
}
});
</script>
File diff suppressed because it is too large Load Diff