1348 lines
50 KiB
PHP
1348 lines
50 KiB
PHP
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css">
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.4.1/css/responsive.bootstrap5.min.css">
|
|
|
|
<style>
|
|
:root {
|
|
--tech-primary: #ff9800;
|
|
--tech-primary-light: #fff3e0;
|
|
--tech-primary-dark: #ff9800;
|
|
}
|
|
|
|
body {
|
|
background: #f5f7fb;
|
|
}
|
|
|
|
.tech-card {
|
|
border: none;
|
|
border-radius: 14px;
|
|
overflow: hidden;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
background: #fff;
|
|
}
|
|
|
|
.tech-card .card-header-custom {
|
|
background: linear-gradient(135deg, var(--tech-primary), var(--tech-primary-dark));
|
|
color: #fff;
|
|
padding: 14px 20px;
|
|
font-weight: 600;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.tech-card .card-body {
|
|
padding: 18px;
|
|
}
|
|
|
|
.tech-btn-group .btn {
|
|
border-radius: 10px;
|
|
padding: 10px 16px;
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
transition: all .2s;
|
|
}
|
|
|
|
.scanner-input {
|
|
height: 48px;
|
|
font-size: 16px;
|
|
border-radius: 10px;
|
|
border: 2px dashed #dee2e6;
|
|
text-align: center;
|
|
letter-spacing: 1.5px;
|
|
transition: border-color .2s;
|
|
}
|
|
|
|
.scanner-input:focus {
|
|
border-color: var(--tech-primary);
|
|
box-shadow: 0 0 0 .2rem rgba(255, 152, 0, .15);
|
|
}
|
|
|
|
.scan-note {
|
|
color: #6c757d;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.table-tech thead th {
|
|
background: #f8f9fa;
|
|
font-weight: 600;
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: .4px;
|
|
color: #495057;
|
|
border-bottom: 2px solid #ffcc80;
|
|
padding: 10px 8px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.table-tech tbody td {
|
|
padding: 8px;
|
|
vertical-align: middle;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.table-tech td .badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 65px;
|
|
padding: 0.35em 0.65em;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.table-tech tbody tr:hover {
|
|
background: #fff3e0;
|
|
}
|
|
|
|
.btn-sm-icon {
|
|
width: 30px;
|
|
height: 30px;
|
|
padding: 0;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 7px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.mode-section {
|
|
transition: opacity .2s;
|
|
}
|
|
|
|
.mode-section.d-none {
|
|
display: none !important;
|
|
}
|
|
|
|
.tech-modal .modal-content {
|
|
border-radius: 14px;
|
|
border: none;
|
|
}
|
|
|
|
.tech-modal .modal-header {
|
|
background: linear-gradient(135deg, var(--tech-primary), var(--tech-primary-dark));
|
|
color: #fff;
|
|
border-radius: 14px 14px 0 0;
|
|
padding: 14px 20px;
|
|
}
|
|
|
|
.teknisi-badge {
|
|
font-size: 13px;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
padding: 10px 14px;
|
|
border-left: 3px solid var(--tech-primary);
|
|
}
|
|
|
|
.teknisi-badge strong {
|
|
color: #1a1a2e;
|
|
}
|
|
|
|
/* ===========================
|
|
SCANNER (History Barang style)
|
|
=========================== */
|
|
.form-control-lg {
|
|
height: 60px;
|
|
font-size: 22px;
|
|
border-radius: 12px;
|
|
border: 2px dashed #dee2e6;
|
|
text-align: center;
|
|
letter-spacing: 1.5px;
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: var(--tech-primary);
|
|
box-shadow: 0 0 0 .2rem rgba(255, 152, 0, .2);
|
|
}
|
|
|
|
.camera-btn {
|
|
height: 55px;
|
|
border-radius: 12px;
|
|
font-size: 17px;
|
|
}
|
|
|
|
#reader {
|
|
width: 100%;
|
|
min-height: 280px;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
#cameraArea .scan-note {
|
|
color: #6c757d;
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* ===========================
|
|
CUSTOM CHECKBOX (Transfer Items style)
|
|
=========================== */
|
|
.form-check-input {
|
|
border: 2px solid #6c757d; /* border abu gelap agar terlihat saat belum dicentang */
|
|
background-color: #ffffff; /* pastikan background checkbox putih, beda dari bg website */
|
|
width: 1.1em;
|
|
height: 1.1em;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.form-check-input:checked {
|
|
background-color: #0d6efd; /* warna saat dicentang (biru bootstrap, bisa diganti) */
|
|
border-color: #0d6efd;
|
|
}
|
|
|
|
.form-check-input:focus {
|
|
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
|
|
border-color: #0d6efd;
|
|
}
|
|
</style>
|
|
|
|
<div class="container-fluid px-3 mt-3">
|
|
|
|
<!-- Header -->
|
|
<div class="d-flex align-items-center gap-2 mb-3">
|
|
<div class="bg-warning text-white p-2 rounded-3 d-flex align-items-center justify-content-center" style="width:38px;height:38px;">
|
|
<i class="bi bi-tools fs-5"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h5 class="mb-0 fw-bold" style="color:#1a1a2e;">Peralatan Teknisi</h5>
|
|
<small class="text-muted">Kelola barang bawaan, pengembalian, dan transfer antar teknisi</small>
|
|
</div>
|
|
<div>
|
|
<a href="<?= base_url('teknisi/log_barang'); ?>" class="btn btn-warning" id="btnLogBarang">
|
|
<i class="bi bi-journal-text me-1"></i> Log Barang Teknisi
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-3">
|
|
|
|
<!-- ============================================================ -->
|
|
<!-- LEFT PANEL -->
|
|
<!-- ============================================================ -->
|
|
<div class="col-lg-5">
|
|
|
|
<div class="card tech-card">
|
|
<div class="card-header-custom d-flex align-items-center gap-2">
|
|
<i class="bi bi-box-seam"></i>
|
|
<span>Barang Teknisi</span>
|
|
</div>
|
|
<div class="card-body">
|
|
|
|
<!-- Mode Buttons -->
|
|
<div class="btn-group tech-btn-group w-100 mb-3" role="group">
|
|
<input type="radio" class="btn-check" name="mode" id="modeKembalikan" value="kembalikan">
|
|
<label class="btn btn-outline-danger" for="modeKembalikan">
|
|
<i class="bi bi-arrow-return-left me-1"></i> Dikembalikan
|
|
</label>
|
|
|
|
<input type="radio" class="btn-check" name="mode" id="modeDibawa" value="dibawa" checked>
|
|
<label class="btn btn-outline-success" for="modeDibawa">
|
|
<i class="bi bi-bag-check me-1"></i> Dibawa
|
|
</label>
|
|
|
|
<input type="radio" class="btn-check" name="mode" id="modeTransfer" value="transfer">
|
|
<label class="btn btn-outline-primary" for="modeTransfer">
|
|
<i class="bi bi-arrow-left-right me-1"></i> Ditransfer
|
|
</label>
|
|
</div>
|
|
|
|
|
|
<!-- ================================================ -->
|
|
<!-- CAMERA AREA (shared, History Barang pattern) -->
|
|
<!-- ================================================ -->
|
|
<div id="cameraArea" style="display:none;">
|
|
<div class="text-center">
|
|
<div id="reader"></div>
|
|
<small class="scan-note d-block mt-2">
|
|
Arahkan QR ID Ke Kamera.
|
|
</small>
|
|
<button type="button" class="btn btn-secondary w-100 mt-3" id="btnCloseCamera">
|
|
Tutup Kamera
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- ================================================ -->
|
|
<!-- MODE 1: DIKEMBALIKAN -->
|
|
<!-- ================================================ -->
|
|
<div class="mode-section d-none" id="sectionKembalikan">
|
|
<div class="text-center mb-3">
|
|
<div id="scannerAreaKembalikan">
|
|
<input type="text" id="scanKembalikan" class="form-control form-control-lg text-center"
|
|
placeholder="Scan / Input QR ID" autocomplete="off">
|
|
<small class="scan-note d-block mt-2">
|
|
Scanner akan otomatis memanggil data.
|
|
</small>
|
|
<button type="button" class="btn btn-warning w-100 camera-btn mt-4" id="btnCamKembalikan">
|
|
<i class="bi bi-camera me-1"></i>
|
|
Scan Dengan Kamera
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table id="tableKembalikan" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">No</th>
|
|
<th>Barcode</th>
|
|
<th>Nama Barang</th>
|
|
<th>Serial Number</th>
|
|
<th>Teknisi</th>
|
|
<th style="width:40px">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<button class="btn btn-danger w-100 fw-semibold" id="btnSubmitKembalikan">
|
|
<i class="bi bi-check2-circle me-1"></i> Submit Pengembalian
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ================================================ -->
|
|
<!-- MODE 2: DIBAWA -->
|
|
<!-- ================================================ -->
|
|
<div class="mode-section" id="sectionDibawa">
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold text-muted small mb-1">Pilih Teknisi</label>
|
|
<select class="form-select" id="teknisiDibawa">
|
|
<option value="">-- Pilih Teknisi --</option>
|
|
<?php foreach ($teknisi_list as $t): ?>
|
|
<option value="<?= (int)$t->id; ?>">
|
|
<?= htmlspecialchars($t->employee_code . ' - ' . $t->full_name, ENT_QUOTES, 'UTF-8'); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="text-center mb-3">
|
|
<div id="scannerAreaDibawa">
|
|
<input type="text" id="scanDibawa" class="form-control form-control-lg text-center"
|
|
placeholder="Scan / Input QR ID" autocomplete="off">
|
|
<small class="scan-note d-block mt-2">
|
|
Scanner akan otomatis memanggil data.
|
|
</small>
|
|
<button type="button" class="btn btn-warning w-100 camera-btn mt-4" id="btnCamDibawa">
|
|
<i class="bi bi-camera me-1"></i>
|
|
Scan Dengan Kamera
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table id="tableDibawa" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">No</th>
|
|
<th>Barcode</th>
|
|
<th>Nama Barang</th>
|
|
<th>Serial Number</th>
|
|
<th style="width:40px">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<button class="btn btn-success w-100 fw-semibold" id="btnSubmitDibawa">
|
|
<i class="bi bi-check2-circle me-1"></i> Submit Barang Dibawa
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ================================================ -->
|
|
<!-- MODE 3: DITRANSFER -->
|
|
<!-- ================================================ -->
|
|
<div class="mode-section d-none" id="sectionTransfer">
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold text-muted small mb-1">From Teknisi</label>
|
|
<select class="form-select" id="teknisiFrom">
|
|
<option value="">-- Pilih Teknisi Asal --</option>
|
|
<?php foreach ($teknisi_list as $t): ?>
|
|
<option value="<?= (int)$t->id; ?>">
|
|
<?= htmlspecialchars($t->employee_code . ' - ' . $t->full_name, ENT_QUOTES, 'UTF-8'); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table id="tableTransferItems" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">No</th>
|
|
<th>Barcode</th>
|
|
<th>Nama Barang</th>
|
|
<th>Serial Number</th>
|
|
<th style="width:50px" class="text-center">
|
|
<div class="d-flex align-items-center justify-content-center gap-1">
|
|
<span class="small">Aksi</span>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="checkAll">
|
|
</div>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold text-muted small mb-1">To Teknisi</label>
|
|
<select class="form-select" id="teknisiTo">
|
|
<option value="">-- Pilih Teknisi Tujuan --</option>
|
|
<?php foreach ($teknisi_list as $t): ?>
|
|
<option value="<?= (int)$t->id; ?>">
|
|
<?= htmlspecialchars($t->employee_code . ' - ' . $t->full_name, ENT_QUOTES, 'UTF-8'); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<button class="btn btn-primary w-100 fw-semibold" id="btnSubmitTransfer">
|
|
<i class="bi bi-check2-circle me-1"></i> Submit Transfer
|
|
</button>
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- ============================================================ -->
|
|
<!-- RIGHT PANEL: Daftar Teknisi -->
|
|
<!-- ============================================================ -->
|
|
<div class="col-lg-7">
|
|
|
|
<div class="card tech-card">
|
|
<div class="card-header-custom d-flex align-items-center gap-2">
|
|
<i class="bi bi-people"></i>
|
|
Daftar Teknisi
|
|
</div>
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive">
|
|
<table id="tableTeknisi" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:50px">No</th>
|
|
<th>Nama Teknisi</th>
|
|
<th>Kode Karyawan</th>
|
|
<th>Departemen</th>
|
|
<th style="width:100px">Jumlah Item</th>
|
|
<th style="width:140px">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================ -->
|
|
<!-- MODAL DETAIL TEKNISI -->
|
|
<!-- ============================================================ -->
|
|
<div class="modal fade tech-modal" id="modalDetailTeknisi" tabindex="-1" data-bs-backdrop="static">
|
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><i class="bi bi-person-badge me-2"></i> Detail Teknisi</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
|
|
<!-- Teknisi Info -->
|
|
<div class="row g-2 mb-3" id="detailTeknisiInfo">
|
|
<div class="col-md-3">
|
|
<div class="teknisi-badge">
|
|
<small class="text-muted">Nama</small><br>
|
|
<strong id="detNama">-</strong>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="teknisi-badge">
|
|
<small class="text-muted">Kode Karyawan</small><br>
|
|
<strong id="detKode">-</strong>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="teknisi-badge">
|
|
<small class="text-muted">Jabatan</small><br>
|
|
<strong id="detJabatan">-</strong>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="teknisi-badge">
|
|
<small class="text-muted">Departemen</small><br>
|
|
<strong id="detDepartemen">-</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h6 class="fw-bold mb-2 mt-5"><i class="bi bi-box me-1"></i> Barang Bawaan</h6>
|
|
<div class="table-responsive">
|
|
<table id="tableDetailItems" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:50px">No</th>
|
|
<th>Tanggal</th>
|
|
<th>Barcode</th>
|
|
<th>Nama Barang</th>
|
|
<th>Serial Number</th>
|
|
<th>Jumlah</th>
|
|
<th class="text-center" style="width:100px">Status</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================ -->
|
|
<!-- MODAL FORM BARANG BAWAAN TEKNISI -->
|
|
<!-- ============================================================ -->
|
|
<div class="modal fade tech-modal" id="modalFormBarangBawaan" tabindex="-1" data-bs-backdrop="static">
|
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title"><i class="bi bi-file-earmark-text me-2"></i> Form Barang Bawaan Teknisi</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
|
|
<!-- Header Info -->
|
|
<div class="row g-2 mb-3" id="formBarangInfo">
|
|
<div class="col-md-12">
|
|
<div class="teknisi-badge">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<small class="text-muted">No. Faktur</small><br>
|
|
<strong id="fbNoFaktur">-</strong>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<small class="text-muted">Tanggal</small><br>
|
|
<select class="form-select form-select-sm d-inline-block" id="fbTanggalList" style="max-width:2000px">
|
|
<option value="">-- Pilih Tanggal --</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<small class="text-muted">Teknisi</small><br>
|
|
<strong id="fbTeknisi">-</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Data table -->
|
|
<h6 class="fw-bold mb-2 mt-5"><i class="bi bi-box me-1"></i> Barang Bawaan</h6>
|
|
<div class="table-responsive">
|
|
<table id="tableFormBarang" class="table table-tech table-hover table-striped align-middle w-100">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:50px">No</th>
|
|
<th style="width:85px">Tanggal</th>
|
|
<th>Barcode</th>
|
|
<th>Nama Barang</th>
|
|
<th>Serial Number</th>
|
|
<th style="width:100px">Jumlah</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" id="btnCetakPDF">
|
|
<i class="bi bi-file-pdf me-1"></i> PDF
|
|
</button>
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let kembalikanData = [];
|
|
let dibawaData = [];
|
|
let dtKembalikan, dtDibawa, dtTransferItems, dtTeknisi, dtDetailItems;
|
|
let activeScanInput = null;
|
|
|
|
$(function(){
|
|
|
|
// =============================================================
|
|
// MODE TOGGLE
|
|
// =============================================================
|
|
$('input[name="mode"]').change(function(){
|
|
$('.mode-section').addClass('d-none');
|
|
switch ($(this).val()) {
|
|
case 'kembalikan':
|
|
$('#sectionKembalikan').removeClass('d-none');
|
|
setTimeout(() => $('#scanKembalikan').focus(), 100);
|
|
break;
|
|
case 'dibawa':
|
|
$('#sectionDibawa').removeClass('d-none');
|
|
setTimeout(() => {
|
|
$('#teknisiDibawa').select2({width:'100%',placeholder:'-- Pilih Teknisi --'});
|
|
$('#scanDibawa').focus();
|
|
}, 100);
|
|
break;
|
|
case 'transfer':
|
|
$('#sectionTransfer').removeClass('d-none');
|
|
setTimeout(() => {
|
|
$('#teknisiFrom').select2({width:'100%',placeholder:'-- Pilih Teknisi Asal --'});
|
|
$('#teknisiTo').select2({width:'100%',placeholder:'-- Pilih Teknisi Tujuan --'});
|
|
$('#teknisiFrom').off('.transfer').on('change.transfer select2:select.transfer', function(){
|
|
loadTransferItems();
|
|
});
|
|
loadTransferItems();
|
|
}, 100);
|
|
break;
|
|
}
|
|
});
|
|
|
|
$('#teknisiDibawa').select2({width:'100%',placeholder:'-- Pilih Teknisi --'});
|
|
|
|
|
|
// =============================================================
|
|
// INIT LEFT TABLES
|
|
// =============================================================
|
|
|
|
dtKembalikan = $('#tableKembalikan').DataTable({
|
|
data: kembalikanData,
|
|
columns: [
|
|
{ data: 'no' },
|
|
{ data: 'barcode' },
|
|
{ data: 'nama_barang' },
|
|
{ data: 'serial_number' },
|
|
{ data: 'teknisi' },
|
|
{ data: 'aksi', orderable: false }
|
|
],
|
|
// language: { url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json" },
|
|
pageLength: 5,
|
|
lengthMenu: [[5, 10, 25, -1], [5, 10, 25, 'All']]
|
|
});
|
|
|
|
dtDibawa = $('#tableDibawa').DataTable({
|
|
data: dibawaData,
|
|
columns: [
|
|
{ data: 'no' },
|
|
{ data: 'barcode' },
|
|
{ data: 'nama_barang' },
|
|
{ data: 'serial_number' },
|
|
{ data: 'aksi', orderable: false }
|
|
],
|
|
// language: { url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json" },
|
|
pageLength: 5,
|
|
lengthMenu: [[5, 10, 25, -1], [5, 10, 25, 'All']]
|
|
});
|
|
|
|
dtTransferItems = $('#tableTransferItems').DataTable({
|
|
columns: [
|
|
{ data: 0 },
|
|
{ data: 1 },
|
|
{ data: 2 },
|
|
{ data: 3 },
|
|
{
|
|
data: null,
|
|
orderable: false,
|
|
searchable: false,
|
|
className: 'text-center',
|
|
defaultContent: '',
|
|
render: function(data, type, row) {
|
|
if (type !== 'display') return data;
|
|
return '<div class="form-check"><input class="form-check-input checkbox-item" type="checkbox" data-barcode="' + row[1] + '"></div>';
|
|
}
|
|
}
|
|
],
|
|
language: {
|
|
// url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json",
|
|
emptyTable: 'Pilih teknisi asal terlebih dahulu'
|
|
},
|
|
pageLength: 5,
|
|
lengthMenu: [[5, 10, 25, -1], [5, 10, 25, 'All']],
|
|
drawCallback: function() {
|
|
$('#tableTransferItems tbody input:checkbox:not(#checkAll)').each(function(){
|
|
let barcode = $(this).data('barcode');
|
|
if (window._checkedBarcodes && window._checkedBarcodes.indexOf(barcode) >= 0) {
|
|
$(this).prop('checked', true);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// =============================================================
|
|
// RIGHT PANEL: DAFTAR TEKNISI (server-side)
|
|
// =============================================================
|
|
|
|
dtTeknisi = $('#tableTeknisi').DataTable({
|
|
processing: true,
|
|
serverSide: true,
|
|
ajax: {
|
|
url: "<?= base_url('teknisi/get_teknisi_table'); ?>",
|
|
type: "GET"
|
|
},
|
|
columns: [
|
|
{ data: 0 },
|
|
{ data: 1 },
|
|
{ data: 2 },
|
|
{ data: 3 },
|
|
{ data: 4, className: 'text-center' },
|
|
{ data: 5, className: 'text-center', orderable: false }
|
|
],
|
|
order: [[1, 'asc']],
|
|
// language: { url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json" },
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, 'All']]
|
|
});
|
|
|
|
// =============================================================
|
|
// MODAL DETAIL TEKNISI - Items Table (initialized on demand)
|
|
// =============================================================
|
|
|
|
$(document).on('click', '.btn-detail-teknisi', function(){
|
|
let userId = $(this).data('id');
|
|
openDetailTeknisi(userId);
|
|
});
|
|
|
|
function openDetailTeknisi(userId) {
|
|
// Reset info
|
|
$('#detNama').text('-');
|
|
$('#detKode').text('-');
|
|
$('#detJabatan').text('-');
|
|
$('#detDepartemen').text('-');
|
|
|
|
// Load teknisi info
|
|
$.get("<?= base_url('teknisi/teknisi_detail'); ?>", {user_id: userId}, function(r){
|
|
if (r) {
|
|
$('#detNama').text(r.full_name || '-');
|
|
$('#detKode').text(r.employee_code || '-');
|
|
$('#detJabatan').text(r.position_name || '-');
|
|
$('#detDepartemen').text(r.department_name || '-');
|
|
}
|
|
}, 'json');
|
|
|
|
// Init / reload items DataTable
|
|
if (dtDetailItems) {
|
|
dtDetailItems.destroy();
|
|
}
|
|
|
|
dtDetailItems = $('#tableDetailItems').DataTable({
|
|
processing: true,
|
|
serverSide: true,
|
|
ajax: {
|
|
url: "<?= base_url('teknisi/get_teknisi_items'); ?>",
|
|
type: "GET",
|
|
data: function(d) {
|
|
d.user_id = userId;
|
|
}
|
|
},
|
|
columns: [
|
|
{ data: 0 },
|
|
{ data: 1 },
|
|
{ data: 2 },
|
|
{ data: 3 },
|
|
{ data: 4 },
|
|
{ data: 5 },
|
|
{ data: 6, className: 'text-center' }
|
|
],
|
|
order: [[1, 'desc']],
|
|
// language: { url: "//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json" },
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, 'All']]
|
|
});
|
|
|
|
$('#modalDetailTeknisi').modal('show');
|
|
}
|
|
|
|
// =============================================================
|
|
// FORM BARANG BAWAAN TEKNISI
|
|
// =============================================================
|
|
|
|
let dtFormBarang;
|
|
let _formBarangUserId = null;
|
|
|
|
function loadListTanggal(userId) {
|
|
$.get("<?= base_url('teknisi/get_date_by_employee_id'); ?>", {user_id: userId}, function(r){
|
|
if (!r.status) {
|
|
Swal.fire({icon:'error', text:r.message});
|
|
return;
|
|
}
|
|
|
|
let opt='<option value="">-- Pilih Tanggal --</option><option value="all">ALL</option>';
|
|
r.data.forEach(d=>{
|
|
let parts = d.tanggal.split('-');
|
|
let display = parts[2] + '/' + parts[1] + '/' + parts[0];
|
|
opt += `<option value="${d.tanggal}">${display}</option>`;
|
|
});
|
|
$('#fbTanggalList').html(opt);
|
|
}, 'json');
|
|
}
|
|
|
|
function loadFormBarangData() {
|
|
let tanggalVal = $('#fbTanggalList').val();
|
|
|
|
if (!tanggalVal) {
|
|
$('#fbNoFaktur').text('Memuat...');
|
|
if (dtFormBarang) {
|
|
dtFormBarang.clear().draw();
|
|
}
|
|
return;
|
|
}
|
|
|
|
$.get("<?= base_url('teknisi/get_form_barang_bawaan_data'); ?>", {user_id: _formBarangUserId, tanggal: tanggalVal}, function(r){
|
|
if (!r.status) {
|
|
Swal.fire({icon:'error', text:r.message});
|
|
return;
|
|
}
|
|
|
|
let d = r.data;
|
|
$('#fbNoFaktur').text(d.no_faktur);
|
|
|
|
if (dtFormBarang) {
|
|
dtFormBarang.destroy();
|
|
}
|
|
|
|
dtFormBarang = $('#tableFormBarang').DataTable({
|
|
data: d.items,
|
|
columns: [
|
|
{ data: 'no' },
|
|
{ data: 'tanggal' },
|
|
{ data: 'barcode' },
|
|
{ data: 'nama_barang' },
|
|
{ data: 'serial_number' },
|
|
{ data: 'jumlah', className: 'text-center' }
|
|
],
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, 'All']],
|
|
order: []
|
|
});
|
|
}, 'json');
|
|
}
|
|
|
|
$('#fbTanggalList').on('change', function() {
|
|
loadFormBarangData();
|
|
});
|
|
|
|
$(document).on('click', '.btn-form-barang-bawaan', function(){
|
|
let userId = $(this).data('id');
|
|
let nama = $(this).data('nama');
|
|
_formBarangUserId = userId;
|
|
|
|
$('#fbNoFaktur').text('Memuat...');
|
|
$('#fbTanggalList').val('');
|
|
$('#fbTeknisi').text(nama);
|
|
|
|
if (!dtFormBarang) {
|
|
dtFormBarang = $('#tableFormBarang').DataTable({
|
|
data: [],
|
|
columns: [
|
|
{ data: 'no' },
|
|
{ data: 'tanggal' },
|
|
{ data: 'barcode' },
|
|
{ data: 'nama_barang' },
|
|
{ data: 'serial_number' },
|
|
{ data: 'jumlah', className: 'text-center' }
|
|
],
|
|
pageLength: 10,
|
|
lengthMenu: [[10, 25, 50, -1], [10, 25, 50, 'All']],
|
|
order: [],
|
|
language: {
|
|
emptyTable: "No data available"
|
|
}
|
|
});
|
|
} else {
|
|
dtFormBarang.clear().draw();
|
|
}
|
|
|
|
loadListTanggal(userId);
|
|
|
|
$('#modalFormBarangBawaan').modal('show');
|
|
});
|
|
|
|
$('#btnCetakPDF').click(function(){
|
|
if (_formBarangUserId) {
|
|
let tanggalVal = $('#fbTanggalList').val();
|
|
let url = "<?= base_url('teknisi/generate_pdf_barang_bawaan/'); ?>" + _formBarangUserId + '?tanggal=' + encodeURIComponent(tanggalVal);
|
|
window.open(url, '_blank');
|
|
}
|
|
});
|
|
|
|
// =============================================================
|
|
// SCAN: MODE KEMBALIKAN
|
|
// =============================================================
|
|
|
|
$('#scanKembalikan').keypress(function(e){
|
|
if (e.which == 13) scanKembalikan();
|
|
});
|
|
|
|
let html5QrCode = null;
|
|
let lastScannerMode = null;
|
|
|
|
$('#btnCamKembalikan').click(function(){
|
|
activeScanInput = 'kembalikan';
|
|
lastScannerMode = 'kembalikan';
|
|
openScanner();
|
|
});
|
|
|
|
function openScanner() {
|
|
let mode = activeScanInput === 'kembalikan' ? 'Kembalikan' : 'Dibawa';
|
|
$('#scannerArea' + mode).hide();
|
|
$('#cameraArea').show();
|
|
|
|
if (html5QrCode) {
|
|
html5QrCode = null;
|
|
}
|
|
|
|
html5QrCode = new Html5Qrcode("reader");
|
|
html5QrCode.start(
|
|
{ facingMode: "environment" },
|
|
{ fps: 10, qrbox: 220 },
|
|
function(decodedText) {
|
|
html5QrCode.stop().then(function(){
|
|
$('#cameraArea').hide();
|
|
$('#scannerArea' + mode).show();
|
|
if (activeScanInput === 'kembalikan') {
|
|
$('#scanKembalikan').val(decodedText);
|
|
scanKembalikan();
|
|
} else {
|
|
$('#scanDibawa').val(decodedText);
|
|
scanDibawa();
|
|
}
|
|
activeScanInput = null;
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
$('#btnCloseCamera').click(function(){
|
|
if (html5QrCode) {
|
|
let mode = lastScannerMode === 'kembalikan' ? 'Kembalikan' : 'Dibawa';
|
|
html5QrCode.stop().then(function(){
|
|
$('#cameraArea').hide();
|
|
$('#scannerArea' + mode).show();
|
|
$('#' + (lastScannerMode === 'kembalikan' ? 'scanKembalikan' : 'scanDibawa')).focus();
|
|
activeScanInput = null;
|
|
lastScannerMode = null;
|
|
});
|
|
}
|
|
});
|
|
|
|
// Close camera when mode changes
|
|
let _modeChange = $('input[name="mode"]').change(function(){
|
|
if (html5QrCode) {
|
|
let currentMode = $(this).val();
|
|
html5QrCode.stop().then(function(){
|
|
$('#cameraArea').hide();
|
|
if (currentMode === 'kembalikan' || currentMode === 'dibawa') {
|
|
let cap = currentMode === 'kembalikan' ? 'Kembalikan' : 'Dibawa';
|
|
$('#scannerArea' + cap).show();
|
|
}
|
|
activeScanInput = null;
|
|
lastScannerMode = null;
|
|
});
|
|
}
|
|
});
|
|
|
|
function scanKembalikan() {
|
|
let barcode = $('#scanKembalikan').val().trim();
|
|
if (!barcode) return;
|
|
|
|
if (kembalikanData.some(d => d.barcode == barcode)) {
|
|
Swal.fire({icon:'warning', text:'Barcode sudah ditambahkan'});
|
|
$('#scanKembalikan').val('').focus();
|
|
return;
|
|
}
|
|
|
|
$.get("<?= base_url('teknisi/scan_item'); ?>", {barcode: barcode}, function(r){
|
|
if (!r.status) {
|
|
Swal.fire({icon:'error', text:r.message});
|
|
$('#scanKembalikan').val('').focus();
|
|
return;
|
|
}
|
|
|
|
let data = r.data;
|
|
|
|
if (!data.teknisi_name) {
|
|
Swal.fire({icon:'warning', text:'Barang tidak sedang dibawa teknisi manapun'});
|
|
$('#scanKembalikan').val('').focus();
|
|
return;
|
|
}
|
|
|
|
let teknisiText = data.teknisi_code + ' - ' + data.teknisi_name;
|
|
let no = kembalikanData.length + 1;
|
|
|
|
kembalikanData.push({
|
|
no: no,
|
|
barcode: data.barcode,
|
|
nama_barang: data.nama_barang,
|
|
serial_number: data.serial_number || '-',
|
|
teknisi: teknisiText,
|
|
aksi: '<button class="btn btn-outline-danger btn-sm-icon delete-kembalikan" data-barcode="'+data.barcode+'"><i class="bi bi-trash"></i></button>'
|
|
});
|
|
|
|
refreshTable(dtKembalikan, kembalikanData);
|
|
$('#scanKembalikan').val('').focus();
|
|
Swal.fire({icon:'success', text:'Barang ditambahkan ke daftar pengembalian', timer:1200, showConfirmButton:false});
|
|
}, 'json');
|
|
}
|
|
|
|
// =============================================================
|
|
// SCAN: MODE DIBAWA
|
|
// =============================================================
|
|
|
|
$('#scanDibawa').keypress(function(e){
|
|
if (e.which == 13) scanDibawa();
|
|
});
|
|
|
|
$('#btnCamDibawa').click(function(){
|
|
activeScanInput = 'dibawa';
|
|
lastScannerMode = 'dibawa';
|
|
openScanner();
|
|
});
|
|
|
|
function scanDibawa() {
|
|
let barcode = $('#scanDibawa').val().trim();
|
|
if (!barcode) return;
|
|
|
|
if (dibawaData.some(d => d.barcode == barcode)) {
|
|
Swal.fire({icon:'warning', text:'Barcode sudah ditambahkan'});
|
|
$('#scanDibawa').val('').focus();
|
|
return;
|
|
}
|
|
|
|
$.get("<?= base_url('teknisi/scan_item'); ?>", {barcode: barcode}, function(r){
|
|
if (!r.status) {
|
|
Swal.fire({icon:'error', text:r.message});
|
|
$('#scanDibawa').val('').focus();
|
|
return;
|
|
}
|
|
|
|
if (r.data.teknisi_name) {
|
|
Swal.fire({icon:'warning', text:'Barang sedang dibawa ' + r.data.teknisi_code + ' - ' + r.data.teknisi_name});
|
|
$('#scanDibawa').val('').focus();
|
|
return;
|
|
}
|
|
|
|
if (r.data.barcode_status === 'sold_out') {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Barang Tidak Dapat Dibawa',
|
|
text: 'Barcode ' + r.data.barcode + ' sudah berstatus SOLD OUT sehingga tidak dapat diproses.'
|
|
});
|
|
$('#scanDibawa').val('').focus();
|
|
return;
|
|
}
|
|
|
|
let data = r.data;
|
|
let no = dibawaData.length + 1;
|
|
|
|
dibawaData.push({
|
|
no: no,
|
|
barcode: data.barcode,
|
|
nama_barang: data.nama_barang,
|
|
serial_number: data.serial_number || '-',
|
|
aksi: '<button class="btn btn-outline-danger btn-sm-icon delete-dibawa" data-barcode="'+data.barcode+'"><i class="bi bi-trash"></i></button>'
|
|
});
|
|
|
|
refreshTable(dtDibawa, dibawaData);
|
|
$('#scanDibawa').val('').focus();
|
|
Swal.fire({icon:'success', text:'Barang ditambahkan ke daftar bawaan', timer:1200, showConfirmButton:false});
|
|
}, 'json');
|
|
}
|
|
|
|
// =============================================================
|
|
// DELETE ROWS
|
|
// =============================================================
|
|
|
|
$(document).on('click', '.delete-kembalikan', function(){
|
|
let barcode = $(this).data('barcode');
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Hapus Data?',
|
|
text: 'Yakin ingin menghapus item ini dari daftar pengembalian?',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc3545',
|
|
confirmButtonText: 'Ya, Hapus',
|
|
cancelButtonColor: '#6c757d',
|
|
cancelButtonText: 'Batal',
|
|
reverseButtons: true
|
|
}).then(result => {
|
|
if (!result.isConfirmed) return;
|
|
kembalikanData = kembalikanData.filter(d => d.barcode != barcode);
|
|
refreshTable(dtKembalikan, renumber(kembalikanData));
|
|
Swal.fire({icon:'success', title:'Berhasil', text:'Item berhasil dihapus dari daftar.', timer:1200, showConfirmButton:false});
|
|
});
|
|
});
|
|
|
|
$(document).on('click', '.delete-dibawa', function(){
|
|
let barcode = $(this).data('barcode');
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Hapus Data?',
|
|
text: 'Yakin ingin menghapus item ini dari daftar bawaan?',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc3545',
|
|
confirmButtonText: 'Ya, Hapus',
|
|
cancelButtonColor: '#6c757d',
|
|
cancelButtonText: 'Batal',
|
|
reverseButtons: true
|
|
}).then(result => {
|
|
if (!result.isConfirmed) return;
|
|
dibawaData = dibawaData.filter(d => d.barcode != barcode);
|
|
refreshTable(dtDibawa, renumber(dibawaData));
|
|
Swal.fire({icon:'success', title:'Berhasil', text:'Item berhasil dihapus dari daftar.', timer:1200, showConfirmButton:false});
|
|
});
|
|
});
|
|
|
|
// =============================================================
|
|
// LOAD TRANSFER ITEMS (on From Teknisi change)
|
|
// =============================================================
|
|
|
|
function loadTransferItems() {
|
|
let userId = $('#teknisiFrom').val();
|
|
// console.log('[loadTransferItems] userId:', userId);
|
|
if (!userId) {
|
|
dtTransferItems.clear().draw();
|
|
return;
|
|
}
|
|
|
|
let url = "<?= base_url('teknisi/get_data'); ?>";
|
|
// console.log('[loadTransferItems] GET', url, {user_id: userId, status: 'active'});
|
|
|
|
$.ajax({
|
|
url: url,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {user_id: userId, status: 'active'},
|
|
success: function(r){
|
|
// console.log('[loadTransferItems] response:', r);
|
|
let rows = r.data || [];
|
|
|
|
window._checkedBarcodes = [];
|
|
dtTransferItems.clear();
|
|
dtTransferItems.rows.add(rows).draw();
|
|
},
|
|
error: function(jqXHR, textStatus, errorThrown){
|
|
console.error('[loadTransferItems] AJAX fail:', textStatus, errorThrown, jqXHR.responseText);
|
|
Swal.fire({icon:'error', text:'Gagal memuat data barang teknisi'});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Checkbox select all
|
|
$(document).on('change', '#checkAll', function(){
|
|
let checked = $(this).prop('checked');
|
|
$('#tableTransferItems tbody .checkbox-item').prop('checked', checked);
|
|
updateCheckedBarcodes();
|
|
});
|
|
|
|
$(document).on('change', '.checkbox-item', function(){
|
|
updateCheckedBarcodes();
|
|
let all = $('#tableTransferItems tbody .checkbox-item').length;
|
|
let chk = $('#tableTransferItems tbody .checkbox-item:checked').length;
|
|
$('#checkAll').prop('checked', all > 0 && all == chk);
|
|
});
|
|
|
|
function updateCheckedBarcodes() {
|
|
window._checkedBarcodes = [];
|
|
$('#tableTransferItems tbody .checkbox-item:checked').each(function(){
|
|
window._checkedBarcodes.push($(this).data('barcode'));
|
|
});
|
|
}
|
|
|
|
// =============================================================
|
|
// SUBMIT: TRANSFER
|
|
// =============================================================
|
|
|
|
$('#btnSubmitTransfer').click(function(){
|
|
let fromUserId = $('#teknisiFrom').val();
|
|
let toUserId = $('#teknisiTo').val();
|
|
|
|
if (!fromUserId) {
|
|
Swal.fire({icon:'warning', title:'Teknisi Asal', text:'Pilih teknisi asal'});
|
|
return;
|
|
}
|
|
|
|
if (!toUserId) {
|
|
Swal.fire({icon:'warning', title:'Teknisi Tujuan', text:'Pilih teknisi tujuan'});
|
|
return;
|
|
}
|
|
|
|
if (fromUserId == toUserId) {
|
|
Swal.fire({icon:'warning', title:'Sama', text:'Teknisi tujuan tidak boleh sama dengan teknisi asal'});
|
|
return;
|
|
}
|
|
|
|
let barcodes = window._checkedBarcodes || [];
|
|
if (barcodes.length == 0) {
|
|
Swal.fire({icon:'warning', title:'Tidak ada barang', text:'Pilih minimal 1 barang yang akan ditransfer'});
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: 'Konfirmasi Transfer',
|
|
html: barcodes.length + ' barang akan ditransfer ke teknisi<br>' + ($('#teknisiTo option:selected').text() || ''),
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#007bff',
|
|
confirmButtonText: 'Ya, Transfer',
|
|
cancelButtonText: 'Batal'
|
|
}).then(result => {
|
|
if (!result.isConfirmed) return;
|
|
|
|
// console.log('[Transfer] submitting', barcodes.length, 'items, from_user:', fromUserId, 'to_user:', toUserId);
|
|
submitBatch('batch_transfer', {
|
|
barcodes: barcodes,
|
|
from_user_id: fromUserId,
|
|
to_user_id: toUserId
|
|
}, function(){
|
|
window._checkedBarcodes = [];
|
|
$('#checkAll').prop('checked', false);
|
|
loadTransferItems();
|
|
dtTeknisi.ajax.reload(null, false);
|
|
});
|
|
});
|
|
});
|
|
|
|
// =============================================================
|
|
// SUBMIT: KEMBALIKAN
|
|
// =============================================================
|
|
|
|
$('#btnSubmitKembalikan').click(function(){
|
|
if (kembalikanData.length == 0) {
|
|
Swal.fire({icon:'warning', title:'Tidak ada barang', text:'Scan minimal 1 barcode terlebih dahulu'});
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: 'Konfirmasi Pengembalian',
|
|
text: kembalikanData.length + ' barang akan dikembalikan',
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#dc3545',
|
|
confirmButtonText: 'Ya, Kembalikan',
|
|
cancelButtonText: 'Batal'
|
|
}).then(result => {
|
|
if (!result.isConfirmed) return;
|
|
|
|
let barcodes = kembalikanData.map(d => d.barcode);
|
|
// console.log('[Kembalikan] submitting', barcodes.length, 'items:', barcodes);
|
|
submitBatch('batch_kembalikan', {barcodes: barcodes}, function(){
|
|
kembalikanData = [];
|
|
refreshTable(dtKembalikan, []);
|
|
$('#scanKembalikan').focus();
|
|
dtTeknisi.ajax.reload(null, false);
|
|
});
|
|
});
|
|
});
|
|
|
|
// =============================================================
|
|
// SUBMIT: DIBAWA
|
|
// =============================================================
|
|
|
|
$('#btnSubmitDibawa').click(function(){
|
|
let userId = $('#teknisiDibawa').val();
|
|
|
|
if (!userId) {
|
|
Swal.fire({icon:'warning', title:'Pilih Teknisi', text:'Pilih teknisi terlebih dahulu'});
|
|
return;
|
|
}
|
|
|
|
if (dibawaData.length == 0) {
|
|
Swal.fire({icon:'warning', title:'Tidak ada barang', text:'Scan minimal 1 barcode terlebih dahulu'});
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: 'Konfirmasi Penugasan',
|
|
html: dibawaData.length + ' barang akan ditugaskan ke teknisi<br>' + ($('#teknisiDibawa option:selected').text() || ''),
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#28a745',
|
|
confirmButtonText: 'Ya, Tugaskan',
|
|
cancelButtonText: 'Batal'
|
|
}).then(result => {
|
|
if (!result.isConfirmed) return;
|
|
|
|
let barcodes = dibawaData.map(d => d.barcode);
|
|
// console.log('[Dibawa] submitting', barcodes.length, 'items to user_id:', userId, 'barcodes:', barcodes);
|
|
submitBatch('batch_dibawa', {barcodes: barcodes, user_id: userId}, function(){
|
|
dibawaData = [];
|
|
refreshTable(dtDibawa, []);
|
|
$('#scanDibawa').focus();
|
|
dtTeknisi.ajax.reload(null, false);
|
|
});
|
|
});
|
|
});
|
|
|
|
// =============================================================
|
|
// UTILITY FUNCTIONS
|
|
// =============================================================
|
|
|
|
function submitBatch(endpoint, data, onSuccess) {
|
|
let mode = endpoint.replace('batch_', '');
|
|
let btnId = 'btnSubmit' + mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
let btn = $('#' + btnId);
|
|
let originalText = btn.data('original-text') || btn.html();
|
|
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span> Memproses...');
|
|
|
|
// console.log('[submitBatch] endpoint:', endpoint, 'payload:', JSON.stringify(data));
|
|
|
|
$.ajax({
|
|
url: "<?= base_url('teknisi/'); ?>" + endpoint,
|
|
type: "POST",
|
|
dataType: "json",
|
|
data: data,
|
|
traditional: false,
|
|
success: function(r) {
|
|
// console.log('[submitBatch] response:', endpoint, r);
|
|
btn.prop('disabled', false).html(originalText);
|
|
|
|
if (r.status) {
|
|
Swal.fire({icon:'success', text:r.message, timer:2000, showConfirmButton:false});
|
|
if (onSuccess) onSuccess();
|
|
} else {
|
|
let errMsg = r.message;
|
|
if (r.debug) errMsg += '<br><small class="text-muted">' + r.debug + '</small>';
|
|
Swal.fire({icon:'error', html:errMsg});
|
|
}
|
|
},
|
|
error: function(jqXHR, textStatus, errorThrown) {
|
|
console.error('[submitBatch] error:', endpoint, textStatus, errorThrown, jqXHR.responseText);
|
|
btn.prop('disabled', false).html(originalText);
|
|
Swal.fire({icon:'error', text:'Terjadi kesalahan server'});
|
|
}
|
|
});
|
|
}
|
|
|
|
function refreshTable(dt, data) {
|
|
let reindexed = renumber(data);
|
|
dt.clear();
|
|
dt.rows.add(reindexed).draw();
|
|
}
|
|
|
|
function renumber(arr) {
|
|
return arr.map((d, i) => ({...d, no: i + 1}));
|
|
}
|
|
|
|
// Store original button text
|
|
$('#btnSubmitKembalikan, #btnSubmitDibawa, #btnSubmitTransfer').each(function(){
|
|
$(this).data('original-text', $(this).html());
|
|
});
|
|
|
|
});
|
|
</script>
|