'}).join('');
let handover=item.subject_type==='company_barcode'&&Number(item.warehouse_available)>0&&can('handover')?' Tambahkan ke Penyerahan Batch':'';
$('#techScanResult').removeClass('tech-empty').html('
Tersedia di Gudang'+qty(item.warehouse_available||0)+'
'+handover+'
Posisi
Penggunaan
Kondisi
Qty
Tindakan Valid
'+(allocations||'
Tidak ada saldo di luar gudang.
')+'
');
}
function loadScanned(code){const btn=$('#techScanForm button').prop('disabled',true);$.getJSON(base+'teknisi/equipment_scan',{code:code}).done(r=>{if(!r.status)return toast(false,r.message||'Barcode tidak dapat diperiksa.');scanned=r.result||r.data&&r.data.result;if(!scanned)return toast(false,'Respons barcode tidak lengkap.');renderScan(scanned)}).fail(x=>toast(false,(x.responseJSON&&x.responseJSON.message)||'Barcode tidak dapat diperiksa.')).always(()=>btn.prop('disabled',false))}
function renderLookup(rows){$('#techScanResult').removeClass('tech-empty').html('
Hasil pencarian
Pilih barcode yang akan diperiksa.
'+rows.length+' hasil
'+rows.map((row,index)=>'').join('')+'
')}
$('#techScanForm').on('submit',function(e){e.preventDefault();const query=$('#techScanCode').val().trim();if(!query)return toast(false,'Scan barcode atau isi nama barang.');const btn=$(this).find('button').prop('disabled',true);$.getJSON(base+'teknisi/equipment_search',{q:query,mode:'all'}).done(r=>{const rows=r.data||[];if(!rows.length)return toast(false,'Barang tidak ditemukan.');const exact=rows.filter(row=>[row.barcode,row.serial_number].some(value=>String(value||'').toLowerCase()===query.toLowerCase()));if(exact.length===1)loadScanned(exact[0].lookup_code);else if(rows.length===1)loadScanned(rows[0].lookup_code);else renderLookup(rows)}).fail(x=>toast(false,(x.responseJSON&&x.responseJSON.message)||'Pencarian barang gagal.')).always(()=>btn.prop('disabled',false))});
$(document).on('click','.tech-lookup-select',function(){$('#techScanCode').val(this.dataset.code);loadScanned(this.dataset.code)});
function allocation(id){return scanned&&scanned.allocations?(scanned.allocations.find(x=>String(x.id)===String(id))||null):null}
function openAction(action,id){const a=id?allocation(id):null;const form=$('#techActionForm')[0];form.reset();form.elements.action.value=action;form.elements.subject_id.value=scanned?scanned.subject_id:'';form.elements.allocation_id.value=id||'';form.elements.idempotency_key.value=randomKey();form.elements.date.value=new Date().toISOString().slice(0,10);$('#techActionForm .modal-title').text(actionLabels[action]||'Catat Pergerakan');$('#techActionSubject').html(''+esc(scanned?scanned.display_name:(a?a.display_name:'Barang'))+' '+esc(scanned?(scanned.barcode||''):(a?a.barcode_snapshot:''))+(a?' · '+esc(positionText(a))+' · Saldo '+qty(a.qty):'')+'');
const needs={qty:true,technician:['handover','remove'].includes(action),target_technician:action==='transfer',customer:['install','return_customer'].includes(action),warehouse:action==='return',condition:action==='remove',inspection:action==='inspect',location:action==='install',reason:['remove','return','transfer'].includes(action)};Object.keys(needs).forEach(k=>{$('[data-field="'+k+'"]').toggleClass('d-none',!needs[k]).find('input,select').prop('required',!!needs[k])});
if(action==='inspect'&&a){form.elements.allocation_id.value=a.id}if((scanned&&scanned.tracking_type==='UNIT')||(a&&a.tracking_type==='UNIT')){$('[data-field="qty"]').addClass('d-none');form.elements.qty.value=1}else form.elements.qty.value=a?a.qty:(scanned?scanned.warehouse_available:'');clearFileBox($('#techActionForm [data-filebox]')[0]);modal('techActionModal',true)}
$(document).on('click','.tech-action',function(){openAction(this.dataset.action,this.dataset.allocation)});
$('#techActionForm').on('submit',async function(e){e.preventDefault();const form=this,action=form.elements.action.value;modal('techActionModal',false);await new Promise(resolve=>setTimeout(resolve,180));if(!(await confirmPost(actionLabels[action]||'Posting pergerakan?'))){modal('techActionModal',true);return}const btn=$(form).find('[type=submit]').prop('disabled',true);const url=action==='inspect'?'teknisi/process_inspection':'teknisi/process_equipment';$.ajax({url:base+url,method:'POST',data:new FormData(form),processData:false,contentType:false,dataType:'json'}).done(r=>{if(!r.status){toast(false,r.message);modal('techActionModal',true);return}toast(true,r.message);if($('#techScanCode').length)$('#techScanForm').trigger('submit');loadInspection();loadDocuments()}).fail(x=>{toast(false,(x.responseJSON&&x.responseJSON.message)||'Transaksi gagal diproses.');modal('techActionModal',true)}).always(()=>btn.prop('disabled',false))});
function loadDocuments(){const table=$('#techDocumentsTable tbody');if(!table.length)return;if(documentTable){documentTable.destroy();documentTable=null}$.getJSON(base+'teknisi/equipment_documents').done(r=>{const rows=(r.data||[]).slice(0,100);table.html(rows.length?rows.map(d=>'
'+(files||'Tidak ada lampiran atau akses tidak diberikan.')+'
'+correction);modal('techDocumentModal',true)}).fail(x=>toast(false,(x.responseJSON&&x.responseJSON.message)||'Detail tidak dapat dibuka.'))});
$(document).on('click','.tech-correct-doc',async function(){const id=this.dataset.id,no=this.dataset.no;modal('techDocumentModal',false);if(!window.Swal)return;const r=await Swal.fire({icon:'warning',title:'Koreksi '+no,html:'',showCancelButton:true,confirmButtonText:'Buat Reversal',cancelButtonText:'Batal',allowOutsideClick:false,preConfirm:()=>{const date=document.getElementById('techCorrectionDate').value,reason=document.getElementById('techCorrectionReason').value.trim();if(!date||!reason){Swal.showValidationMessage('Tanggal dan alasan koreksi wajib diisi.');return false}return{date,reason}}});if(!r.isConfirmed)return;$.post(base+'teknisi/process_correction',{document_id:id,date:r.value.date,reason:r.value.reason,idempotency_key:randomKey()},res=>{toast(!!res.status,res.message);if(res.status)loadDocuments()},'json').fail(x=>toast(false,(x.responseJSON&&x.responseJSON.message)||'Koreksi gagal diproses.'))});
$(document).on('click','.tech-doc-pdf',function(){preview(base+'teknisi/equipment_document_pdf/'+this.dataset.id,'application/pdf')});
$(document).on('click','.tech-attachment',function(){preview(this.dataset.url,this.dataset.mime)});
function preview(url,mime){$('#techPreviewBody').html(mime==='application/pdf'?'':'
');modal('techPreviewModal',true)}
function replacementCandidates(kind,query){const form=document.getElementById('techReplacementForm');if(!form)return[];const tech=Number(form.elements.technician_id.value||0),customer=Number(form.elements.customer_id.value||0),q=String(query||'').trim().toLowerCase();return replacementAllocations.filter(a=>{const eligible=kind==='carried'?a.custodian_type==='technician'&&Number(a.custodian_id)===tech&&['carried','removed','returned'].includes(a.usage_status):a.custodian_type==='customer'&&Number(a.customer_id)===customer&&a.usage_status==='installed';return eligible&&(!q||[a.display_name,a.barcode_snapshot,a.serial_number,a.external_serial].some(v=>String(v||'').toLowerCase().includes(q)))})}
function renderReplacementSelect(kind,query){const form=document.getElementById('techReplacementForm');if(!form)return;const select=form.querySelector('.tech-allocation-select[data-kind="'+kind+'"]'),current=select.value,rows=replacementCandidates(kind,query),needs=kind==='carried'?!form.elements.technician_id.value:!form.elements.customer_id.value;select.innerHTML=''+rows.map(a=>'').join('');if(rows.some(a=>String(a.id)===String(current)))select.value=current;else if(current)$(select).trigger('change');const hint=document.getElementById(kind==='carried'?'techOutgoingHint':'techIncomingHint');if(hint)hint.textContent=needs?(kind==='carried'?'Pilih teknisi terlebih dahulu.':'Pilih customer terlebih dahulu.'):(rows.length+' barang ditemukan'+(query?' untuk pencarian ini.':'.'))}
function loadAllocs(){if(!$('.tech-allocation-select').length)return;$.getJSON(base+'teknisi/equipment_allocations').done(r=>{replacementAllocations=r.data||[];renderReplacementSelect('carried','');renderReplacementSelect('installed','')}).fail(()=>toast(false,'Daftar posisi barang gagal dimuat.'))}
function selectReplacementBySearch(kind){const input=document.getElementById(kind==='carried'?'techOutgoingSearch':'techIncomingSearch'),query=input.value.trim();if(!query)return renderReplacementSelect(kind,'');const rows=replacementCandidates(kind,query),exact=rows.filter(a=>[a.barcode_snapshot,a.serial_number,a.external_serial].some(v=>String(v||'').toLowerCase()===query.toLowerCase()));renderReplacementSelect(kind,exact.length===1?'':query);const select=document.querySelector('.tech-allocation-select[data-kind="'+kind+'"]');if(exact.length===1){select.value=exact[0].id;$(select).trigger('change');input.value='';renderReplacementSelect(kind,'')}else if(rows.length===1){select.value=rows[0].id;$(select).trigger('change')}else if(!rows.length)toast(false,'Barang tidak ditemukan pada teknisi/customer yang dipilih.');else{select.focus();toast(true,rows.length+' barang sesuai pencarian. Pilih salah satu dari daftar.')}}
$(document).on('click','.tech-replacement-search',function(){selectReplacementBySearch(this.dataset.kind)});
$('#techOutgoingSearch,#techIncomingSearch').on('keydown',function(e){if(e.key==='Enter'){e.preventDefault();selectReplacementBySearch(this.id==='techOutgoingSearch'?'carried':'installed')}}).on('input',function(){renderReplacementSelect(this.id==='techOutgoingSearch'?'carried':'installed',this.value)});
$('#techReplacementForm [name=technician_id]').on('change',function(){$('#techOutgoingSearch').val('');renderReplacementSelect('carried','')});
$('#techReplacementForm [name=customer_id]').on('change',function(){$('#techIncomingSearch').val('');renderReplacementSelect('installed','')});
$(document).on('change','.tech-allocation-select',function(){const row=replacementAllocations.find(a=>String(a.id)===String(this.value)),kind=this.dataset.kind,info=document.getElementById(kind==='carried'?'techOutgoingInfo':'techIncomingInfo'),amount=document.querySelector('#techReplacementForm [name="'+(kind==='carried'?'outgoing_qty':'incoming_qty')+'"]');if(!row){if(info)info.textContent=kind==='carried'?'Belum ada barang dipilih.':'Bisa milik perusahaan maupun milik customer.';if(amount){amount.readOnly=false;if(kind==='carried')amount.value='';}return}if(info)info.innerHTML=''+esc(row.ownership_type==='company'?'Milik Perusahaan':'Milik Customer / Non-Persediaan')+' · '+esc(row.tracking_type)+' · Saldo '+qty(row.qty)+' · '+esc(positionText(row));if(amount){amount.value=String(row.tracking_type).toUpperCase()==='UNIT'?1:Number(row.qty);amount.readOnly=String(row.tracking_type).toUpperCase()==='UNIT';amount.max=row.qty}});
$('#techNewOldItem').on('change',function(){const manual=this.checked;$('#techOldItemFields').toggleClass('d-none',!manual);$('#techReplacementForm [name=incoming_allocation_id]').prop('disabled',manual).prop('required',!manual);$('#techIncomingSearch').prop('disabled',manual);$('#techOldItemFields [name=old_equipment_name],#techOldItemFields [name=old_barcode]').prop('required',manual)});
$('#techReplacementForm [name=incoming_allocation_id]').prop('required',true);
$('#techReplacementForm').on('submit',async function(e){e.preventDefault();if(!(await confirmPost('Posting pemasangan dan penggantian?')))return;const btn=$(this).find('[type=submit]').prop('disabled',true),fd=new FormData(this);fd.set('idempotency_key',randomKey());$.ajax({url:base+'teknisi/process_replacement',method:'POST',data:fd,processData:false,contentType:false,dataType:'json'}).done(r=>{if(!r.status)return toast(false,r.message);toast(true,r.message);this.reset();$('#techNewOldItem').trigger('change');$('#techOutgoingSearch,#techIncomingSearch').val('');$('#techOutgoingInfo').text('Belum ada barang dipilih.');$('#techIncomingInfo').text('Bisa milik perusahaan maupun milik customer.');$('#techReplacementForm [name=outgoing_qty]').val('').prop('readonly',false).removeAttr('max');$('#techReplacementForm [name=incoming_qty]').val('1').prop('readonly',false).removeAttr('max');clearFileBox($(this).find('[data-filebox]')[0]);loadAllocs()}).fail(x=>toast(false,(x.responseJSON&&x.responseJSON.message)||'Penggantian gagal diproses.')).always(()=>btn.prop('disabled',false))});
function loadInspection(){const body=$('#techInspectionTable tbody');if(!body.length)return;const query=$('#techInspectionFilter').serialize();$.getJSON(base+'teknisi/inspection_data'+(query?'?'+query:'')).done(r=>{const rows=r.data||[];body.html(rows.length?rows.map(a=>{const waiting=Number(a.requires_return)===1;let position=waiting?'Masih dibawa teknisi':(a.custodian_type==='customer'?'Gudang customer: '+(a.customer_name||'-'):(a.custodian_type==='warehouse'?'Gudang perusahaan: '+(a.warehouse_name||'-'):(a.warehouse_name||'Karantina gudang')));let action='Menunggu dikembalikan';if(waiting&&perms.return)action=' Kembalikan';else if(!waiting&&perms.inspect)action='';return'
Tidak ada barang yang perlu dikembalikan atau diperiksa.
')}).fail(()=>body.html('
Antrean gagal dimuat.
'))}
$('#techInspectionFilter').on('submit',function(e){e.preventDefault();loadInspection()});
$(document).on('click','.tech-inspect-row',function(){const a=JSON.parse(decodeURIComponent(this.dataset.row));scanned={display_name:a.display_name,barcode:a.barcode_snapshot,tracking_type:a.tracking_type,allocations:[a]};openAction('inspect',a.id)});
function loadCustomers(){const body=$('#techCustomerTable tbody');if(!body.length)return;$.getJSON(base+'teknisi/customer_equipment_data').done(r=>{const rows=r.data||[];body.html(rows.length?rows.map(a=>'
'+esc(a.customer_name)+'
'+qty(a.item_count)+'
'+qty(a.total_qty)+'
'+qty(a.company_qty)+'
'+qty(a.customer_qty)+'
'+qty(a.installed_qty)+'
'+qty(a.good_qty)+'
').join(''):'
Belum ada customer yang mempunyai barang tercatat.
')}).fail(()=>body.html('
Ringkasan barang customer gagal dimuat.
'))}
let activeCustomerId=0,activeCustomerName='';
function customerPosition(a){if(a.custodian_type==='technician')return'Teknisi: '+(a.technician_name||'-');if(a.custodian_type==='customer')return(a.usage_status==='installed'?'Terpasang di ':'Tersimpan di ')+(a.customer_name||'Customer');if(a.custodian_type==='quarantine')return'Karantina: '+(a.warehouse_name||'-');if(a.custodian_type==='warehouse')return'Gudang perusahaan: '+(a.warehouse_name||'-');if(a.custodian_type==='service_center')return'Pusat perbaikan: '+(a.warehouse_name||'-');return a.custodian_type||'-'}
function loadCustomerGroup(){if(!activeCustomerId)return;const body=$('#techCustomerGroupBody'),status=$('#techCustomerStatus').val()||'all';body.html('
'+esc((x.responseJSON&&x.responseJSON.message)||'Log keterangan gagal dimuat.')+'
'))});
$('#techCustomerLookupForm').on('submit',function(e){e.preventDefault();const query=$('#techCustomerLookup').val().trim(),target=$('#techCustomerLookupResult');if(!query)return toast(false,'Scan barcode/SN atau isi nama barang customer.');const btn=$(this).find('button').prop('disabled',true);$.getJSON(base+'teknisi/equipment_search',{q:query,mode:'customer'}).done(r=>{const rows=r.data||[];if(!rows.length){target.addClass('d-none').empty();$('#techCustomerItemForm [name=external_barcode]').val(query);document.getElementById('techCustomerItemForm').scrollIntoView({behavior:'smooth',block:'start'});toast(true,'Data lama tidak ditemukan. Barcode sudah dimasukkan ke form baru; lengkapi data wajib saja.');return}target.removeClass('d-none').html('
Barang sudah pernah dicatat. Pilih data berikut; identitas tidak perlu dimasukkan ulang.