feat:영업권(명함등록) 시스템 구현
- TenantProspect 모델, 서비스, 컨트롤러 추가 - 명함 등록 시 2개월 영업권 부여 - 만료 후 1개월 쿨다운 기간 적용 - 테넌트 전환 기능 구현 - 사업자번호 중복 체크 API 추가 - 명함 이미지 업로드 지원 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
212
app/Http/Controllers/Sales/TenantProspectController.php
Normal file
212
app/Http/Controllers/Sales/TenantProspectController.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Sales;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Sales\TenantProspect;
|
||||
use App\Services\Sales\TenantProspectService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* 영업권(명함등록) 관리 컨트롤러
|
||||
*/
|
||||
class TenantProspectController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private TenantProspectService $service
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 목록 페이지
|
||||
*/
|
||||
public function index(Request $request): View|Response
|
||||
{
|
||||
if ($request->header('HX-Request')) {
|
||||
return response('', 200)->header('HX-Redirect', route('sales.prospects.index'));
|
||||
}
|
||||
|
||||
$filters = [
|
||||
'search' => $request->get('search'),
|
||||
'status' => $request->get('status'),
|
||||
'registered_by' => $request->get('registered_by'),
|
||||
];
|
||||
|
||||
$prospects = $this->service->getProspects($filters)->paginate(20);
|
||||
$stats = $this->service->getStats();
|
||||
|
||||
return view('sales.prospects.index', compact('prospects', 'stats'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록 폼
|
||||
*/
|
||||
public function create(Request $request): View|Response
|
||||
{
|
||||
// HTMX 요청이면 JavaScript 로드를 위해 전체 페이지로 리다이렉트
|
||||
if ($request->header('HX-Request')) {
|
||||
return response('', 200)->header('HX-Redirect', route('sales.prospects.create'));
|
||||
}
|
||||
|
||||
return view('sales.prospects.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* 등록 처리
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'business_number' => 'required|string|max:20',
|
||||
'company_name' => 'required|string|max:100',
|
||||
'ceo_name' => 'nullable|string|max:50',
|
||||
'contact_phone' => 'nullable|string|max:20',
|
||||
'contact_email' => 'nullable|email|max:100',
|
||||
'address' => 'nullable|string|max:500',
|
||||
'business_card' => 'nullable|image|max:5120',
|
||||
'memo' => 'nullable|string|max:1000',
|
||||
]);
|
||||
|
||||
// 등록 가능 여부 확인
|
||||
$checkResult = $this->service->canRegister($validated['business_number']);
|
||||
if (!$checkResult['can_register']) {
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', $checkResult['reason']);
|
||||
}
|
||||
|
||||
// 등록자는 현재 로그인 사용자
|
||||
$validated['registered_by'] = auth()->id();
|
||||
|
||||
$this->service->register(
|
||||
$validated,
|
||||
$request->file('business_card')
|
||||
);
|
||||
|
||||
return redirect()->route('sales.prospects.index')
|
||||
->with('success', '명함이 등록되었습니다. 2개월간 영업권이 유효합니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 상세 페이지
|
||||
*/
|
||||
public function show(int $id): View
|
||||
{
|
||||
$prospect = TenantProspect::with(['registeredBy', 'tenant', 'convertedBy'])
|
||||
->findOrFail($id);
|
||||
|
||||
return view('sales.prospects.show', compact('prospect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 수정 폼
|
||||
*/
|
||||
public function edit(int $id): View
|
||||
{
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
|
||||
// 이미 전환된 경우 수정 불가
|
||||
if ($prospect->isConverted()) {
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('error', '이미 테넌트로 전환된 영업권은 수정할 수 없습니다.');
|
||||
}
|
||||
|
||||
return view('sales.prospects.edit', compact('prospect'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 수정 처리
|
||||
*/
|
||||
public function update(Request $request, int $id)
|
||||
{
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
|
||||
// 이미 전환된 경우 수정 불가
|
||||
if ($prospect->isConverted()) {
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('error', '이미 테넌트로 전환된 영업권은 수정할 수 없습니다.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'company_name' => 'required|string|max:100',
|
||||
'ceo_name' => 'nullable|string|max:50',
|
||||
'contact_phone' => 'nullable|string|max:20',
|
||||
'contact_email' => 'nullable|email|max:100',
|
||||
'address' => 'nullable|string|max:500',
|
||||
'business_card' => 'nullable|image|max:5120',
|
||||
'memo' => 'nullable|string|max:1000',
|
||||
]);
|
||||
|
||||
$this->service->update(
|
||||
$prospect,
|
||||
$validated,
|
||||
$request->file('business_card')
|
||||
);
|
||||
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('success', '영업권 정보가 수정되었습니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 삭제 처리
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
|
||||
// 이미 전환된 경우 삭제 불가
|
||||
if ($prospect->isConverted()) {
|
||||
return redirect()->route('sales.prospects.index')
|
||||
->with('error', '이미 테넌트로 전환된 영업권은 삭제할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 본인 또는 관리자만 삭제 가능
|
||||
if ($prospect->registered_by !== auth()->id()) {
|
||||
// TODO: 관리자 권한 체크 추가
|
||||
}
|
||||
|
||||
$prospect->delete();
|
||||
|
||||
return redirect()->route('sales.prospects.index')
|
||||
->with('success', '영업권이 삭제되었습니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 테넌트 전환
|
||||
*/
|
||||
public function convert(int $id)
|
||||
{
|
||||
$prospect = TenantProspect::findOrFail($id);
|
||||
|
||||
// 이미 전환된 경우
|
||||
if ($prospect->isConverted()) {
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('error', '이미 테넌트로 전환되었습니다.');
|
||||
}
|
||||
|
||||
// 만료된 경우
|
||||
if ($prospect->isExpired()) {
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('error', '만료된 영업권은 전환할 수 없습니다.');
|
||||
}
|
||||
|
||||
$tenant = $this->service->convertToTenant($prospect, auth()->id());
|
||||
|
||||
return redirect()->route('sales.prospects.show', $id)
|
||||
->with('success', "테넌트로 전환되었습니다. (테넌트 ID: {$tenant->id})");
|
||||
}
|
||||
|
||||
/**
|
||||
* 사업자번호 중복 체크 (AJAX)
|
||||
*/
|
||||
public function checkBusinessNumber(Request $request)
|
||||
{
|
||||
$businessNumber = $request->get('business_number');
|
||||
$excludeId = $request->get('exclude_id');
|
||||
|
||||
$result = $this->service->canRegister($businessNumber, $excludeId);
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user