add backup file and autobackup code, partial update mutations receive on transation page
This commit is contained in:
@@ -108,6 +108,62 @@ use Illuminate\Support\Facades\Auth;
|
||||
.available-stock-mutasi {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Styles for receive mutations table */
|
||||
#receiveMutationsTable {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#receiveMutationsTable th {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#receiveMutationsTable td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn-detail {
|
||||
font-size: 12px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
font-size: 11px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mutation-detail-table {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mutation-detail-table th {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.quantity-approved-input {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.quantity-approved-input.is-invalid {
|
||||
border-color: #dc3545;
|
||||
background-color: #fff5f5;
|
||||
}
|
||||
|
||||
.mutation-detail-table textarea {
|
||||
font-size: 12px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.mutation-detail-table input {
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@@ -487,6 +543,9 @@ use Illuminate\Support\Facades\Auth;
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#mutasi">Mutasi</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#penerimaan">Penerimaan Mutasi</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content mt-3">
|
||||
@@ -655,6 +714,30 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Tab Penerimaan Mutasi -->
|
||||
<div class="tab-pane" id="penerimaan" role="tabpanel">
|
||||
<div class="mt-3">
|
||||
<h6 class="mb-3">Daftar Mutasi yang Perlu Diterima</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover" id="receiveMutationsTable">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="20%">No. Mutasi</th>
|
||||
<th width="25%">Dealer Asal</th>
|
||||
<th width="15%">Status</th>
|
||||
<th width="10%">Total Item</th>
|
||||
<th width="15%">Tanggal</th>
|
||||
<th width="15%">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Data will be loaded via DataTables AJAX -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -668,6 +751,37 @@ use Illuminate\Support\Facades\Auth;
|
||||
<input type="hidden" name="dealer_id" value="{{ $mechanic->dealer_id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Detail Mutasi -->
|
||||
<div class="modal fade" id="mutationDetailModal" tabindex="-1" role="dialog" aria-labelledby="mutationDetailModalLabel">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="mutationDetailModalLabel">Detail & Penerimaan Mutasi</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="receiveMutationForm" action="" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div id="mutationDetailContent">
|
||||
<div class="text-center">
|
||||
<i class="fa fa-spinner fa-spin fa-2x"></i>
|
||||
<p class="mt-2">Memuat data...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Tutup</button>
|
||||
<button type="submit" class="btn btn-success" id="receiveButton" style="display: none;">
|
||||
<i class="fa fa-check"></i> Terima Mutasi
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('javascripts')
|
||||
@@ -1479,6 +1593,277 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
||||
|
||||
// Initialize DataTable for receive mutations
|
||||
var receiveMutationsTable;
|
||||
|
||||
function initReceiveMutationsTable() {
|
||||
if (receiveMutationsTable) {
|
||||
receiveMutationsTable.destroy();
|
||||
}
|
||||
|
||||
receiveMutationsTable = $('#receiveMutationsTable').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
ajax: {
|
||||
url: '{{ route("mutations.get-pending-mutations") }}',
|
||||
data: {
|
||||
dealer_id: {{ $mechanic->dealer_id }}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{data: 'mutation_number', name: 'mutation_number'},
|
||||
{data: 'from_dealer', name: 'from_dealer'},
|
||||
{data: 'status', name: 'status', orderable: false},
|
||||
{data: 'total_items', name: 'total_items'},
|
||||
{data: 'created_at', name: 'created_at'},
|
||||
{data: 'action', name: 'action', orderable: false, searchable: false}
|
||||
],
|
||||
pageLength: 10,
|
||||
responsive: true,
|
||||
scrollX: true
|
||||
});
|
||||
}
|
||||
|
||||
// Show mutation detail modal
|
||||
function showMutationDetail(mutationId) {
|
||||
$('#mutationDetailModal').modal('show');
|
||||
$('#mutationDetailContent').html(`
|
||||
<div class="text-center">
|
||||
<i class="fa fa-spinner fa-spin fa-2x"></i>
|
||||
<p class="mt-2">Memuat data...</p>
|
||||
</div>
|
||||
`);
|
||||
$('#receiveButton').hide();
|
||||
|
||||
// Load mutation detail via AJAX
|
||||
$.ajax({
|
||||
url: '{{ route("mutations.get-detail", ":id") }}'.replace(':id', mutationId),
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
renderMutationDetail(response.data);
|
||||
} else {
|
||||
$('#mutationDetailContent').html(`
|
||||
<div class="alert alert-danger">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
${response.message || 'Gagal memuat detail mutasi'}
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
$('#mutationDetailContent').html(`
|
||||
<div class="alert alert-danger">
|
||||
<i class="fa fa-exclamation-triangle"></i>
|
||||
Terjadi kesalahan saat memuat data
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Render mutation detail in modal
|
||||
function renderMutationDetail(mutation) {
|
||||
var statusColor = mutation.status_color;
|
||||
var statusLabel = mutation.status_label;
|
||||
|
||||
// Set form action URL
|
||||
$('#receiveMutationForm').attr('action', '{{ route("mutations.receive", ":id") }}'.replace(':id', mutation.id));
|
||||
|
||||
// Build detail HTML
|
||||
var detailHtml = `
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<strong>No. Mutasi:</strong><br>
|
||||
${mutation.mutation_number}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<strong>Status:</strong><br>
|
||||
<span class="font-weight-bold text-${statusColor}">${statusLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<strong>Dealer Asal:</strong><br>
|
||||
${mutation.from_dealer.name}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<strong>Tanggal:</strong><br>
|
||||
${mutation.created_at_formatted}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<strong>Diminta oleh:</strong><br>
|
||||
${mutation.requested_by ? mutation.requested_by.name : '-'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<label for="mutationNotes"><strong>Catatan Penerimaan:</strong></label>
|
||||
<textarea name="notes" id="mutationNotes" class="form-control" rows="3" placeholder="Masukkan catatan jika diperlukan..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="mb-3">Detail Produk & Penerimaan:</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered mutation-detail-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="30%">Produk</th>
|
||||
<th width="15%" class="text-center">Qty Diminta</th>
|
||||
<th width="20%" class="text-center">Qty Disetujui</th>
|
||||
<th width="35%">Catatan Produk</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
|
||||
// Add product details with form inputs
|
||||
if (mutation.mutation_details && mutation.mutation_details.length > 0) {
|
||||
mutation.mutation_details.forEach(function(detail) {
|
||||
detailHtml += `
|
||||
<tr>
|
||||
<td>${detail.product.name}</td>
|
||||
<td class="text-center">
|
||||
<span class="font-weight-bold text-info">${parseFloat(detail.quantity_requested).toFixed(2)}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number"
|
||||
name="products[${detail.id}][quantity_approved]"
|
||||
class="form-control quantity-approved-input"
|
||||
min="0"
|
||||
max="${detail.quantity_requested}"
|
||||
step="0.01"
|
||||
value="${detail.quantity_requested}"
|
||||
data-max="${detail.quantity_requested}"
|
||||
placeholder="0.00">
|
||||
</td>
|
||||
<td>
|
||||
<textarea name="products[${detail.id}][notes]"
|
||||
class="form-control"
|
||||
rows="2"
|
||||
placeholder="Catatan untuk produk ini..."></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
} else {
|
||||
detailHtml += `
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">Tidak ada detail produk</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
|
||||
detailHtml += `
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
<strong>Petunjuk:</strong>
|
||||
Masukkan quantity yang disetujui untuk setiap produk. Quantity tidak boleh melebihi quantity yang diminta.
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('#mutationDetailContent').html(detailHtml);
|
||||
|
||||
// Show receive button if mutation can be received
|
||||
if (mutation.can_be_received) {
|
||||
$('#receiveButton').show();
|
||||
}
|
||||
|
||||
// Add validation for quantity inputs
|
||||
$('.quantity-approved-input').on('input', function() {
|
||||
var value = parseFloat($(this).val()) || 0;
|
||||
var max = parseFloat($(this).data('max')) || 0;
|
||||
|
||||
if (value > max) {
|
||||
$(this).addClass('is-invalid');
|
||||
if (!$(this).siblings('.invalid-feedback').length) {
|
||||
$(this).after('<div class="invalid-feedback">Quantity tidak boleh melebihi quantity yang diminta</div>');
|
||||
}
|
||||
} else {
|
||||
$(this).removeClass('is-invalid');
|
||||
$(this).siblings('.invalid-feedback').remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle receive form submission
|
||||
$('#receiveMutationForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Validate form
|
||||
var hasInvalidInput = $('.quantity-approved-input.is-invalid').length > 0;
|
||||
if (hasInvalidInput) {
|
||||
Swal.fire({
|
||||
type: 'error',
|
||||
title: 'Validasi Gagal',
|
||||
text: 'Perbaiki quantity yang tidak valid sebelum melanjutkan'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if at least one product has quantity approved > 0
|
||||
var hasApprovedQuantity = false;
|
||||
$('.quantity-approved-input').each(function() {
|
||||
if (parseFloat($(this).val()) > 0) {
|
||||
hasApprovedQuantity = true;
|
||||
return false; // break loop
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasApprovedQuantity) {
|
||||
Swal.fire({
|
||||
type: 'warning',
|
||||
title: 'Peringatan',
|
||||
text: 'Minimal satu produk harus memiliki quantity yang disetujui'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof Swal !== 'undefined') {
|
||||
Swal.fire({
|
||||
title: 'Terima Mutasi?',
|
||||
text: "Mutasi akan diterima dengan quantity dan catatan yang telah Anda masukkan",
|
||||
type: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#28a745',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Ya, Terima',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
// Set loading state
|
||||
$('#receiveButton').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Memproses...');
|
||||
|
||||
// Submit form
|
||||
this.submit();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (confirm('Terima mutasi dengan data yang telah dimasukkan?')) {
|
||||
$('#receiveButton').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Memproses...');
|
||||
this.submit();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize table when tab is shown
|
||||
$('a[href="#penerimaan"]').on('shown.bs.tab', function (e) {
|
||||
setTimeout(function() {
|
||||
initReceiveMutationsTable();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function createTransaction(form) {
|
||||
let work_ids;
|
||||
if(form == 'work') {
|
||||
|
||||
Reference in New Issue
Block a user