fix edit products using new workflow mutations
This commit is contained in:
@@ -116,6 +116,13 @@ class MutationsController extends Controller
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Check if request came from transaction page
|
||||
if ($request->has('from_transaction_page') || str_contains($request->header('referer', ''), '/transaction')) {
|
||||
return redirect()->back()
|
||||
->with('success', 'Mutasi berhasil dibuat dan terkirim ke dealer tujuan');
|
||||
}
|
||||
|
||||
return redirect()->route('mutations.index')
|
||||
->with('success', 'Mutasi berhasil dibuat dan terkirim ke dealer tujuan');
|
||||
|
||||
|
||||
@@ -41,4 +41,11 @@ class Dealer extends Model
|
||||
{
|
||||
return $this->hasMany(Stock::class);
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany(Product::class, 'stocks', 'dealer_id', 'product_id')
|
||||
->withPivot('quantity')
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,13 @@ class Product extends Model
|
||||
return $this->hasMany(MutationDetail::class);
|
||||
}
|
||||
|
||||
public function dealers()
|
||||
{
|
||||
return $this->belongsToMany(Dealer::class, 'stocks', 'product_id', 'dealer_id')
|
||||
->withPivot('quantity')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
// Helper method untuk mendapatkan total stock saat ini
|
||||
public function getCurrentTotalStockAttribute()
|
||||
{
|
||||
|
||||
@@ -97,6 +97,17 @@ use Illuminate\Support\Facades\Auth;
|
||||
border-color: #dc3545;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
.quantity-input-mutasi.is-invalid {
|
||||
border-color: #dc3545;
|
||||
background-color: #fff5f5;
|
||||
}
|
||||
.quantity-input-mutasi.is-invalid:focus {
|
||||
border-color: #dc3545;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
.available-stock-mutasi {
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@@ -156,35 +167,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (session('success'))
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="col-12">
|
||||
<div class="alert alert—check alert-success fade show" role="alert">
|
||||
<div class="alert-text">{{ session('success') }}</div>
|
||||
<div class="alert-close">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="la la-close"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('error'))
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-danger fade show" role="alert">
|
||||
<div class="alert-text">{{ session('error') }}</div>
|
||||
<div class="alert-close">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true"><i class="la la-close"></i></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<!--begin::Portlet-->
|
||||
@@ -581,7 +564,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-3">
|
||||
<button class="btn btn-warning btn-lg button-save d-block w-100 mt-2">
|
||||
<button id="btn-save-opname" class="btn btn-warning btn-lg d-block w-100 mt-2">
|
||||
Simpan Opname
|
||||
</button>
|
||||
</div>
|
||||
@@ -590,73 +573,84 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
<!-- Form Mutasi -->
|
||||
<div class="tab-pane" id="mutasi" role="tabpanel">
|
||||
<form action="#" method="POST" id="mutasiForm">
|
||||
<form action="{{ route('mutations.store') }}" method="POST" id="mutasiForm">
|
||||
@csrf
|
||||
<input type="hidden" name="form" value="mutasi">
|
||||
<input type="hidden" name="mechanic_id" value="{{ $mechanic->id }}">
|
||||
<input type="hidden" name="dealer_id" value="{{ $mechanic->dealer_id }}">
|
||||
<input type="hidden" name="from_dealer_id" value="{{ $mechanic->dealer_id }}">
|
||||
<input type="hidden" name="from_transaction_page" value="1">
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>Tanggal Mutasi</label>
|
||||
<input type="text" name="mutasi_date" id="date-mutasi" class="form-control" placeholder="Tanggal Mutasi" required>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label>Jenis Mutasi</label>
|
||||
<select name="mutasi_type" class="form-control" required>
|
||||
<option value="">Pilih Jenis</option>
|
||||
<option value="masuk">Barang Masuk</option>
|
||||
<option value="keluar">Barang Keluar</option>
|
||||
<option value="transfer">Transfer</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Dealer Asal</label>
|
||||
<input type="text" class="form-control" value="{{ $mechanic->dealer_name }}" disabled>
|
||||
<small class="text-muted">Otomatis terdeteksi dari akun Anda</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Keterangan</label>
|
||||
<textarea name="description" class="form-control" rows="3" placeholder="Keterangan mutasi"></textarea>
|
||||
<label for="to_dealer_id">Dealer Tujuan <span class="text-danger">*</span></label>
|
||||
<select name="to_dealer_id" id="to_dealer_id" class="form-control" required>
|
||||
<option value="">Pilih Dealer Tujuan</option>
|
||||
@php
|
||||
$dealers = \App\Models\Dealer::where('id', '!=', $mechanic->dealer_id)->get();
|
||||
@endphp
|
||||
@foreach($dealers as $dealer)
|
||||
<option value="{{ $dealer->id }}">{{ $dealer->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- List Produk untuk Mutasi -->
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">
|
||||
<input type="checkbox" id="select-all-mutasi">
|
||||
</th>
|
||||
<th>Produk</th>
|
||||
<th>Stock Saat Ini</th>
|
||||
<th>Jumlah Mutasi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{-- Dealer/Mechanic - Show products for current dealer only --}}
|
||||
@foreach($products as $product)
|
||||
@php
|
||||
$stock = $product->stocks->first();
|
||||
$currentStock = $stock ? $stock->quantity : 0;
|
||||
@endphp
|
||||
<div class="form-group">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<label class="form-label mb-0">Detail Produk <span class="text-danger">*</span></label>
|
||||
<button type="button" class="btn btn-success btn-sm" id="add-product-mutasi">
|
||||
<i class="fa fa-plus"></i> Tambah Produk
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-sm" id="products-table-mutasi">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="40%">Produk</th>
|
||||
<th width="20%">Stock Tersedia</th>
|
||||
<th width="25%">Quantity</th>
|
||||
<th width="15%">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="products-tbody-mutasi">
|
||||
<tr class="product-row-mutasi" data-index="0">
|
||||
<td>
|
||||
<input type="checkbox" class="mutasi-product-checkbox" name="selected_products[]" value="{{ $product->id }}_{{ $mechanic->dealer_id }}">
|
||||
<select name="products[0][product_id]" class="form-control product-select-mutasi" required>
|
||||
<option value="">Pilih Produk</option>
|
||||
@foreach($products as $product)
|
||||
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="available-stock-mutasi text-muted">-</span>
|
||||
</td>
|
||||
<td>{{ $product->name }}</td>
|
||||
<td class="text-right">{{ number_format($currentStock, 2) }}</td>
|
||||
<td>
|
||||
<input type="number" class="form-control mutasi-quantity" name="mutasi_quantity[{{ $product->id }}_{{ $mechanic->dealer_id }}]" step="0.01" placeholder="0.00" disabled>
|
||||
<input type="hidden" name="product_id_mutasi[]" value="{{ $product->id }}">
|
||||
<input type="hidden" name="dealer_id_mutasi[]" value="{{ $mechanic->dealer_id }}">
|
||||
<input type="number"
|
||||
name="products[0][quantity_requested]"
|
||||
class="form-control quantity-input-mutasi"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
placeholder="0"
|
||||
required>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger btn-sm remove-product-mutasi" disabled>
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-3">
|
||||
<button class="btn btn-warning btn-lg button-save d-block w-100 mt-2">
|
||||
Simpan Mutasi
|
||||
<button id="btn-save-mutasi" type="submit" class="btn btn-warning btn-lg d-block w-100 mt-2">
|
||||
Kirim Mutasi
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -881,9 +875,9 @@ use Illuminate\Support\Facades\Auth;
|
||||
return false;
|
||||
}
|
||||
|
||||
$(".button-save").attr("disabled", true);
|
||||
$(".button-save").addClass("disabled");
|
||||
$(".button-save").html('<i class="fa fa-spinner fa-spin"></i> Menyimpan...');
|
||||
$("#btn-save-opname").attr("disabled", true);
|
||||
$("#btn-save-opname").addClass("disabled");
|
||||
$("#btn-save-opname").html('<i class="fa fa-spinner fa-spin"></i> Menyimpan...');
|
||||
|
||||
// Date format is already YYYY-MM-DD, no conversion needed
|
||||
|
||||
@@ -906,10 +900,158 @@ use Illuminate\Support\Facades\Auth;
|
||||
this.submit();
|
||||
})
|
||||
|
||||
$("#mutasiForm").submit(function(e) {
|
||||
$(".button-save").attr("disabled");
|
||||
$(".button-save").addClass("disabled");
|
||||
return true;
|
||||
// Handle mutasi form submission
|
||||
$(document).on('submit', '#mutasiForm', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Validate form
|
||||
var isValid = true;
|
||||
var errorMessages = [];
|
||||
|
||||
// Check if dealer tujuan is selected
|
||||
var dealerTujuan = $('#to_dealer_id').val();
|
||||
console.log('Dealer tujuan value:', dealerTujuan);
|
||||
if (!dealerTujuan || dealerTujuan === '') {
|
||||
errorMessages.push('Pilih dealer tujuan');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// Check if at least one product is selected with quantity
|
||||
var hasProducts = false;
|
||||
var productCount = 0;
|
||||
$('.product-select-mutasi').each(function(index) {
|
||||
var productId = $(this).val();
|
||||
var quantity = $(this).closest('tr').find('.quantity-input-mutasi').val();
|
||||
|
||||
console.log(`Product ${index}:`, 'ID =', productId, 'Qty =', quantity);
|
||||
|
||||
if (productId && productId !== '' && quantity && parseFloat(quantity) > 0) {
|
||||
hasProducts = true;
|
||||
productCount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasProducts) {
|
||||
errorMessages.push('Minimal pilih satu produk dengan quantity yang valid');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// Additional validation: check all required fields
|
||||
var requiredFields = [
|
||||
{name: 'to_dealer_id', label: 'Dealer Tujuan'},
|
||||
{name: 'from_dealer_id', label: 'Dealer Asal'}
|
||||
];
|
||||
|
||||
requiredFields.forEach(function(field) {
|
||||
var value = $(`[name="${field.name}"]`).val();
|
||||
console.log(`${field.name} value:`, value);
|
||||
if (!value || value === '') {
|
||||
errorMessages.push(`${field.label} harus diisi`);
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Check products array
|
||||
var hasValidProduct = false;
|
||||
$('select[name^="products["][name$="][product_id]"]').each(function(index) {
|
||||
var productId = $(this).val();
|
||||
var quantityName = $(this).attr('name').replace('[product_id]', '[quantity_requested]');
|
||||
var quantity = $(`[name="${quantityName}"]`).val();
|
||||
|
||||
console.log(`Product validation ${index}:`, productId, quantity);
|
||||
|
||||
if (productId && productId !== '' && quantity && parseFloat(quantity) > 0) {
|
||||
hasValidProduct = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasValidProduct) {
|
||||
errorMessages.push('Minimal harus ada satu produk dengan quantity yang valid');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
console.log('Final validation result:', isValid);
|
||||
console.log('Error messages:', errorMessages);
|
||||
|
||||
// Check for invalid quantities
|
||||
var hasInvalidQuantity = false;
|
||||
$('.quantity-input-mutasi').each(function() {
|
||||
if ($(this).hasClass('is-invalid')) {
|
||||
hasInvalidQuantity = true;
|
||||
return false; // break loop
|
||||
}
|
||||
});
|
||||
|
||||
if (hasInvalidQuantity) {
|
||||
errorMessages.push('Perbaiki quantity yang melebihi stock tersedia');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!isValid) {
|
||||
// Highlight invalid fields
|
||||
if (!$('#to_dealer_id').val()) {
|
||||
$('#to_dealer_id').addClass('is-invalid');
|
||||
} else {
|
||||
$('#to_dealer_id').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
// Check products
|
||||
$('select[name^="products["][name$="][product_id]"]').each(function() {
|
||||
var productId = $(this).val();
|
||||
var quantityInput = $(this).closest('tr').find('.quantity-input-mutasi');
|
||||
var quantity = quantityInput.val();
|
||||
|
||||
if (!productId || productId === '') {
|
||||
$(this).addClass('is-invalid');
|
||||
} else {
|
||||
$(this).removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!quantity || parseFloat(quantity) <= 0) {
|
||||
quantityInput.addClass('is-invalid');
|
||||
} else {
|
||||
quantityInput.removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof Swal !== 'undefined') {
|
||||
Swal.fire({
|
||||
type: 'warning',
|
||||
title: 'Validasi Gagal',
|
||||
text: errorMessages.join(', ')
|
||||
});
|
||||
} else {
|
||||
alert('Validasi Gagal: ' + errorMessages.join(', '));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Show confirmation
|
||||
if (typeof Swal !== 'undefined') {
|
||||
Swal.fire({
|
||||
title: 'Kirim Mutasi?',
|
||||
text: "Mutasi akan dikirim ke dealer tujuan",
|
||||
type: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#ffc107',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Ya, Kirim',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
console.log('SweetAlert result:', result);
|
||||
if (result.value === true) { // For older SweetAlert2
|
||||
console.log('Confirmed, submitting...');
|
||||
submitMutasiFormDirect();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Fallback to native confirm
|
||||
if (confirm('Kirim Mutasi? Mutasi akan dikirim ke dealer tujuan')) {
|
||||
submitMutasiFormDirect();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
$("#date-work").datepicker({
|
||||
@@ -983,8 +1125,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
buttonText += ` (${filledProducts}/${totalProducts} produk)`;
|
||||
}
|
||||
|
||||
if (!$('.button-save').hasClass('disabled')) {
|
||||
$('.button-save').html(buttonText);
|
||||
if (!$('#btn-save-opname').hasClass('disabled')) {
|
||||
$('#btn-save-opname').html(buttonText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,8 +1138,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
// Function to reset button state if validation fails
|
||||
function resetSubmitButton() {
|
||||
$(".button-save").attr("disabled", false);
|
||||
$(".button-save").removeClass("disabled");
|
||||
$("#btn-save-opname").attr("disabled", false);
|
||||
$("#btn-save-opname").removeClass("disabled");
|
||||
updateProductCounter(); // Update with current counter
|
||||
}
|
||||
|
||||
@@ -1033,6 +1175,18 @@ use Illuminate\Support\Facades\Auth;
|
||||
$('#date-opname').val(today);
|
||||
}
|
||||
|
||||
// Initialize mutasi form
|
||||
updateRemoveButtonsMutasi();
|
||||
|
||||
// Check if we should show mutasi tab (after form submission)
|
||||
@if(session('success') || session('error') || $errors->any())
|
||||
// Activate stock tab and mutasi sub-tab
|
||||
$('.nav-link[href="#stock"]').tab('show');
|
||||
setTimeout(function() {
|
||||
$('.nav-link[href="#mutasi"]').tab('show');
|
||||
}, 100);
|
||||
@endif
|
||||
|
||||
// Check if there are validation errors
|
||||
if ($('.is-invalid').length > 0) {
|
||||
// Scroll to first error
|
||||
@@ -1043,7 +1197,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
// Show alert for validation errors
|
||||
@if(session('error'))
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
type: 'error',
|
||||
title: 'Terjadi Kesalahan',
|
||||
text: '{{ session("error") }}',
|
||||
confirmButtonText: 'OK'
|
||||
@@ -1051,10 +1205,94 @@ use Illuminate\Support\Facades\Auth;
|
||||
@endif
|
||||
}
|
||||
|
||||
// Auto-dismiss alerts after 5 seconds
|
||||
setTimeout(function() {
|
||||
$('.alert').fadeOut('slow');
|
||||
}, 5000);
|
||||
|
||||
|
||||
// Handle success/error messages for both opname and mutasi
|
||||
@if(session('success'))
|
||||
Swal.fire({
|
||||
type: 'success',
|
||||
title: 'Berhasil!',
|
||||
text: '{{ session("success") }}',
|
||||
timer: 3000,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
// Check if this is from mutasi form (contains "Mutasi" in message)
|
||||
var successMessage = '{{ session("success") }}';
|
||||
if (successMessage.toLowerCase().includes('mutasi')) {
|
||||
// Reset mutasi form after success
|
||||
$('#mutasiForm')[0].reset();
|
||||
$('#products-tbody-mutasi').html(`
|
||||
<tr class="product-row-mutasi" data-index="0">
|
||||
<td>
|
||||
<select name="products[0][product_id]" class="form-control product-select-mutasi" required>
|
||||
<option value="">Pilih Produk</option>
|
||||
@foreach($products as $product)
|
||||
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="available-stock-mutasi text-muted">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number"
|
||||
name="products[0][quantity_requested]"
|
||||
class="form-control quantity-input-mutasi"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
placeholder="0"
|
||||
required>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger btn-sm remove-product-mutasi" disabled>
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
productIndexMutasi = 0;
|
||||
updateRemoveButtonsMutasi();
|
||||
$("#btn-save-mutasi").attr("disabled", false);
|
||||
$("#btn-save-mutasi").removeClass("disabled");
|
||||
$("#btn-save-mutasi").html('Kirim Mutasi');
|
||||
} else if (successMessage.toLowerCase().includes('opname')) {
|
||||
// Reset opname form after success
|
||||
$('#opnameForm')[0].reset();
|
||||
$('.physical-stock').val('').removeClass('is-invalid');
|
||||
$('.difference').text('0.00').removeClass('text-success text-danger');
|
||||
$("#btn-save-opname").attr("disabled", false);
|
||||
$("#btn-save-opname").removeClass("disabled");
|
||||
$("#btn-save-opname").html('Simpan Opname');
|
||||
// Set default date
|
||||
var today = new Date().toISOString().split('T')[0];
|
||||
$('#date-opname').val(today);
|
||||
}
|
||||
});
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
Swal.fire({
|
||||
type: 'error',
|
||||
title: 'Terjadi Kesalahan',
|
||||
text: '{{ session("error") }}',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
@endif
|
||||
|
||||
// Handle validation errors
|
||||
@if($errors->any())
|
||||
var errorMessages = [];
|
||||
@foreach($errors->all() as $error)
|
||||
errorMessages.push('{{ $error }}');
|
||||
@endforeach
|
||||
|
||||
Swal.fire({
|
||||
type: 'error',
|
||||
title: 'Validasi Gagal',
|
||||
html: errorMessages.join('<br>'),
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
@endif
|
||||
});
|
||||
|
||||
// Handle opname date field - set default if becomes empty
|
||||
@@ -1065,19 +1303,178 @@ use Illuminate\Support\Facades\Auth;
|
||||
}
|
||||
});
|
||||
|
||||
// Handle mutasi product selection
|
||||
$(document).on('change', '.mutasi-product-checkbox', function() {
|
||||
var quantityInput = $(this).closest('tr').find('.mutasi-quantity');
|
||||
if ($(this).is(':checked')) {
|
||||
quantityInput.prop('disabled', false);
|
||||
// Handle mutasi form - similar to create mutation
|
||||
var productIndexMutasi = 0;
|
||||
|
||||
|
||||
|
||||
// Function to submit mutasi form directly
|
||||
function submitMutasiFormDirect() {
|
||||
console.log('=== SUBMITTING FORM ===');
|
||||
|
||||
// Set loading state
|
||||
$("#btn-save-mutasi").attr("disabled", true);
|
||||
$("#btn-save-mutasi").addClass("disabled");
|
||||
$("#btn-save-mutasi").html('<i class="fa fa-spinner fa-spin"></i> Mengirim...');
|
||||
|
||||
// Get form element directly
|
||||
var form = document.getElementById('mutasiForm');
|
||||
|
||||
if (!form) {
|
||||
console.error('Form not found!');
|
||||
alert('Form tidak ditemukan!');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Form found:', form);
|
||||
console.log('Form action:', form.action);
|
||||
console.log('Form method:', form.method);
|
||||
|
||||
// Check form data
|
||||
var formData = new FormData(form);
|
||||
console.log('Form data:');
|
||||
for (var pair of formData.entries()) {
|
||||
console.log(pair[0] + ': ' + pair[1]);
|
||||
}
|
||||
|
||||
// Submit form directly - simplified approach
|
||||
try {
|
||||
console.log('Attempting form.submit()...');
|
||||
|
||||
// Temporarily remove the submit event listener to prevent recursion
|
||||
$(form).off('submit');
|
||||
|
||||
// Submit the form
|
||||
form.submit();
|
||||
console.log('form.submit() called successfully');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Form submission error:', error);
|
||||
// Reset button if submission fails
|
||||
$("#btn-save-mutasi").attr("disabled", false);
|
||||
$("#btn-save-mutasi").removeClass("disabled");
|
||||
$("#btn-save-mutasi").html('Kirim Mutasi');
|
||||
alert('Terjadi kesalahan saat mengirim form. Silakan coba lagi.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Add product row for mutasi
|
||||
$('#add-product-mutasi').click(function() {
|
||||
productIndexMutasi++;
|
||||
var newRow = `
|
||||
<tr class="product-row-mutasi" data-index="${productIndexMutasi}">
|
||||
<td>
|
||||
<select name="products[${productIndexMutasi}][product_id]" class="form-control product-select-mutasi" required>
|
||||
<option value="">Pilih Produk</option>
|
||||
@foreach($products as $product)
|
||||
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="available-stock-mutasi text-muted">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number"
|
||||
name="products[${productIndexMutasi}][quantity_requested]"
|
||||
class="form-control quantity-input-mutasi"
|
||||
min="0.01"
|
||||
step="0.01"
|
||||
placeholder="0"
|
||||
required>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger btn-sm remove-product-mutasi">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
$('#products-tbody-mutasi').append(newRow);
|
||||
updateRemoveButtonsMutasi();
|
||||
});
|
||||
|
||||
// Remove product row for mutasi
|
||||
$(document).on('click', '.remove-product-mutasi', function() {
|
||||
$(this).closest('tr').remove();
|
||||
updateRemoveButtonsMutasi();
|
||||
});
|
||||
|
||||
// Update remove buttons state for mutasi
|
||||
function updateRemoveButtonsMutasi() {
|
||||
var rows = $('.product-row-mutasi');
|
||||
if (rows.length <= 1) {
|
||||
$('.remove-product-mutasi').prop('disabled', true);
|
||||
} else {
|
||||
quantityInput.prop('disabled', true).val('');
|
||||
$('.remove-product-mutasi').prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle product selection change for mutasi - get stock info
|
||||
$(document).on('change', '.product-select-mutasi', function() {
|
||||
var productId = $(this).val();
|
||||
var dealerId = {{ $mechanic->dealer_id }};
|
||||
var stockSpan = $(this).closest('tr').find('.available-stock-mutasi');
|
||||
|
||||
if (productId) {
|
||||
// Get stock info via AJAX
|
||||
$.ajax({
|
||||
url: '{{ route("mutations.get-product-stock") }}',
|
||||
method: 'GET',
|
||||
data: {
|
||||
product_id: productId,
|
||||
dealer_id: dealerId
|
||||
},
|
||||
success: function(response) {
|
||||
stockSpan.text(parseFloat(response.current_stock).toFixed(2));
|
||||
stockSpan.removeClass('text-muted').addClass('text-info');
|
||||
},
|
||||
error: function() {
|
||||
stockSpan.text('-');
|
||||
stockSpan.removeClass('text-info').addClass('text-muted');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
stockSpan.text('-');
|
||||
stockSpan.removeClass('text-info').addClass('text-muted');
|
||||
}
|
||||
});
|
||||
|
||||
// Select all mutasi products
|
||||
$('#select-all-mutasi').change(function() {
|
||||
$('.mutasi-product-checkbox').prop('checked', this.checked).trigger('change');
|
||||
// Validate quantity against available stock for mutasi
|
||||
$(document).on('input', '.quantity-input-mutasi', function() {
|
||||
var quantity = parseFloat($(this).val()) || 0;
|
||||
var stockText = $(this).closest('tr').find('.available-stock-mutasi').text();
|
||||
var availableStock = parseFloat(stockText) || 0;
|
||||
|
||||
if (quantity > availableStock && availableStock > 0) {
|
||||
$(this).addClass('is-invalid');
|
||||
if (!$(this).siblings('.invalid-feedback').length) {
|
||||
$(this).after('<div class="invalid-feedback">Quantity melebihi stock tersedia</div>');
|
||||
}
|
||||
} else {
|
||||
$(this).removeClass('is-invalid');
|
||||
$(this).siblings('.invalid-feedback').remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove error styling when user starts filling fields
|
||||
$(document).on('change', '#to_dealer_id', function() {
|
||||
$(this).removeClass('is-invalid');
|
||||
});
|
||||
|
||||
$(document).on('change', '.product-select-mutasi', function() {
|
||||
$(this).removeClass('is-invalid');
|
||||
});
|
||||
|
||||
$(document).on('input', '.quantity-input-mutasi', function() {
|
||||
if (parseFloat($(this).val()) > 0) {
|
||||
$(this).removeClass('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<!-- View Button -->
|
||||
<a href="{{ route('mutations.show', $row->id) }}"
|
||||
class="btn btn-sm btn-outline-info me-1">
|
||||
class="btn btn-sm btn-info mr-2">
|
||||
Detail
|
||||
</a>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<!-- Receive Button (untuk dealer tujuan) -->
|
||||
@if(auth()->user()->dealer_id == $row->to_dealer_id)
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-primary btn-receive me-1"
|
||||
class="btn btn-sm btn-primary btn-receive mr-2"
|
||||
data-id="{{ $row->id }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#receiveModal{{ $row->id }}">
|
||||
@@ -20,7 +20,7 @@
|
||||
<!-- Cancel Button (untuk pengirim) -->
|
||||
@if(auth()->user()->dealer_id == $row->from_dealer_id || auth()->user()->hasRole('admin'))
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-warning btn-cancel me-1"
|
||||
class="btn btn-sm btn-warning btn-cancel mr-2"
|
||||
data-id="{{ $row->id }}">
|
||||
Batal
|
||||
</button>
|
||||
@@ -31,7 +31,7 @@
|
||||
<!-- Approve Button (untuk pengirim atau admin) -->
|
||||
@if(auth()->user()->dealer_id == $row->from_dealer_id || auth()->user()->hasRole('admin'))
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-success btn-approve me-1"
|
||||
class="btn btn-sm btn-success btn-approve mr-2"
|
||||
data-id="{{ $row->id }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#approveModal{{ $row->id }}">
|
||||
@@ -42,7 +42,7 @@
|
||||
<!-- Reject Button (untuk pengirim atau admin) -->
|
||||
@if(auth()->user()->dealer_id == $row->from_dealer_id || auth()->user()->hasRole('admin'))
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-danger btn-reject me-1"
|
||||
class="btn btn-sm btn-danger btn-reject mr-2"
|
||||
data-id="{{ $row->id }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#rejectModal{{ $row->id }}">
|
||||
@@ -55,7 +55,7 @@
|
||||
<!-- Complete/Receive Button -->
|
||||
@can('complete-mutation')
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-primary btn-complete me-1"
|
||||
class="btn btn-sm btn-primary btn-complete mr-2"
|
||||
data-id="{{ $row->id }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#completeModal{{ $row->id }}">
|
||||
@@ -66,20 +66,12 @@
|
||||
<!-- Cancel Button -->
|
||||
@can('edit-mutation')
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-warning btn-cancel me-1"
|
||||
class="btn btn-sm btn-warning btn-cancel mr-2"
|
||||
data-id="{{ $row->id }}">
|
||||
Batal
|
||||
</button>
|
||||
@endcan
|
||||
@endif
|
||||
|
||||
@if(in_array($row->status->value, ['pending', 'approved']) && auth()->user()->id === $row->requested_by)
|
||||
<!-- Edit Button (only for creator and if still pending/approved) -->
|
||||
<a href="{{ route('mutations.edit', $row->id) }}"
|
||||
class="btn btn-sm btn-outline-secondary me-1">
|
||||
Edit
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Modal untuk Approve -->
|
||||
@@ -88,7 +80,6 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="approveModalLabel{{ $row->id }}">Setujui Mutasi</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('mutations.approve', $row->id) }}" method="POST" class="approve-form">
|
||||
@csrf
|
||||
@@ -154,7 +145,6 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="rejectModalLabel{{ $row->id }}">Tolak Mutasi</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('mutations.reject', $row->id) }}" method="POST">
|
||||
@csrf
|
||||
@@ -182,7 +172,6 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="receiveModalLabel{{ $row->id }}">Terima Mutasi</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('mutations.receive', $row->id) }}" method="POST">
|
||||
@csrf
|
||||
@@ -251,7 +240,6 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="completeModalLabel{{ $row->id }}">Selesaikan Mutasi</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('mutations.complete', $row->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
Tabel Mutasi
|
||||
</h3>
|
||||
</div>
|
||||
@can('create', $menus['mutations.index'])
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-wrapper">
|
||||
<div class="kt-portlet__head-actions">
|
||||
@@ -20,6 +21,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
<div class="kt-portlet__body">
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-wrapper">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<button type="button" class="btn btn-bold btn-label-brand btn-sm" id="addProductCategory"> Tambah </button>
|
||||
<button type="button" class="btn btn-bold btn-label-brand btn--sm" id="addProductCategory"> Tambah </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user