diff --git a/app/Http/Controllers/Finance/TradingPartnerController.php b/app/Http/Controllers/Finance/TradingPartnerController.php index 9ea40229..bc62ce27 100644 --- a/app/Http/Controllers/Finance/TradingPartnerController.php +++ b/app/Http/Controllers/Finance/TradingPartnerController.php @@ -48,6 +48,7 @@ public function index(Request $request): JsonResponse return [ 'id' => $partner->id, 'name' => $partner->name, + 'tradeType' => $partner->trade_type, 'type' => $partner->type, 'category' => $partner->category, 'bizNo' => $partner->biz_no, @@ -66,8 +67,9 @@ public function index(Request $request): JsonResponse $allPartners = TradingPartner::forTenant($tenantId); $stats = [ 'total' => (clone $allPartners)->count(), + 'sales' => (clone $allPartners)->where('trade_type', 'sales')->count(), + 'purchase' => (clone $allPartners)->where('trade_type', 'purchase')->count(), 'active' => (clone $allPartners)->where('status', 'active')->count(), - 'inactive' => (clone $allPartners)->where('status', 'inactive')->count(), ]; return response()->json([ @@ -90,6 +92,7 @@ public function store(Request $request): JsonResponse $partner = TradingPartner::create([ 'tenant_id' => $tenantId, 'name' => $request->input('name'), + 'trade_type' => $request->input('tradeType', 'sales'), 'type' => $request->input('type'), 'category' => $request->input('category'), 'biz_no' => $request->input('bizNo'), @@ -110,6 +113,7 @@ public function store(Request $request): JsonResponse 'data' => [ 'id' => $partner->id, 'name' => $partner->name, + 'tradeType' => $partner->trade_type, 'type' => $partner->type, 'category' => $partner->category, 'bizNo' => $partner->biz_no, @@ -139,6 +143,7 @@ public function update(Request $request, int $id): JsonResponse $partner->update([ 'name' => $request->input('name'), + 'trade_type' => $request->input('tradeType', $partner->trade_type), 'type' => $request->input('type'), 'category' => $request->input('category'), 'biz_no' => $request->input('bizNo'), @@ -159,6 +164,7 @@ public function update(Request $request, int $id): JsonResponse 'data' => [ 'id' => $partner->id, 'name' => $partner->name, + 'tradeType' => $partner->trade_type, 'type' => $partner->type, 'category' => $partner->category, 'bizNo' => $partner->biz_no, diff --git a/app/Models/Finance/TradingPartner.php b/app/Models/Finance/TradingPartner.php index b0276d8d..547f01de 100644 --- a/app/Models/Finance/TradingPartner.php +++ b/app/Models/Finance/TradingPartner.php @@ -14,6 +14,7 @@ class TradingPartner extends Model protected $fillable = [ 'tenant_id', 'name', + 'trade_type', 'type', 'category', 'biz_no', diff --git a/resources/views/finance/partners.blade.php b/resources/views/finance/partners.blade.php index 292ec702..d51884c1 100644 --- a/resources/views/finance/partners.blade.php +++ b/resources/views/finance/partners.blade.php @@ -50,10 +50,11 @@ function PartnersManagement() { const [partners, setPartners] = useState([]); - const [stats, setStats] = useState({ total: 0, active: 0, inactive: 0 }); + const [stats, setStats] = useState({ total: 0, sales: 0, purchase: 0, active: 0 }); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); + const [filterTradeType, setFilterTradeType] = useState('all'); const [filterType, setFilterType] = useState('all'); const [filterCategory, setFilterCategory] = useState('all'); @@ -68,6 +69,7 @@ function PartnersManagement() { const initialFormState = { name: '', + tradeType: 'sales', type: '', category: '', bizNo: '', @@ -105,9 +107,10 @@ function PartnersManagement() { const matchesSearch = item.name.toLowerCase().includes(searchTerm.toLowerCase()) || (item.ceo || '').toLowerCase().includes(searchTerm.toLowerCase()) || (item.manager || '').toLowerCase().includes(searchTerm.toLowerCase()); + const matchesTradeType = filterTradeType === 'all' || item.tradeType === filterTradeType; const matchesType = filterType === 'all' || item.type === filterType; const matchesCategory = filterCategory === 'all' || item.category === filterCategory; - return matchesSearch && matchesType && matchesCategory; + return matchesSearch && matchesTradeType && matchesType && matchesCategory; }); const handleAdd = () => { setModalMode('add'); setFormData(initialFormState); setShowModal(true); }; @@ -210,8 +213,8 @@ function PartnersManagement() { }; const handleDownload = () => { - const rows = [['거래처 관리'], [], ['거래처명', '대표자', '업태', '종목', '사업자번호', '주소', '연락처', '이메일', '담당자', '상태'], - ...filteredPartners.map(item => [item.name, item.ceo || '', item.type || '', item.category || '', item.bizNo, item.address || '', item.contact, item.email, item.manager, item.status === 'active' ? '활성' : '비활성'])]; + const rows = [['거래처 관리'], [], ['거래구분', '거래처명', '대표자', '업태', '종목', '사업자번호', '주소', '연락처', '이메일', '담당자', '상태'], + ...filteredPartners.map(item => [item.tradeType === 'purchase' ? '매입' : '매출', item.name, item.ceo || '', item.type || '', item.category || '', item.bizNo, item.address || '', 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(); @@ -233,27 +236,36 @@ function PartnersManagement() { -
+
총 거래처

{stats.total}개

+
+
매출
+

{stats.sales}개

+
+
+
매입
+

{stats.purchase}개

+
활성

{stats.active}개

-
-
비활성
-

{stats.inactive}개

-
-
+
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" />
+
+ {[{v:'all',l:'전체'},{v:'sales',l:'매출'},{v:'purchase',l:'매입'}].map(o => ( + + ))} +
@@ -279,7 +291,7 @@ function PartnersManagement() { 데이터가 없습니다. ) : filteredPartners.map(item => ( handleEdit(item)}> -

{item.name}

{item.bizNo &&

{item.bizNo}

} +
{item.tradeType === 'purchase' ? '매입' : '매출'}

{item.name}

{item.bizNo &&

{item.bizNo}

} {item.ceo || '-'} {item.type && {item.type}}{item.category &&

{item.category}

}

{item.contact || item.email}

@@ -325,6 +337,21 @@ 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, bizNo: e.target.value }))} placeholder="123-45-67890" className="w-full px-3 py-2 border border-gray-300 rounded-lg" />