diff --git a/app/Http/Controllers/Finance/TradingPartnerController.php b/app/Http/Controllers/Finance/TradingPartnerController.php index 1e7c3fc6..ddac7e66 100644 --- a/app/Http/Controllers/Finance/TradingPartnerController.php +++ b/app/Http/Controllers/Finance/TradingPartnerController.php @@ -63,9 +63,8 @@ public function index(Request $request): JsonResponse $allPartners = TradingPartner::forTenant($tenantId); $stats = [ 'total' => (clone $allPartners)->count(), - 'vendor' => (clone $allPartners)->where('type', 'vendor')->count(), - 'freelancer' => (clone $allPartners)->where('type', 'freelancer')->count(), 'active' => (clone $allPartners)->where('status', 'active')->count(), + 'inactive' => (clone $allPartners)->where('status', 'inactive')->count(), ]; return response()->json([ @@ -79,8 +78,8 @@ public function store(Request $request): JsonResponse { $request->validate([ 'name' => 'required|string|max:100', - 'type' => 'required|in:vendor,freelancer', - 'category' => 'required|string|max:50', + 'type' => 'nullable|string|max:100', + 'category' => 'nullable|string|max:100', ]); $tenantId = session('selected_tenant_id', 1); @@ -88,8 +87,8 @@ public function store(Request $request): JsonResponse $partner = TradingPartner::create([ 'tenant_id' => $tenantId, 'name' => $request->input('name'), - 'type' => $request->input('type', 'vendor'), - 'category' => $request->input('category', '기타'), + 'type' => $request->input('type'), + 'category' => $request->input('category'), 'biz_no' => $request->input('bizNo'), 'bank_account' => $request->input('bankAccount'), 'contact' => $request->input('contact'), @@ -127,8 +126,8 @@ public function update(Request $request, int $id): JsonResponse $request->validate([ 'name' => 'required|string|max:100', - 'type' => 'required|in:vendor,freelancer', - 'category' => 'required|string|max:50', + 'type' => 'nullable|string|max:100', + 'category' => 'nullable|string|max:100', ]); $partner->update([ diff --git a/app/Services/TradingPartnerOcrService.php b/app/Services/TradingPartnerOcrService.php index fae06ac4..419136b9 100644 --- a/app/Services/TradingPartnerOcrService.php +++ b/app/Services/TradingPartnerOcrService.php @@ -283,21 +283,7 @@ private function normalizeData(array $data): array } } - // memo: 주소 + 업태 + 종목 조합 - $memoParts = []; $address = trim($data['address'] ?? ''); - $bizType = trim($data['biz_type'] ?? ''); - $bizItem = trim($data['biz_item'] ?? ''); - - if ($address) { - $memoParts[] = "[주소] {$address}"; - } - if ($bizType) { - $memoParts[] = "[업태] {$bizType}"; - } - if ($bizItem) { - $memoParts[] = "[종목] {$bizItem}"; - } return [ 'name' => trim($data['company_name'] ?? ''), @@ -305,7 +291,9 @@ private function normalizeData(array $data): array 'manager' => trim($data['ceo_name'] ?? ''), 'contact' => trim($data['contact_phone'] ?? ''), 'email' => trim($data['email'] ?? ''), - 'memo' => implode(' / ', $memoParts), + 'type' => trim($data['biz_type'] ?? ''), + 'category' => trim($data['biz_item'] ?? ''), + 'memo' => $address ? "[주소] {$address}" : '', ]; } } diff --git a/resources/views/finance/partners.blade.php b/resources/views/finance/partners.blade.php index 5e7fcb2a..cc346378 100644 --- a/resources/views/finance/partners.blade.php +++ b/resources/views/finance/partners.blade.php @@ -43,15 +43,14 @@ const Trash2 = createIcon('trash-2'); const Phone = createIcon('phone'); const Mail = createIcon('mail'); -const Truck = createIcon('truck'); -const Hammer = createIcon('hammer'); +const ScanLine = createIcon('scan-line'); const Upload = createIcon('upload'); const FileText = createIcon('file-text'); const Loader = createIcon('loader'); function PartnersManagement() { const [partners, setPartners] = useState([]); - const [stats, setStats] = useState({ total: 0, vendor: 0, freelancer: 0, active: 0 }); + const [stats, setStats] = useState({ total: 0, active: 0, inactive: 0 }); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); @@ -67,13 +66,10 @@ function PartnersManagement() { const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); - const types = [{ value: 'vendor', label: '공급업체' }, { value: 'freelancer', label: '프리랜서' }]; - const categories = ['클라우드', '외주개발', '차량관리', '보험', '사무용품', '마케팅', '법률/회계', '기타']; - const initialFormState = { name: '', - type: 'vendor', - category: '기타', + type: '', + category: '', bizNo: '', bankAccount: '', contact: '', @@ -188,6 +184,8 @@ function PartnersManagement() { ...prev, name: d.name || prev.name, bizNo: d.bizNo || prev.bizNo, + type: d.type || prev.type, + category: d.category || prev.category, manager: d.manager || prev.manager, contact: d.contact || prev.contact, email: d.email || prev.email, @@ -208,15 +206,13 @@ function PartnersManagement() { }; const handleDownload = () => { - const rows = [['거래처 관리'], [], ['거래처명', '유형', '분류', '사업자번호', '연락처', '이메일', '담당자', '상태'], - ...filteredPartners.map(item => [item.name, item.type === 'vendor' ? '공급업체' : '프리랜서', item.category, item.bizNo, item.contact, item.email, item.manager, item.status === 'active' ? '활성' : '비활성'])]; + const rows = [['거래처 관리'], [], ['거래처명', '업태', '종목', '사업자번호', '연락처', '이메일', '담당자', '상태'], + ...filteredPartners.map(item => [item.name, item.type || '', item.category || '', item.bizNo, item.contact, item.email, item.manager, item.status === 'active' ? '활성' : '비활성'])]; const csvContent = rows.map(row => row.join(',')).join('\n'); const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = '거래처목록.csv'; link.click(); }; - const getTypeIcon = (type) => type === 'vendor' ? : ; - const getTypeColor = (type) => type === 'vendor' ? 'bg-blue-100 text-blue-700' : 'bg-purple-100 text-purple-700'; return (
@@ -233,23 +229,19 @@ function PartnersManagement() {
-
+
총 거래처

{stats.total}개

-
-
공급업체
-

{stats.vendor}개

-
-
-
프리랜서
-

{stats.freelancer}개

-
활성

{stats.active}개

+
+
비활성
+

{stats.inactive}개

+
@@ -258,8 +250,8 @@ function PartnersManagement() { setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-emerald-500" />
- - + +
@@ -268,8 +260,8 @@ function PartnersManagement() { 거래처명 - 유형 - 분류 + 업태 + 종목 연락처 담당자 상태 @@ -284,7 +276,7 @@ function PartnersManagement() { ) : filteredPartners.map(item => ( handleEdit(item)}>

{item.name}

{item.bizNo &&

{item.bizNo}

} - {getTypeIcon(item.type)}{item.type === 'vendor' ? '공급업체' : '프리랜서'} + {item.type || '-'} {item.category}

{item.contact || item.email}

{item.manager}

{item.managerPhone &&

{item.managerPhone}

} @@ -331,8 +323,8 @@ className={`mb-4 border-2 border-dashed rounded-xl p-6 text-center cursor-pointe
setFormData(prev => ({ ...prev, name: e.target.value }))} placeholder="거래처명" className="w-full px-3 py-2 border border-gray-300 rounded-lg" />
-
-
+
setFormData(prev => ({ ...prev, type: e.target.value }))} placeholder="제조업, 서비스업, 도소매업 등" className="w-full px-3 py-2 border border-gray-300 rounded-lg" />
+
setFormData(prev => ({ ...prev, category: e.target.value }))} placeholder="소프트웨어 개발, 블라인드 등" className="w-full px-3 py-2 border border-gray-300 rounded-lg" />
setFormData(prev => ({ ...prev, bizNo: e.target.value }))} placeholder="123-45-67890" className="w-full px-3 py-2 border border-gray-300 rounded-lg" />