feat: [business-card] 3단계 워크플로우 구현 (요청→제작의뢰→처리완료)

- 모델: STATUS_ORDERED 추가, markAsOrdered() 헬퍼
- 서비스: order(), getOrderedRequests() 추가
- 컨트롤러: order() 액션 추가
- 관리자 뷰: 좌측 신규요청 + 우측 제작중 + 하단 처리완료
- 파트너 뷰: 제작중(파란) 상태 뱃지 추가
- 라우트: POST business-cards/{id}/order 추가
This commit is contained in:
김보곤
2026-02-25 05:41:34 +09:00
parent 51e2525b6f
commit 85c7a55d00
6 changed files with 256 additions and 72 deletions

View File

@@ -30,7 +30,7 @@ public function index(Request $request): View|Response
}
/**
* 명함신청 처리 (관리자 전용 - 대기/완료 2분할)
* 명함신청 처리 (관리자 전용)
*/
public function manage(Request $request): View|Response
{
@@ -45,11 +45,13 @@ public function manage(Request $request): View|Response
$search = $request->get('search');
$stats = $this->service->getStats();
$pendingRequests = $this->service->getPendingRequests($search);
$orderedRequests = $this->service->getOrderedRequests($search);
$processedRequests = $this->service->getProcessedRequests($search);
return view('sales.business-cards.admin-index', compact(
'stats',
'pendingRequests',
'orderedRequests',
'processedRequests',
'search'
));
@@ -75,6 +77,28 @@ public function store(Request $request)
->with('success', '명함 신청이 완료되었습니다.');
}
/**
* 제작의뢰 (관리자 전용)
*/
public function order(Request $request, int $id)
{
if (! auth()->user()->isAdmin()) {
abort(403, '관리자만 처리할 수 있습니다.');
}
$this->service->order($id);
if ($request->expectsJson() || $request->header('Accept') === 'application/json') {
return response()->json([
'success' => true,
'message' => '제작의뢰 처리되었습니다.',
]);
}
return redirect()->route('sales.business-cards.manage')
->with('success', '제작의뢰 처리되었습니다.');
}
/**
* 처리 완료 (관리자 전용)
*/

View File

@@ -10,10 +10,13 @@ class BusinessCardRequest extends Model
{
public const STATUS_PENDING = 'pending';
public const STATUS_ORDERED = 'ordered';
public const STATUS_PROCESSED = 'processed';
public const STATUS_LABELS = [
self::STATUS_PENDING => '신청대기',
self::STATUS_PENDING => '요청',
self::STATUS_ORDERED => '제작의뢰',
self::STATUS_PROCESSED => '처리완료',
];
@@ -27,12 +30,15 @@ class BusinessCardRequest extends Model
'quantity',
'memo',
'status',
'ordered_by',
'ordered_at',
'processed_by',
'processed_at',
'process_memo',
];
protected $casts = [
'ordered_at' => 'datetime',
'processed_at' => 'datetime',
'quantity' => 'integer',
];
@@ -51,6 +57,11 @@ public function requester(): BelongsTo
return $this->belongsTo(User::class, 'user_id');
}
public function orderer(): BelongsTo
{
return $this->belongsTo(User::class, 'ordered_by');
}
public function processor(): BelongsTo
{
return $this->belongsTo(User::class, 'processed_by');
@@ -65,6 +76,11 @@ public function scopePending($query)
return $query->where('status', self::STATUS_PENDING);
}
public function scopeOrdered($query)
{
return $query->where('status', self::STATUS_ORDERED);
}
public function scopeProcessed($query)
{
return $query->where('status', self::STATUS_PROCESSED);
@@ -89,16 +105,34 @@ public function getIsPendingAttribute(): bool
return $this->status === self::STATUS_PENDING;
}
public function getIsOrderedAttribute(): bool
{
return $this->status === self::STATUS_ORDERED;
}
// =========================================================================
// 헬퍼 메서드
// =========================================================================
public function markAsProcessed(int $processedBy, ?string $memo = null): bool
public function markAsOrdered(int $orderedBy): bool
{
if (! $this->is_pending) {
return false;
}
$this->status = self::STATUS_ORDERED;
$this->ordered_by = $orderedBy;
$this->ordered_at = now();
return $this->save();
}
public function markAsProcessed(int $processedBy, ?string $memo = null): bool
{
if (! $this->is_ordered) {
return false;
}
$this->status = self::STATUS_PROCESSED;
$this->processed_by = $processedBy;
$this->processed_at = now();

View File

@@ -7,13 +7,15 @@
class BusinessCardRequestService
{
/**
* 뱃지용 대기 건수
* 뱃지용 대기 건수 (요청 + 제작의뢰)
*/
public function getPendingCount(): int
{
$tenantId = session('selected_tenant_id', 1);
return BusinessCardRequest::ofTenant($tenantId)->pending()->count();
return BusinessCardRequest::ofTenant($tenantId)
->whereIn('status', [BusinessCardRequest::STATUS_PENDING, BusinessCardRequest::STATUS_ORDERED])
->count();
}
/**
@@ -26,6 +28,7 @@ public function getStats(): array
return [
'pending' => (clone $base)->pending()->count(),
'ordered' => (clone $base)->ordered()->count(),
'processed_today' => (clone $base)->processed()
->whereDate('processed_at', today())
->count(),
@@ -34,26 +37,25 @@ public function getStats(): array
}
/**
* 대기 목록
* 신규 요청 목록
*/
public function getPendingRequests(?string $search = null, int $perPage = 20)
{
$tenantId = session('selected_tenant_id', 1);
$query = BusinessCardRequest::ofTenant($tenantId)
->pending()
return $this->buildQuery(BusinessCardRequest::STATUS_PENDING, $search)
->with('requester')
->latest();
->latest()
->paginate($perPage, ['*'], 'pending_page');
}
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('phone', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
}
return $query->paginate($perPage, ['*'], 'pending_page');
/**
* 제작의뢰 목록
*/
public function getOrderedRequests(?string $search = null, int $perPage = 20)
{
return $this->buildQuery(BusinessCardRequest::STATUS_ORDERED, $search)
->with(['requester', 'orderer'])
->latest('ordered_at')
->paginate($perPage, ['*'], 'ordered_page');
}
/**
@@ -61,22 +63,10 @@ public function getPendingRequests(?string $search = null, int $perPage = 20)
*/
public function getProcessedRequests(?string $search = null, int $perPage = 20)
{
$tenantId = session('selected_tenant_id', 1);
$query = BusinessCardRequest::ofTenant($tenantId)
->processed()
return $this->buildQuery(BusinessCardRequest::STATUS_PROCESSED, $search)
->with(['requester', 'processor'])
->latest('processed_at');
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('phone', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
}
return $query->paginate($perPage, ['*'], 'processed_page');
->latest('processed_at')
->paginate($perPage, ['*'], 'processed_page');
}
/**
@@ -105,6 +95,18 @@ public function createRequest(array $data): BusinessCardRequest
return BusinessCardRequest::create($data);
}
/**
* 제작의뢰
*/
public function order(int $id): BusinessCardRequest
{
$tenantId = session('selected_tenant_id', 1);
$request = BusinessCardRequest::ofTenant($tenantId)->findOrFail($id);
$request->markAsOrdered(auth()->id());
return $request;
}
/**
* 처리 완료
*/
@@ -116,4 +118,20 @@ public function process(int $id, ?string $memo = null): BusinessCardRequest
return $request;
}
private function buildQuery(string $status, ?string $search)
{
$tenantId = session('selected_tenant_id', 1);
$query = BusinessCardRequest::ofTenant($tenantId)->where('status', $status);
if ($search) {
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('phone', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
}
return $query;
}
}

View File

@@ -1,30 +1,36 @@
@extends('layouts.app')
@section('title', '명함신청 리')
@section('title', '명함신청 리')
@section('content')
<div class="flex flex-col h-full">
<!-- 페이지 헤더 -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4 flex-shrink-0">
<div>
<h1 class="text-2xl font-bold text-gray-800">명함신청 </h1>
<p class="text-sm text-gray-500 mt-1">영업파트너의 명함 신청을 확인하고 처리합니다</p>
<h1 class="text-2xl font-bold text-gray-800">명함신청 </h1>
<p class="text-sm text-gray-500 mt-1">
요청 <span class="text-blue-600 font-medium">제작의뢰</span> <span class="text-emerald-600 font-medium">처리완료</span>
</p>
</div>
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-3 gap-4 mb-4 flex-shrink-0">
<div class="grid grid-cols-4 gap-3 mb-4 flex-shrink-0">
<div class="bg-yellow-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-yellow-600"> 대기</div>
<div class="text-xs text-yellow-600"> 요청</div>
<div class="text-xl font-bold text-yellow-800">{{ number_format($stats['pending']) }}</div>
</div>
<div class="bg-blue-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-blue-600">제작의뢰</div>
<div class="text-xl font-bold text-blue-800">{{ number_format($stats['ordered']) }}</div>
</div>
<div class="bg-emerald-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-emerald-600">오늘 처리</div>
<div class="text-xl font-bold text-emerald-800">{{ number_format($stats['processed_today']) }}</div>
</div>
<div class="bg-blue-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-blue-600">전체 신청</div>
<div class="text-xl font-bold text-blue-800">{{ number_format($stats['total']) }}</div>
<div class="bg-gray-50 rounded-lg shadow-sm p-3">
<div class="text-xs text-gray-500">전체</div>
<div class="text-xl font-bold text-gray-700">{{ number_format($stats['total']) }}</div>
</div>
</div>
@@ -44,15 +50,15 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</form>
</div>
<!-- 2분할 레이아웃 -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 flex-1 min-h-0">
<!-- 좌측: 대기 -->
<!-- 2분할: 신규 요청 / 제작의뢰 -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-4" style="min-height: 300px;">
<!-- 좌측: 요청 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex flex-col min-h-0">
<div class="bg-yellow-500 text-white px-4 py-3 flex items-center gap-2 flex-shrink-0">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="font-semibold"> 대기</span>
<span class="font-semibold"> 요청</span>
<span class="ml-auto bg-yellow-600 px-2 py-0.5 rounded-full text-xs">{{ $pendingRequests->total() }}</span>
</div>
<div class="overflow-y-auto flex-1">
@@ -67,7 +73,7 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($pendingRequests as $req)
<tr class="hover:bg-yellow-50" id="pending-row-{{ $req->id }}">
<tr class="hover:bg-yellow-50">
<td class="px-4 py-3">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
@@ -82,15 +88,15 @@ class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none foc
</td>
<td class="px-4 py-3 text-center">
<button type="button"
onclick="processRequest({{ $req->id }}, '{{ $req->name }}')"
class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-medium rounded transition">
처리완료
onclick="orderRequest({{ $req->id }}, '{{ $req->name }}')"
class="px-3 py-1 bg-blue-500 hover:bg-blue-600 text-white text-xs font-medium rounded transition">
제작의뢰
</button>
</td>
</tr>
@if($req->memo)
<tr class="bg-yellow-25">
<td colspan="4" class="px-4 py-1">
<tr>
<td colspan="4" class="px-4 py-1 bg-yellow-50">
<div class="text-xs text-gray-500"><span class="font-medium">메모:</span> {{ $req->memo }}</div>
</td>
</tr>
@@ -101,7 +107,7 @@ class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-med
<svg class="w-12 h-12 mx-auto text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
대기 중인 명함 청이 없습니다.
신규 청이 없습니다.
</td>
</tr>
@endforelse
@@ -115,14 +121,14 @@ class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-med
@endif
</div>
<!-- 우측: 처리 완료 -->
<!-- 우측: 제작의뢰 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex flex-col min-h-0">
<div class="bg-emerald-500 text-white px-4 py-3 flex items-center gap-2 flex-shrink-0">
<div class="bg-blue-500 text-white px-4 py-3 flex items-center gap-2 flex-shrink-0">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
<span class="font-semibold">처리 완료</span>
<span class="ml-auto bg-emerald-600 px-2 py-0.5 rounded-full text-xs">{{ $processedRequests->total() }}</span>
<span class="font-semibold">제작 </span>
<span class="ml-auto bg-blue-600 px-2 py-0.5 rounded-full text-xs">{{ $orderedRequests->total() }}</span>
</div>
<div class="overflow-y-auto flex-1">
<table class="min-w-full divide-y divide-gray-200">
@@ -131,12 +137,13 @@ class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-med
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">신청자</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">연락처</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">수량</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">처리</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">의뢰</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">처리</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($processedRequests as $req)
<tr class="hover:bg-emerald-50">
@forelse($orderedRequests as $req)
<tr class="hover:bg-blue-50">
<td class="px-4 py-3">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
@@ -149,38 +156,136 @@ class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-med
{{ number_format($req->quantity) }}
</td>
<td class="px-4 py-3">
<div class="text-xs text-gray-700">{{ $req->processed_at?->format('m/d H:i') }}</div>
<div class="text-xs text-gray-400">{{ $req->processor?->name }}</div>
<div class="text-xs text-gray-700">{{ $req->ordered_at?->format('m/d H:i') }}</div>
<div class="text-xs text-gray-400">{{ $req->orderer?->name }}</div>
</td>
<td class="px-4 py-3 text-center">
<button type="button"
onclick="processRequest({{ $req->id }}, '{{ $req->name }}')"
class="px-3 py-1 bg-emerald-500 hover:bg-emerald-600 text-white text-xs font-medium rounded transition">
처리완료
</button>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="px-4 py-8 text-center text-gray-500 text-sm">
<td colspan="5" class="px-4 py-8 text-center text-gray-500 text-sm">
<svg class="w-12 h-12 mx-auto text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
</svg>
처리된 명함 신청 없습니다.
제작의뢰 중인 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($processedRequests->hasPages())
@if($orderedRequests->hasPages())
<div class="px-4 py-2 border-t border-gray-200 flex-shrink-0 bg-gray-50">
{{ $processedRequests->withQueryString()->links() }}
{{ $orderedRequests->withQueryString()->links() }}
</div>
@endif
</div>
</div>
<!-- 하단: 처리 완료 -->
<div class="bg-white rounded-lg shadow-sm overflow-hidden flex-shrink-0">
<div class="bg-emerald-500 text-white px-4 py-3 flex items-center gap-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span class="font-semibold">처리 완료</span>
<span class="ml-auto bg-emerald-600 px-2 py-0.5 rounded-full text-xs">{{ $processedRequests->total() }}</span>
</div>
<div class="overflow-x-auto" style="max-height: 300px; overflow-y: auto;">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 sticky top-0">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">신청자</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">연락처</th>
<th class="px-4 py-2 text-center text-xs font-medium text-gray-500 uppercase">수량</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">의뢰일</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">처리일</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">처리자</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@forelse($processedRequests as $req)
<tr class="hover:bg-emerald-50">
<td class="px-4 py-2">
<div class="font-medium text-gray-900 text-sm">{{ $req->name }}</div>
<div class="text-xs text-gray-500">{{ $req->title ?: '-' }}</div>
</td>
<td class="px-4 py-2">
<div class="text-sm text-gray-900">{{ $req->phone }}</div>
</td>
<td class="px-4 py-2 text-center text-sm text-gray-700">
{{ number_format($req->quantity) }}
</td>
<td class="px-4 py-2 text-xs text-gray-500">
{{ $req->ordered_at?->format('m/d H:i') ?? '-' }}
</td>
<td class="px-4 py-2 text-xs text-gray-700">
{{ $req->processed_at?->format('m/d H:i') }}
</td>
<td class="px-4 py-2 text-xs text-gray-500">
{{ $req->processor?->name }}
</td>
</tr>
@empty
<tr>
<td colspan="6" class="px-4 py-6 text-center text-gray-500 text-sm">
처리된 명함 신청이 없습니다.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($processedRequests->hasPages())
<div class="px-4 py-2 border-t border-gray-200 bg-gray-50">
{{ $processedRequests->withQueryString()->links() }}
</div>
@endif
</div>
</div>
@endsection
@push('scripts')
<script>
function orderRequest(id, name) {
showConfirm(
`<strong>${name}</strong>님의 명함을 제작의뢰 하시겠습니까?`,
() => {
fetch(`/sales/business-cards/${id}/order`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast(data.message, 'success');
window.location.reload();
} else {
showToast(data.message || '처리에 실패했습니다.', 'error');
}
})
.catch(error => {
showToast('서버 오류가 발생했습니다.', 'error');
console.error(error);
});
},
{ title: '제작의뢰', icon: 'question', confirmText: '의뢰하기' }
);
}
function processRequest(id, name) {
showConfirm(
`<strong>${name}</strong>님의 명함 신청을 처리완료 하시겠습니까?`,
`<strong>${name}</strong>님의 명함 제작이 완료되었습니까?`,
() => {
fetch(`/sales/business-cards/${id}/process`, {
method: 'POST',
@@ -204,7 +309,7 @@ function processRequest(id, name) {
console.error(error);
});
},
{ title: '처리 확인', icon: 'question', confirmText: '처리완료' }
{ title: '처리 완료', icon: 'question', confirmText: '처리완료' }
);
}
</script>

View File

@@ -118,7 +118,9 @@ class="w-full sm:w-auto px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white font-
<td class="px-4 py-3 text-sm text-gray-700 text-center">{{ number_format($req->quantity) }}</td>
<td class="px-4 py-3 text-center">
@if($req->status === 'pending')
<span class="px-2 py-0.5 text-xs font-medium rounded-full bg-yellow-100 text-yellow-800">대기중</span>
<span class="px-2 py-0.5 text-xs font-medium rounded-full bg-yellow-100 text-yellow-800">요청</span>
@elseif($req->status === 'ordered')
<span class="px-2 py-0.5 text-xs font-medium rounded-full bg-blue-100 text-blue-800">제작중</span>
@else
<span class="px-2 py-0.5 text-xs font-medium rounded-full bg-emerald-100 text-emerald-800">처리완료</span>
@endif

View File

@@ -1287,6 +1287,7 @@
Route::get('business-cards', [\App\Http\Controllers\Sales\BusinessCardRequestController::class, 'index'])->name('business-cards.index');
Route::post('business-cards', [\App\Http\Controllers\Sales\BusinessCardRequestController::class, 'store'])->name('business-cards.store');
Route::get('business-cards/manage', [\App\Http\Controllers\Sales\BusinessCardRequestController::class, 'manage'])->name('business-cards.manage');
Route::post('business-cards/{id}/order', [\App\Http\Controllers\Sales\BusinessCardRequestController::class, 'order'])->name('business-cards.order');
Route::post('business-cards/{id}/process', [\App\Http\Controllers\Sales\BusinessCardRequestController::class, 'process'])->name('business-cards.process');
// 매니저 검색 (리소스 라우트보다 먼저 정의해야 함!)