fix opname default value, show different opname and hide system stock opname

This commit is contained in:
2025-07-03 13:55:49 +07:00
parent 9b3889ef1f
commit 0ef03fe7cb
8 changed files with 179 additions and 147 deletions

View File

@@ -27,7 +27,7 @@ class OpnamesController extends Controller
$dealers = Dealer::all();
if($request->ajax()){
$data = Opname::query()
->with('user','dealer')
->with(['user','dealer', 'details.product'])
->orderBy('created_at', 'desc');
// Filter berdasarkan dealer yang dipilih
@@ -76,6 +76,46 @@ class OpnamesController extends Controller
return "<span class=\"font-weight-bold {$textColorClass}\">{$label}</span>";
})
->addColumn('stock_info', function ($row) {
// Use eager loaded details
$details = $row->details;
if ($details->isEmpty()) {
return '<span class="text-muted">Tidak ada data</span>';
}
$totalProducts = $details->count();
$matchingProducts = $details->where('difference', 0)->count();
$differentProducts = $totalProducts - $matchingProducts;
$info = [];
if ($matchingProducts > 0) {
$info[] = "<span class='text-success'><i class='fa fa-check-circle'></i> {$matchingProducts} sesuai</span>";
}
if ($differentProducts > 0) {
// Get more details about differences
$positiveDiff = $details->where('difference', '>', 0)->count();
$negativeDiff = $details->where('difference', '<', 0)->count();
$diffInfo = [];
if ($positiveDiff > 0) {
$diffInfo[] = "+{$positiveDiff}";
}
if ($negativeDiff > 0) {
$diffInfo[] = "-{$negativeDiff}";
}
$diffText = implode(', ', $diffInfo);
$info[] = "<span class='text-danger'><i class='fa fa-exclamation-triangle'></i> {$differentProducts} selisih ({$diffText})</span>";
}
// Add total products info
$info[] = "<small class='text-muted'>(Total: {$totalProducts} produk)</small>";
return '<div class="stock-info-cell">' . implode('<br>', $info) . '</div>';
})
->addColumn('action', function ($row) use ($menu) {
$btn = '<div class="d-flex">';
@@ -86,7 +126,7 @@ class OpnamesController extends Controller
return $btn;
})
->rawColumns(['action', 'status'])
->rawColumns(['action', 'status', 'stock_info'])
->make(true);
}
@@ -124,7 +164,7 @@ class OpnamesController extends Controller
$isTransactionForm = $request->has('form') && $request->form === 'opname';
if ($isTransactionForm) {
// Custom validation for transaction form
// Simplified validation for transaction form
$request->validate([
'dealer_id' => 'required|exists:dealers,id',
'user_id' => 'required|exists:users,id',
@@ -140,7 +180,7 @@ class OpnamesController extends Controller
'system_stock' => 'required|array',
'system_stock.*' => 'required|numeric|min:0',
'physical_stock' => 'required|array',
'physical_stock.*' => 'required|numeric|min:0'
'physical_stock.*' => 'nullable|numeric|min:0'
]);
// Process transaction form data with proper date parsing
@@ -199,19 +239,11 @@ class OpnamesController extends Controller
$physicalStocks = $request->physical_quantity;
}
// 2. Validasi minimal ada produk yang diisi (termasuk nilai 0)
// 2. Simplified validation - all products are valid, set defaults for empty physical stocks
$validProductIds = array_filter($productIds);
$validSystemStocks = array_filter($systemStocks, function($value) { return $value !== null && $value !== ''; });
$validPhysicalStocks = array_filter($physicalStocks, function($value) {
return $value !== null && $value !== '' && is_numeric($value);
});
if (empty($validProductIds) || count($validProductIds) === 0) {
throw new \Exception('Minimal harus ada satu produk yang diisi untuk opname.');
}
if (count($validPhysicalStocks) === 0) {
throw new \Exception('Minimal harus ada satu stock fisik yang diisi (termasuk nilai 0).');
throw new \Exception('Minimal harus ada satu produk untuk opname.');
}
// 3. Validasi duplikasi produk
@@ -283,19 +315,14 @@ class OpnamesController extends Controller
foreach ($productIds as $index => $productId) {
if (!$productId) continue;
// Skip only if physical stock is truly not provided (empty string or null)
// Accept 0 as valid input
if (!isset($physicalStocks[$index]) || $physicalStocks[$index] === '' || $physicalStocks[$index] === null) {
continue;
}
// Validate that physical stock is numeric (including 0)
if (!is_numeric($physicalStocks[$index])) {
continue;
// Set default value to 0 if physical stock is empty or invalid
$physicalStockValue = $physicalStocks[$index] ?? null;
if ($physicalStockValue === '' || $physicalStockValue === null || !is_numeric($physicalStockValue)) {
$physicalStockValue = 0;
}
$systemStock = floatval($systemStocks[$index] ?? 0);
$physicalStock = floatval($physicalStocks[$index]);
$physicalStock = floatval($physicalStockValue);
$difference = $physicalStock - $systemStock;
$processedCount++;
@@ -337,7 +364,7 @@ class OpnamesController extends Controller
// Validate we have at least one detail to insert
if (empty($details)) {
throw new \Exception('Tidak ada data stock fisik yang valid untuk diproses.');
throw new \Exception('Tidak ada data produk yang valid untuk diproses.');
}
// Bulk insert untuk performa lebih baik
@@ -371,13 +398,13 @@ class OpnamesController extends Controller
// Redirect back to transaction page with success message and tab indicator
return redirect()
->route('transaction')
->with('success', "Opname berhasil disimpan dan disetujui. {$processedCount} produk telah diproses.")
->with('success', "Opname berhasil disimpan. {$processedCount} produk telah diproses.")
->with('active_tab', 'opname');
} else {
// Redirect to opname index for regular form
return redirect()
->route('opnames.index')
->with('success', "Opname berhasil disimpan dan disetujui. {$processedCount} produk telah diproses.");
->with('success', "Opname berhasil disimpan. {$processedCount} produk telah diproses.");
}
} catch (\Illuminate\Validation\ValidationException $e) {