fix:정산관리 입금등록 버튼 제거 및 내보내기 엑셀 기능 구현
- 입금 등록 버튼 및 모달 제거 - 내보내기 버튼을 모든 탭에서 동작하도록 변경 - 현재 활성 탭(수당관리/고객사정산/구독관리)의 테이블을 CSV로 내보내기 - UTF-8 BOM 포함하여 엑셀에서 한글 정상 표시 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,22 +12,13 @@
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button type="button"
|
||||
x-show="activeTab === 'commission'"
|
||||
onclick="openPaymentModal()"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white rounded-lg transition-colors">
|
||||
<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 4v16m8-8H4"/>
|
||||
</svg>
|
||||
입금 등록
|
||||
</button>
|
||||
<a x-show="activeTab === 'commission'"
|
||||
href="{{ route('finance.sales-commissions.export', ['year' => $year, 'month' => $month]) }}"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-lg transition-colors">
|
||||
onclick="exportCurrentTable()"
|
||||
class="inline-flex items-center gap-2 px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-lg transition-colors">
|
||||
<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 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
내보내기
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,25 +133,6 @@ class="px-4 py-1.5 text-sm font-medium rounded-md transition-all">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 입금 등록 모달 --}}
|
||||
<div id="payment-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden flex items-center justify-center">
|
||||
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div class="p-6 border-b border-gray-200">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-lg font-semibold text-gray-800">입금 등록</h3>
|
||||
<button type="button" onclick="closePaymentModal()" class="text-gray-400 hover:text-gray-600">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="payment-form-container" class="p-6">
|
||||
@include('finance.settlement.partials.commission.payment-form', ['management' => null, 'pendingTenants' => $pendingTenants])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 상세 모달 --}}
|
||||
<div id="detail-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden flex items-center justify-center">
|
||||
<div class="bg-white rounded-lg shadow-xl max-w-3xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
@@ -205,42 +177,6 @@ function toggleSelectAll(checkbox) {
|
||||
updateSelection();
|
||||
}
|
||||
|
||||
function openPaymentModal() {
|
||||
document.getElementById('payment-modal').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function closePaymentModal() {
|
||||
document.getElementById('payment-modal').classList.add('hidden');
|
||||
}
|
||||
|
||||
function submitPayment() {
|
||||
const form = document.getElementById('payment-form');
|
||||
const formData = new FormData(form);
|
||||
|
||||
fetch('{{ route("finance.sales-commissions.payment") }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
alert(data.message);
|
||||
closePaymentModal();
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || '오류가 발생했습니다.');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('오류가 발생했습니다.');
|
||||
});
|
||||
}
|
||||
|
||||
function openDetailModal(commissionId) {
|
||||
fetch('{{ url("finance/sales-commissions") }}/' + commissionId + '/detail')
|
||||
.then(response => response.text())
|
||||
@@ -398,11 +334,109 @@ function formatCommissionInput(el) {
|
||||
el.value = raw ? Number(raw).toLocaleString() : '';
|
||||
}
|
||||
|
||||
function onTenantSelect(managementId) {
|
||||
if (!managementId) return;
|
||||
htmx.ajax('GET', '{{ route("finance.sales-commissions.payment-form") }}?management_id=' + managementId, {
|
||||
target: '#payment-form-container'
|
||||
});
|
||||
function exportCurrentTable() {
|
||||
// 현재 활성 탭 감지
|
||||
const activeTabEl = document.querySelector('[x-data]');
|
||||
const activeTab = activeTabEl ? activeTabEl.__x.$data.activeTab : 'commission';
|
||||
|
||||
let table, filename;
|
||||
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
||||
|
||||
if (activeTab === 'commission') {
|
||||
// 수당 관리 - 현재 보이는 서브탭 테이블
|
||||
const subTab = activeTabEl.__x.$data.commissionSubTab;
|
||||
if (subTab === 'manager') {
|
||||
table = document.querySelector('#manager-table-container table');
|
||||
filename = `매니저수당_${today}.csv`;
|
||||
} else {
|
||||
table = document.querySelector('#commission-table-container table');
|
||||
filename = `영업파트너수당_${today}.csv`;
|
||||
}
|
||||
} else if (activeTab === 'customer') {
|
||||
table = document.querySelector('#customer-content table');
|
||||
filename = `고객사정산_${today}.csv`;
|
||||
} else if (activeTab === 'subscription') {
|
||||
table = document.querySelector('#subscription-content table');
|
||||
filename = `구독관리_${today}.csv`;
|
||||
}
|
||||
|
||||
if (!table) {
|
||||
alert('내보낼 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 테이블 → CSV 변환
|
||||
const rows = [];
|
||||
const thead = table.querySelector('thead');
|
||||
const tbody = table.querySelector('tbody');
|
||||
|
||||
// 헤더 추출 (체크박스/액션 컬럼 제외)
|
||||
if (thead) {
|
||||
const headerRow = [];
|
||||
thead.querySelectorAll('th').forEach(th => {
|
||||
const text = th.textContent.trim();
|
||||
// 체크박스(빈 헤더)와 액션 컬럼 제외
|
||||
if (text && text !== '액션') {
|
||||
headerRow.push(text);
|
||||
}
|
||||
});
|
||||
rows.push(headerRow);
|
||||
}
|
||||
|
||||
// 본문 추출
|
||||
if (tbody) {
|
||||
tbody.querySelectorAll('tr').forEach(tr => {
|
||||
// 빈 메시지 행 제외
|
||||
if (tr.querySelector('td[colspan]')) return;
|
||||
|
||||
const row = [];
|
||||
tr.querySelectorAll('td').forEach(td => {
|
||||
// 체크박스 셀 제외 (input[type=checkbox]만 있는 셀)
|
||||
if (td.querySelector('input[type="checkbox"].commission-checkbox') || (td.querySelector('input[type="checkbox"]') && !td.textContent.trim())) return;
|
||||
// 액션 버튼 셀 제외
|
||||
if (td.querySelector('button[onclick*="openDetailModal"]')) return;
|
||||
|
||||
// input 값 우선, 없으면 텍스트
|
||||
const dateInput = td.querySelector('input[type="date"]');
|
||||
const textInput = td.querySelector('input[type="text"]');
|
||||
let text;
|
||||
if (dateInput) {
|
||||
text = dateInput.value || '';
|
||||
} else if (textInput) {
|
||||
text = textInput.value || '';
|
||||
} else {
|
||||
text = td.textContent.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
row.push(text);
|
||||
});
|
||||
|
||||
if (row.length > 0) {
|
||||
rows.push(row);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (rows.length <= 1) {
|
||||
alert('내보낼 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// CSV 생성 (UTF-8 BOM 포함)
|
||||
const BOM = '\uFEFF';
|
||||
const csvContent = BOM + rows.map(row =>
|
||||
row.map(cell => {
|
||||
const escaped = String(cell).replace(/"/g, '""');
|
||||
return `"${escaped}"`;
|
||||
}).join(',')
|
||||
).join('\n');
|
||||
|
||||
// 다운로드
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
link.click();
|
||||
URL.revokeObjectURL(link.href);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
Reference in New Issue
Block a user