validate([ 'kilometer' => 'required|numeric|min:0', 'pressure_high' => 'required|numeric|min:0', 'pressure_low' => 'nullable|numeric|min:0', 'cabin_temperature' => 'nullable|numeric', 'cabin_temperature_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048', 'ac_condition' => 'nullable|in:' . implode(',', Precheck::getAcConditionOptions()), 'ac_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048', 'blower_condition' => 'nullable|in:' . implode(',', Precheck::getBlowerConditionOptions()), 'blower_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048', 'evaporator_condition' => 'nullable|in:' . implode(',', Precheck::getEvaporatorConditionOptions()), 'evaporator_image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048', 'compressor_condition' => 'nullable|in:' . implode(',', Precheck::getCompressorConditionOptions()), 'precheck_notes' => 'nullable|string', 'front_image' => 'required|image|mimes:jpeg,png,jpg|max:2048', ]); $data = [ 'transaction_id' => $transaction->id, 'precheck_by' => auth()->id(), 'precheck_at' => now(), 'police_number' => $transaction->police_number, 'spk_number' => $transaction->spk, 'kilometer' => $request->kilometer, 'pressure_high' => $request->pressure_high, 'pressure_low' => $request->pressure_low, 'cabin_temperature' => $request->cabin_temperature, 'ac_condition' => $request->ac_condition, 'blower_condition' => $request->blower_condition, 'evaporator_condition' => $request->evaporator_condition, 'compressor_condition' => $request->compressor_condition, 'precheck_notes' => $request->precheck_notes, ]; // Handle file uploads $imageFields = [ 'front_image', 'cabin_temperature_image', 'ac_image', 'blower_image', 'evaporator_image' ]; foreach ($imageFields as $field) { if ($request->hasFile($field) && $request->file($field)->isValid()) { try { $file = $request->file($field); // Generate unique filename $filename = time() . '_' . uniqid() . '_' . $field . '.' . $file->getClientOriginalExtension(); // Create directory path $directory = 'prechecks/' . date('Y/m'); // Ensure base storage directory exists $this->ensureStorageDirectoryExists(); // Ensure prechecks directory exists if (!Storage::disk('public')->exists('prechecks')) { Storage::disk('public')->makeDirectory('prechecks', 0755, true); Log::info('Created prechecks directory'); } // Ensure year directory exists $yearDir = 'prechecks/' . date('Y'); if (!Storage::disk('public')->exists($yearDir)) { Storage::disk('public')->makeDirectory($yearDir, 0755, true); Log::info('Created year directory: ' . $yearDir); } // Ensure month directory exists if (!Storage::disk('public')->exists($directory)) { Storage::disk('public')->makeDirectory($directory, 0755, true); Log::info('Created month directory: ' . $directory); } // Store file in organized directory structure $path = $file->storeAs($directory, $filename, 'public'); // Store file path $data[$field] = $path; // Store metadata $data[$field . '_metadata'] = [ 'original_name' => $file->getClientOriginalName(), 'size' => $file->getSize(), 'mime_type' => $file->getMimeType(), 'uploaded_at' => now()->toISOString(), ]; Log::info('File uploaded successfully: ' . $path); } catch (\Exception $e) { // Log error for debugging Log::error('File upload failed: ' . $e->getMessage(), [ 'field' => $field, 'file' => $file->getClientOriginalName(), 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return back()->withErrors(['error' => 'Gagal mengupload file: ' . $field . '. Error: ' . $e->getMessage()]); } } } try { Precheck::create($data); return redirect()->route('transaction')->with('success', 'Precheck berhasil disimpan'); } catch (\Exception $e) { Log::error('Precheck creation failed: ' . $e->getMessage()); return back()->withErrors(['error' => 'Gagal menyimpan data precheck. Silakan coba lagi.']); } } /** * Ensure the base storage directory exists */ private function ensureStorageDirectoryExists() { $storagePath = storage_path('app/public'); if (!is_dir($storagePath)) { if (!mkdir($storagePath, 0755, true)) { Log::error('Failed to create storage directory: ' . $storagePath); throw new \Exception('Cannot create storage directory: ' . $storagePath . '. Please run: php fix_permissions.php or manually create the directory.'); } Log::info('Created storage directory: ' . $storagePath); } // Check if directory is writable if (!is_writable($storagePath)) { Log::error('Storage directory is not writable: ' . $storagePath); throw new \Exception( 'Storage directory is not writable: ' . $storagePath . '. ' . 'Please run one of these commands from your project root: ' . '1) php fix_permissions.php ' . '2) chmod -R 775 storage/ ' . '3) mkdir -p storage/app/public/prechecks/' . date('Y/m') ); } // Check if we can create subdirectories $testDir = $storagePath . '/test_' . time(); if (!mkdir($testDir, 0755, true)) { Log::error('Cannot create subdirectories in storage: ' . $storagePath); throw new \Exception( 'Cannot create subdirectories in storage. ' . 'Please check permissions and run: php fix_permissions.php' ); } // Clean up test directory rmdir($testDir); Log::info('Storage directory is properly configured: ' . $storagePath); } }