header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('sales.prospects.index')); } $query = SalesProspect::with(['manager', 'salesManager', 'products']); // 검색 if ($search = $request->get('search')) { $query->where(function ($q) use ($search) { $q->where('company_name', 'like', "%{$search}%") ->orWhere('business_no', 'like', "%{$search}%") ->orWhere('representative', 'like', "%{$search}%") ->orWhere('contact_phone', 'like', "%{$search}%"); }); } // 상태 필터 if ($status = $request->get('status')) { $query->where('status', $status); } // 담당자 필터 if ($managerId = $request->get('manager_id')) { $query->where(function ($q) use ($managerId) { $q->where('manager_id', $managerId) ->orWhere('sales_manager_id', $managerId); }); } $prospects = $query->orderByDesc('created_at')->paginate(20); // 통계 $stats = [ 'total' => SalesProspect::count(), 'lead' => SalesProspect::where('status', 'lead')->count(), 'prospect' => SalesProspect::where('status', 'prospect')->count(), 'negotiation' => SalesProspect::where('status', 'negotiation')->count(), 'contracted' => SalesProspect::where('status', 'contracted')->count(), 'total_contract' => SalesProspectProduct::sum('contract_amount'), 'total_commission' => SalesProspectProduct::sum('commission_amount'), ]; $managers = SalesManager::active()->orderBy('name')->get(); return view('sales.prospects.index', compact('prospects', 'stats', 'managers')); } /** * 등록 폼 */ public function create(): View { $managers = SalesManager::active()->orderBy('name')->get(); return view('sales.prospects.create', compact('managers')); } /** * 등록 처리 */ public function store(Request $request) { $validated = $request->validate([ 'manager_id' => 'required|exists:sales_managers,id', 'sales_manager_id' => 'nullable|exists:sales_managers,id', 'company_name' => 'required|string|max:200', 'representative' => 'nullable|string|max:100', 'business_no' => 'nullable|string|max:20', 'contact_phone' => 'nullable|string|max:20', 'email' => 'nullable|email|max:100', 'address' => 'nullable|string|max:500', 'status' => 'required|in:lead,prospect,negotiation,contracted,lost', 'business_card_image_data' => 'nullable|string', 'id_card_image_data' => 'nullable|string', 'bankbook_image_data' => 'nullable|string', ]); // 명함 이미지 저장 (Base64) if (!empty($validated['business_card_image_data'])) { $validated['business_card_image'] = $this->saveBase64Image($validated['business_card_image_data'], 'business-cards'); } unset($validated['business_card_image_data']); // 신분증 이미지 저장 (Base64) if (!empty($validated['id_card_image_data'])) { $validated['id_card_image'] = $this->saveBase64Image($validated['id_card_image_data'], 'id-cards'); } unset($validated['id_card_image_data']); // 통장사본 이미지 저장 (Base64) if (!empty($validated['bankbook_image_data'])) { $validated['bankbook_image'] = $this->saveBase64Image($validated['bankbook_image_data'], 'bankbooks'); } unset($validated['bankbook_image_data']); $prospect = SalesProspect::create($validated); return redirect()->route('sales.prospects.show', $prospect->id) ->with('success', '가망고객이 등록되었습니다.'); } /** * 상세 페이지 */ public function show(int $id): View { $prospect = SalesProspect::with([ 'manager', 'salesManager', 'products', 'scenarios', 'consultations.manager' ])->findOrFail($id); $managers = SalesManager::active() ->whereIn('role', ['sales_admin', 'manager']) ->orderBy('name') ->get(); return view('sales.prospects.show', compact('prospect', 'managers')); } /** * 수정 폼 */ public function edit(int $id): View { $prospect = SalesProspect::findOrFail($id); $managers = SalesManager::active()->orderBy('name')->get(); return view('sales.prospects.edit', compact('prospect', 'managers')); } /** * 수정 처리 */ public function update(Request $request, int $id) { $prospect = SalesProspect::findOrFail($id); $validated = $request->validate([ 'sales_manager_id' => 'nullable|exists:sales_managers,id', 'company_name' => 'required|string|max:200', 'representative' => 'nullable|string|max:100', 'business_no' => 'nullable|string|max:20', 'contact_phone' => 'nullable|string|max:20', 'email' => 'nullable|email|max:100', 'address' => 'nullable|string|max:500', 'status' => 'required|in:lead,prospect,negotiation,contracted,lost', 'business_card' => 'nullable|image|max:5120', 'id_card' => 'nullable|image|max:5120', 'bankbook' => 'nullable|image|max:5120', ]); // 명함 이미지 업로드 처리 if ($request->hasFile('business_card')) { if ($prospect->business_card_image) { Storage::disk('public')->delete($prospect->business_card_image); } $validated['business_card_image'] = $request->file('business_card') ->store('business-cards', 'public'); } unset($validated['business_card']); // 신분증 이미지 업로드 처리 if ($request->hasFile('id_card')) { if ($prospect->id_card_image) { Storage::disk('public')->delete($prospect->id_card_image); } $validated['id_card_image'] = $request->file('id_card') ->store('id-cards', 'public'); } unset($validated['id_card']); // 통장사본 이미지 업로드 처리 if ($request->hasFile('bankbook')) { if ($prospect->bankbook_image) { Storage::disk('public')->delete($prospect->bankbook_image); } $validated['bankbook_image'] = $request->file('bankbook') ->store('bankbooks', 'public'); } unset($validated['bankbook']); $prospect->update($validated); return redirect()->route('sales.prospects.show', $prospect->id) ->with('success', '가망고객 정보가 수정되었습니다.'); } /** * 삭제 처리 */ public function destroy(int $id) { $prospect = SalesProspect::findOrFail($id); // 첨부 이미지 삭제 $imageFields = ['business_card_image', 'id_card_image', 'bankbook_image']; foreach ($imageFields as $field) { if ($prospect->$field) { Storage::disk('public')->delete($prospect->$field); } } $prospect->delete(); return redirect()->route('sales.prospects.index') ->with('success', '가망고객이 삭제되었습니다.'); } /** * Base64 이미지 저장 */ private function saveBase64Image(string $base64Data, string $folder): ?string { // data:image/jpeg;base64,... 형식에서 데이터 추출 if (preg_match('/^data:image\/(\w+);base64,/', $base64Data, $matches)) { $extension = $matches[1]; $base64Data = preg_replace('/^data:image\/\w+;base64,/', '', $base64Data); } else { $extension = 'jpg'; } $imageData = base64_decode($base64Data); if ($imageData === false) { return null; } $filename = $folder . '/' . date('Ymd') . '_' . uniqid() . '.' . $extension; Storage::disk('public')->put($filename, $imageData); return $filename; } }