Perubahan barcode dan inventory

This commit is contained in:
Wian Drs
2026-07-12 22:10:02 +07:00
parent 3ac6316da4
commit 3113d77242
21 changed files with 2989 additions and 1138 deletions
+308 -38
View File
@@ -16,9 +16,10 @@
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Kode</th>
<th>Nama</th>
<th style="min-width: 80px;">Kode</th>
<th style="min-width: 80px;">Nama</th>
<th>Lokasi Asset</th>
<th style="max-width: 150px;">Keterangan</th>
<th>Nilai</th>
<th>Masa</th>
<th>Susut/Bulan</th>
@@ -56,9 +57,10 @@
<input type="text" id="nama_asset" class="form-control">
<label class="mt-2">Keterangan</label>
<input type="text" id="keterangan" class="form-control">
<textarea rows="3" id="keterangan" class="form-control"></textarea>
<!-- <input type="text" id="keterangan" class="form-control"> -->
<label class="mt-2">Harga Per Unit</label>
<label class="mt-2">Harga</label>
<input type="text" id="harga" class="form-control format-rupiah">
<label class="mt-2">Tanggal</label>
@@ -99,7 +101,8 @@
<select id="edit_lokasi_asset" class="form-control"></select>
<label class="mt-2">Keterangan</label>
<input type="text" id="edit_keterangan" class="form-control">
<!-- <input type="text" id="edit_keterangan" class="form-control"> -->
<textarea rows="3" id="edit_keterangan" class="form-control"></textarea>
</div>
<div class="modal-footer">
<button class="btn btn-primary" id="btnUpdate">Update</button>
@@ -146,7 +149,7 @@
</div>
<div class="modal-body">
<input type="hidden" id="s_item_id">
<input type="hidden" id="s_harga">
<!-- <input type="hidden" id="s_harga"> -->
<label class="mt-2">Akun Asset (Debit)</label>
<select id="s_account_asset" class="form-control"></select>
@@ -155,14 +158,33 @@
<select id="s_lokasi_asset" class="form-control"></select>
<label>Pilih Barang</label>
<select id="s_item" class="form-control"></select>
<select id="s_item" class="form-control select-search"></select>
<label class="mt-2">Stok Tersedia</label>
<input type="text" id="s_stok" class="form-control" readonly>
<div class="mb-2 d-none" id="wrap_barcode_select">
<label for="barcode_select" class="form-label">Barcode / QR ID</label>
<select id="barcode_select" class="form-control select-search"></select>
</div>
<div id="stokSisaQty"></div>
<label class="mt-2">Harga Barang</label>
<input type="text" id="s_harga" class="form-control format-rupiah" disabled>
<div class="mb-0 d-none" id="wrap_qty">
<label class="mt-2">Qty</label>
<input type="number" id="s_qty" placeholder="1" class="form-control">
<label class="mt-2">Total Harga</label>
<input type="text" id="s_total_harga" class="form-control format-rupiah" disabled>
</div>
<label class="mt-2">Tanggal</label>
<input type="date" id="s_tanggal" class="form-control">
<label class="mt-2">Keterangan</label>
<textarea rows="3" id="s_keterangan" class="form-control"></textarea>
<!-- <input type="text" id="s_keterangan" class="form-control"> -->
<hr>
<label>Masa Manfaat (bulan)</label>
@@ -224,6 +246,10 @@ function formatRupiah(angka){
return angka.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
function parseNumber(val){
return parseInt((val || '').toString().replace(/\D/g,'')) || 0;
}
function setSelectValue(selector, value){
setTimeout(()=>{
$(selector).val(value).trigger('change');
@@ -269,7 +295,7 @@ function loadItems(){
$.get("<?= base_url('asset/get_items'); ?>",res=>{
let opt='<option value="">-- PILIH BARANG --</option>';
res.forEach(i=>{
opt += `<option value="${i.id}" data-harga="${i.harga_beli}" data-stok="${i.stok}" data-nama="${i.nama_barang}">
opt += `<option value="${i.id}" data-id="${i.id}" data-harga="${i.harga_beli}" data-stok="${i.stok}" data-nama="${i.nama_barang}" data-type="${i.tracking_type}">
${i.kode_detail} - ${i.nama_barang} - ( Stok: ${i.stok})
</option>`;
});
@@ -282,20 +308,81 @@ function hitungSusut(){
let harga = parseInt($('#harga').val().replace(/\D/g,'')) || 0;
let residu = parseInt($('#residu').val().replace(/\D/g,'')) || 0;
let masa = parseInt($('#masa').val()) || 1;
let maxResidu = harga / 100 * 80;
if (residu > maxResidu) {
residu = maxResidu;
$('#residu').val(maxResidu).trigger('input');
}
let susut = (harga - residu) / masa;
$('#susut').val(formatRupiah(Math.round(susut)));
susut = Math.max(0, susut);
$('#susut').val(susut);
}
// ================= LOAD BARCODE ITEMS =================
// function loadItemBarcodes(item_id){
// return $.get("<?= base_url('items/get_list_barcode_id/'); ?>" + item_id, function(res){
// if(res && res.length){
// let opt = '<option value="">Pilih Item</option>';
// res.forEach(i=>{
// opt += `<option value="${i.barcode_id}">
// ${i.nama_barang} - ${i.barcode} - ${i.serial_number}
// </option>`;
// });
// $('#barcode_select').html(opt);
// $('#wrap_barcode_select').removeClass('d-none');
// } else {
// $('#wrap_barcode_select').addClass('d-none');
// }
// }, 'json');
// }
function loadItemBarcodes(item_id, selectedBarcode = null){
return $.get("<?= base_url('items/get_list_barcode_id/'); ?>" + item_id, function(res){
if(res && res.length){
let opt = '<option value="">Pilih Barcode</option>';
res.forEach(i=>{
opt += `
<option value="${i.barcode_id}" data-qty_sisa="${i.qty_sisa}">
${i.nama_barang} - ${i.barcode} - ${i.serial_number}
</option>
`;
});
$('#barcode_select').html(opt);
if(selectedBarcode){
$('#barcode_select').val(selectedBarcode);
}
$('#wrap_barcode_select').removeClass('d-none');
// setMode('item');
}else{
$('#wrap_barcode_select').addClass('d-none');
// setMode('manual');
}
},'json');
}
$('#masa, #residu, #harga').on('keyup change',hitungSusut);
// ================= HITUNG SUSUT STOCK =================
$('#s_masa, #s_residu').on('keyup change',function(){
let harga = parseInt($('#s_harga').val()) || 0;
let residu = parseInt($('#s_residu').val().replace(/\D/g,'')) || 0;
function hitungSusutStock(){
let trackingType = ($('#s_item option:selected').data('type') || '').toString().trim().toUpperCase();
let hargaDasar = trackingType === 'QTY' ? parseNumber($('#s_total_harga').val()) : parseNumber($('#s_harga').val());
let residu = parseNumber($('#s_residu').val());
let masa = parseInt($('#s_masa').val()) || 1;
let susut = (harga - residu) / masa;
$('#s_susut').val(formatRupiah(Math.round(susut)));
});
let maxResidu = hargaDasar / 100 * 80;
if (residu > maxResidu) {
residu = maxResidu;
$('#s_residu').val(maxResidu).trigger('input');
}
let susut = (hargaDasar - residu) / masa;
susut = Math.max(0, susut);
$('#s_susut').val(susut);
}
$('#s_masa, #s_residu').on('keyup change', hitungSusutStock);
// ================= TAMBAH ASSET MANUAL =================
$('.btn-add-asset').click(function(){
@@ -303,26 +390,77 @@ $('.btn-add-asset').click(function(){
$('#modalTitleAsset').text('Tambah Asset');
$('#modalAsset input[type="text"], #modalAsset input[type="date"], #modalAsset input[type="number"], #modalAsset select').val('');
$('#id_asset').val('');
$('#stokSisaQty').html('');
loadKas(); loadAsset(); loadLokasiAsset();
$('#modalAsset').modal('show');
});
// ================= DETAIL & HISTORY =================
$(document).on('click','.btn-detail',function(){
let id = $(this).data('id');
$.get("<?= base_url('asset/detail/'); ?>"+id, function(asset){
$('#detailContent').html(`
<table class="table table-borderless">
<tr><td><strong>Kode Asset</strong></td><td>: <strong>${asset.kode_asset || '-'}</strong></td></tr>
<tr><td><strong>Nama Asset</strong></td><td>: <strong>${asset.nama_asset}</strong></td></tr>
<tr><td><strong>Lokasi</strong></td><td>: <strong>${asset.nama_lokasi || '-'}</strong></td></tr>
<tr><td><strong>Harga/Unit</strong></td><td>: <strong>Rp ${formatRupiah(asset.harga_per_unit)}</strong></td></tr>
<tr><td><strong>Nilai Buku</strong></td><td>: <strong>Rp ${formatRupiah(asset.nilai_buku)}</strong></td></tr>
<tr><td><strong>Masa Manfaat</strong></td><td>: <strong>${asset.masa_manfaat} bulan</strong></td></tr>
<tr><td><strong>Sumber</strong></td><td>: <strong>${asset.sumber}</strong></td></tr>
<tr><td><strong>Keterangan</strong></td><td>: <strong>${asset.keterangan || '-'}</strong></td></tr>
</table>
<div class="row">
<div class="col-md-6">
<table class="table table-borderless table-sm">
<tr>
<td width="45%"><strong>Kode Asset</strong></td>
<td>: <strong>${asset.kode_asset || '-'}</strong></td>
</tr>
<tr>
<td><strong>Nama Asset</strong></td>
<td>: <strong>${asset.nama_asset}</strong></td>
</tr>
<tr>
<td><strong>Lokasi</strong></td>
<td>: <strong>${asset.nama_lokasi || '-'}</strong></td>
</tr>
<tr>
<td><strong>Harga/Unit</strong></td>
<td>: <strong>Rp ${formatRupiah(asset.harga_per_unit)}</strong></td>
</tr>
<tr>
<td><strong>Qty</strong></td>
<td>: <strong>${asset.qty}</strong></td>
</tr>
<tr>
<td><strong>Nilai Perolehan</strong></td>
<td>: <strong>Rp ${formatRupiah(asset.nilai_perolehan)}</strong></td>
</tr>
</table>
</div>
<div class="col-md-6">
<table class="table table-borderless table-sm">
<tr>
<td width="45%"><strong>Akumulasi Penyusutan</strong></td>
<td>: <strong>Rp ${formatRupiah(asset.akumulasi_penyusutan || 0)}</strong></td>
</tr>
<tr>
<td><strong>Nilai Buku</strong></td>
<td>: <strong>Rp ${formatRupiah(asset.nilai_buku)}</strong></td>
</tr>
<tr>
<td><strong>Masa Manfaat</strong></td>
<td>: <strong>${asset.masa_manfaat} bulan</strong></td>
</tr>
<tr>
<td><strong>Sumber</strong></td>
<td>: <strong>${asset.sumber}</strong></td>
</tr>
<tr>
<td><strong>Keterangan</strong></td>
<td>: <strong>${asset.keterangan || '-'}</strong></td>
</tr>
</table>
</div>
</div>
`);
// Load history
@@ -336,7 +474,7 @@ $(document).on('click','.btn-detail',function(){
h.tipe=='penambahan' ? 'bg-info' :
h.tipe=='pengurangan' ? 'bg-warning' : 'bg-secondary';
rows += `<tr>
<td>${h.created_at}</td>
<td>${h.tanggal_dibuat}</td>
<td><span class="badge ${badgeClass}">${h.tipe}</span></td>
<td>Rp ${formatRupiah(h.nilai || 0)}</td>
<td>${h.keterangan}</td>
@@ -465,35 +603,157 @@ $('#btnSave').click(function(){
});
// ================= FROM STOCK =================
$('.btn-from-stock').click(function(){
function resetStockForm(){
$('#modalAssetStock input[type="text"], #modalAssetStock input[type="date"], #modalAssetStock input[type="number"], #modalAssetStock select').val('');
$('#s_item_id, #s_harga').val('');
$('#s_item_id, #s_harga, #s_total_harga, #s_susut, #s_keterangan').val('');
$('#s_qty').val(1);
$('#stokSisaQty').html('');
$('#wrap_qty').addClass('d-none');
$('#wrap_barcode_select').removeClass('d-none');
$('#barcode_select').html('<option value="">Loading...</option>');
}
$('.btn-from-stock').click(function(){
resetStockForm();
loadItems();
loadAsset();
loadLokasiAsset();
$('#modalAssetStock').modal('show');
});
// ================= PILIH ITEM STOCK =================
$(document).on('change','#s_item',function(){
$('#barcode_select').on('change', function(){
let selectedItem = $('#s_item option:selected');
let type = (selectedItem.data('type') || '').toString().trim().toUpperCase();
let selected = $(this).find(':selected');
let harga = selected.data('harga') || 0;
let stok = selected.data('stok') || 0;
$('#s_item_id').val($(this).val());
let qty_sisa = parseFloat(selected.data('qty_sisa')) || 0;
if($(this).val()){
$('#stokSisaQty').html('<h6 class="text-success ml-4">Stok : ' + qty_sisa + '</h6><hr>');
}else{
$('#stokSisaQty').html('');
}
// perlakuan qty setelah barcode dipilih, berdasarkan tracking_type
if(type === 'UNIT'){
$('#stokSisaQty').html('');
$('#wrap_qty').addClass('d-none');
$('#s_qty').removeAttr('max').val(1);
$('#s_total_harga').val(parseNumber($('#s_harga').val()));
hitungSusutStock();
}else{
$('#wrap_qty').removeClass('d-none');
$('#s_qty').attr('min', 1).attr('max', qty_sisa > 0 ? qty_sisa : 1).val('');
$('#s_total_harga').val('');
}
});
$('#s_item').on('change', function(){
let selected = $(this).find(':selected');
let item_id = selected.data('id');
let type = selected.data('type');
let harga = parseInt(selected.data('harga')) || 0;
let stok = parseFloat(selected.data('stok')) || 0;
$('#s_item_id').val(item_id || '');
$('#s_harga').val(harga);
$('#s_stok').val(stok);
$('#s_total_harga').val(harga);
$('#stokSisaQty').html('');
$('#s_qty').val(1).removeAttr('max');
$('#wrap_qty').addClass('d-none');
$('#wrap_barcode_select').addClass('d-none');
$('#barcode_select').html('<option value="">Pilih Barcode</option>');
if(!item_id){
return;
}
let normalizedType = (type || '').toString().trim().toUpperCase();
// barcode tetap harus muncul untuk ITEM maupun QTY
loadItemBarcodes(item_id, null).done(function(res){
if(res && res.length){
$('#wrap_barcode_select').removeClass('d-none');
}else{
$('#wrap_barcode_select').addClass('d-none');
$('#barcode_select').html('<option value="">Barcode tidak tersedia</option>');
}
// sebelum pilih barcode: qty & total belum ditentukan
$('#wrap_qty').addClass('d-none');
$('#s_qty').removeAttr('max').val('');
$('#s_total_harga').val('');
}).fail(function(){
$('#wrap_barcode_select').addClass('d-none');
$('#barcode_select').html('<option value="">Gagal load barcode</option>');
$('#wrap_qty').addClass('d-none');
$('#s_qty').removeAttr('max').val('');
$('#s_total_harga').val('');
});
});
$('#s_qty').on('keyup change',function(){
let selectedItem = $('#s_item option:selected');
let type = (selectedItem.data('type') || '').toString().trim().toUpperCase();
let qtyRaw = $('#s_qty').val();
let qty = parseInt(qtyRaw);
let harga = parseNumber($('#s_harga').val());
let max = parseFloat($('#s_qty').attr('max')) || 0;
if(type === 'UNIT'){
$('#wrap_qty').addClass('d-none');
$('#s_qty').val(1);
$('#s_total_harga').val(harga);
return;
}
if(!qtyRaw || isNaN(qty) || qty < 1){
$('#s_total_harga').val('');
return;
}
if(max > 0 && qty > max){
qty = max;
Swal.fire('Warning','Stok tidak cukup! Max: ' + max,'warning');
}
let total = harga * qty;
$('#s_qty').val(qty);
$('#s_total_harga').val(total);
hitungSusutStock();
});
// ================= SAVE FROM STOCK =================
$('#btnSaveStock').click(function(){
let btn = $(this);
let trackingType = ($('#s_item option:selected').data('type') || '').toString().trim().toUpperCase();
let maxQty = parseFloat($('#s_qty').attr('max')) || 0;
let qtyRaw = $('#s_qty').val();
let qty = parseInt(qtyRaw);
if(trackingType === 'UNIT'){
qty = 1;
}else{
if(!qtyRaw || isNaN(qty) || qty < 1){
Swal.fire('Error','Qty wajib diisi untuk item tracking QTY','error');
return;
}
if(maxQty > 0 && qty > maxQty){
Swal.fire('Error','Qty melebihi stok tersedia','error');
return;
}
}
let data = {
item_id: $('#s_item').val(),
s_tanggal: $('#s_tanggal').val(),
s_masa: $('#s_masa').val(),
s_residu: $('#s_residu').val(),
s_lokasi_asset: $('#s_lokasi_asset').val(),
account_asset: $('#s_account_asset').val()
account_asset: $('#s_account_asset').val(),
s_keterangan: $('#s_keterangan').val(),
barcode_id: $('#barcode_select').val(),
qty: qty
};
// Validasi
@@ -502,6 +762,15 @@ $('#btnSaveStock').click(function(){
return;
}
if(!data.barcode_id){
Swal.fire('Error','Barcode wajib dipilih','error');
return;
}
if(trackingType === 'UNIT'){
data.qty = 1;
}
btn.prop('disabled', true).html('Menyimpan...');
$.post("<?= base_url('asset/save_from_stock'); ?>",data,function(res){
@@ -523,5 +792,6 @@ $('#btnSaveStock').click(function(){
});
});
});
</script>