171 lines
5.4 KiB
PHP
171 lines
5.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Http\Controllers\Sales;
|
||
|
|
|
||
|
|
use App\Http\Controllers\Controller;
|
||
|
|
use App\Models\Sales\SalesManager;
|
||
|
|
use App\Models\Sales\SalesProspect;
|
||
|
|
use App\Models\Sales\SalesProspectProduct;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\Http\Response;
|
||
|
|
use Illuminate\View\View;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 가망고객 관리 컨트롤러
|
||
|
|
*/
|
||
|
|
class SalesProspectController extends Controller
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* 목록 페이지
|
||
|
|
*/
|
||
|
|
public function index(Request $request): View|Response
|
||
|
|
{
|
||
|
|
if ($request->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',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$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',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$prospect->update($validated);
|
||
|
|
|
||
|
|
return redirect()->route('sales.prospects.show', $prospect->id)
|
||
|
|
->with('success', '가망고객 정보가 수정되었습니다.');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 삭제 처리
|
||
|
|
*/
|
||
|
|
public function destroy(int $id)
|
||
|
|
{
|
||
|
|
$prospect = SalesProspect::findOrFail($id);
|
||
|
|
$prospect->delete();
|
||
|
|
|
||
|
|
return redirect()->route('sales.prospects.index')
|
||
|
|
->with('success', '가망고객이 삭제되었습니다.');
|
||
|
|
}
|
||
|
|
}
|