input('scenario_type', 'sales'); $stepId = $request->input('step_id'); // 캐시에서 상담 기록 조회 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 특정 단계 필터링 if ($stepId) { $consultations = array_filter($consultations, fn($c) => ($c['step_id'] ?? null) == $stepId); } // 최신순 정렬 usort($consultations, fn($a, $b) => strtotime($b['created_at']) - strtotime($a['created_at'])); return view('sales.modals.consultation-log', [ 'tenant' => $tenant, 'consultations' => $consultations, 'scenarioType' => $scenarioType, 'stepId' => $stepId, ]); } /** * 텍스트 상담 기록 저장 */ public function store(Request $request): JsonResponse { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', 'step_id' => 'nullable|integer', 'content' => 'required|string|max:5000', ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); $stepId = $request->input('step_id'); $content = $request->input('content'); // 캐시 키 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 새 상담 기록 추가 $consultation = [ 'id' => uniqid('cons_'), 'type' => 'text', 'content' => $content, 'step_id' => $stepId, 'created_by' => auth()->id(), 'created_by_name' => auth()->user()->name, 'created_at' => now()->toDateTimeString(), ]; $consultations[] = $consultation; // 캐시에 저장 (90일 유지) cache()->put($cacheKey, $consultations, now()->addDays(90)); return response()->json([ 'success' => true, 'consultation' => $consultation, ]); } /** * 상담 기록 삭제 */ public function destroy(string $consultationId, Request $request): JsonResponse { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); // 캐시 키 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 상담 기록 찾기 및 삭제 $found = false; foreach ($consultations as $index => $consultation) { if ($consultation['id'] === $consultationId) { // 파일이 있으면 삭제 if (isset($consultation['file_path'])) { Storage::delete($consultation['file_path']); } unset($consultations[$index]); $found = true; break; } } if (!$found) { return response()->json([ 'success' => false, 'message' => '상담 기록을 찾을 수 없습니다.', ], 404); } // 캐시에 저장 cache()->put($cacheKey, array_values($consultations), now()->addDays(90)); return response()->json([ 'success' => true, ]); } /** * 음성 파일 업로드 */ public function uploadAudio(Request $request): JsonResponse { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', 'step_id' => 'nullable|integer', 'audio' => 'required|file|mimes:webm,mp3,wav,ogg|max:51200', // 50MB 'transcript' => 'nullable|string|max:10000', 'duration' => 'nullable|integer', ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); $stepId = $request->input('step_id'); $transcript = $request->input('transcript'); $duration = $request->input('duration'); // 파일 저장 $file = $request->file('audio'); $fileName = 'audio_' . now()->format('Ymd_His') . '_' . uniqid() . '.' . $file->getClientOriginalExtension(); $path = $file->storeAs("tenant/consultations/{$tenantId}", $fileName, 'local'); // 캐시 키 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 새 상담 기록 추가 $consultation = [ 'id' => uniqid('cons_'), 'type' => 'audio', 'file_path' => $path, 'file_name' => $fileName, 'transcript' => $transcript, 'duration' => $duration, 'step_id' => $stepId, 'created_by' => auth()->id(), 'created_by_name' => auth()->user()->name, 'created_at' => now()->toDateTimeString(), ]; $consultations[] = $consultation; // 캐시에 저장 cache()->put($cacheKey, $consultations, now()->addDays(90)); return response()->json([ 'success' => true, 'consultation' => $consultation, ]); } /** * 첨부파일 업로드 */ public function uploadFile(Request $request): JsonResponse { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', 'step_id' => 'nullable|integer', 'file' => 'required|file|max:20480', // 20MB ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); $stepId = $request->input('step_id'); // 파일 저장 $file = $request->file('file'); $originalName = $file->getClientOriginalName(); $fileName = now()->format('Ymd_His') . '_' . uniqid() . '_' . $originalName; $path = $file->storeAs("tenant/attachments/{$tenantId}", $fileName, 'local'); // 캐시 키 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 새 상담 기록 추가 $consultation = [ 'id' => uniqid('cons_'), 'type' => 'file', 'file_path' => $path, 'file_name' => $originalName, 'file_size' => $file->getSize(), 'file_type' => $file->getMimeType(), 'step_id' => $stepId, 'created_by' => auth()->id(), 'created_by_name' => auth()->user()->name, 'created_at' => now()->toDateTimeString(), ]; $consultations[] = $consultation; // 캐시에 저장 cache()->put($cacheKey, $consultations, now()->addDays(90)); return response()->json([ 'success' => true, 'consultation' => $consultation, ]); } /** * 파일 삭제 */ public function deleteFile(string $fileId, Request $request): JsonResponse { return $this->destroy($fileId, $request); } /** * 파일 다운로드 URL 생성 */ public function getDownloadUrl(string $consultationId, Request $request): JsonResponse { $request->validate([ 'tenant_id' => 'required|integer|exists:tenants,id', 'scenario_type' => 'required|in:sales,manager', ]); $tenantId = $request->input('tenant_id'); $scenarioType = $request->input('scenario_type'); // 캐시 키 $cacheKey = "consultations:{$tenantId}:{$scenarioType}"; $consultations = cache()->get($cacheKey, []); // 상담 기록 찾기 $consultation = collect($consultations)->firstWhere('id', $consultationId); if (!$consultation || !isset($consultation['file_path'])) { return response()->json([ 'success' => false, 'message' => '파일을 찾을 수 없습니다.', ], 404); } // 임시 다운로드 URL 생성 (5분 유효) $url = Storage::temporaryUrl($consultation['file_path'], now()->addMinutes(5)); return response()->json([ 'success' => true, 'url' => $url, ]); } }