ba5b2e61a5
- KJBank 레이아웃, 프래그먼트 파일 DJBank로 변경 - HTML 레이아웃 파일 KJBank에서 DJBank로 업데이트
497 lines
21 KiB
HTML
497 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html xmlns:th="http://www.thymeleaf.org"
|
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
|
layout:decorate="~{layout/djbank_title_layout}">
|
|
<head>
|
|
<title>수수료 관리</title>
|
|
</head>
|
|
<body>
|
|
<section layout:fragment="title">
|
|
<div class="page-title-banner">
|
|
<img th:src="@{/img/img_title_bg.png}" class="title-image">
|
|
<h1>기관 수수료 관리</h1>
|
|
</div>
|
|
</section>
|
|
<th:block layout:fragment="contentFragment">
|
|
<section class="org-register-container">
|
|
<div class="searchBox row-two">
|
|
<span class="form-inline form-inline--period">
|
|
<label for="forYear">조회기간</label>
|
|
<span class="period-selects">
|
|
<select id="forYear" class="form-control">
|
|
<option value="">- 선택 -</option>
|
|
</select> <span class="period-unit">년</span>
|
|
<select id="forMonth" class="form-control">
|
|
<option value="">- 선택 -</option>
|
|
<option value="1">1</option>
|
|
<option value="2">2</option>
|
|
<option value="3">3</option>
|
|
<option value="4">4</option>
|
|
<option value="5">5</option>
|
|
<option value="6">6</option>
|
|
<option value="7">7</option>
|
|
<option value="8">8</option>
|
|
<option value="9">9</option>
|
|
<option value="10">10</option>
|
|
<option value="11">11</option>
|
|
<option value="12">12</option>
|
|
</select> <span class="period-unit">월</span>
|
|
</span>
|
|
</span>
|
|
<span class="btnBox">
|
|
<span id="searchedPeriod" class="searched-period" style="display:none; margin-right:10px; font-weight:bold; color:#28a745;"></span>
|
|
<button type="button" class="btn btn-primary" onclick="loadData()">
|
|
<span class="fa fa-search"></span><span>조회</span>
|
|
</button>
|
|
<button type="button" id="printBtn" class="btn btn-secondary" onclick="printCommission()">
|
|
<span>청구서 출력</span>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
|
|
<div class="commission-container">
|
|
<div class="col-md-12">
|
|
<p class="commission-notice">
|
|
이용기관은 매월 1~5일 전월 수수료 조회 가능하며, 10일 확정금액으로 정산됩니다. <br/>
|
|
금액이상시 담당자 연락 및 조정요청 하시기 바랍니다. (매월 1~5일 수수료 조회, 6~9일 수수료 조정 및 확정, 10일 정산)
|
|
</p>
|
|
|
|
<!-- API 수수료 테이블 -->
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered border-type">
|
|
<colgroup>
|
|
<col style="width:6%"/>
|
|
<col style="width:16%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col style="width:8%"/>
|
|
<col/>
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2">구분</th>
|
|
<th rowspan="2">API 명</th>
|
|
<th colspan="4">조정 전</th>
|
|
<th colspan="4">조정 후</th>
|
|
<th rowspan="2">조정사유</th>
|
|
</tr>
|
|
<tr>
|
|
<th>처리<br/>건수</th>
|
|
<th>적용<br/>수수료(원)</th>
|
|
<th>최저<br/>수수료</th>
|
|
<th>출금<br/>예상금액</th>
|
|
<th>조정<br/>건수</th>
|
|
<th>조정<br/>수수료(원)</th>
|
|
<th>최저<br/>수수료</th>
|
|
<th>출금<br/>예상금액</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="apiTableBody">
|
|
<!-- 동적 생성 -->
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- 판매 수수료 테이블 -->
|
|
<table class="table table-bordered border-type voffset3">
|
|
<colgroup>
|
|
<col style="width: 6%;">
|
|
<col style="width: 8%;">
|
|
<col style="width: 8%;">
|
|
<col style="width: 5%;">
|
|
<col style="width: 5%;">
|
|
<col style="width: 7%;">
|
|
<col style="width: 6%;">
|
|
<col style="width: 6%;">
|
|
<col style="width: 7%;">
|
|
<col style="width: 7%;">
|
|
<col style="width: 6%;">
|
|
<col style="width: 6%;">
|
|
<col style="width: 7%;">
|
|
<col style="width: 7%;">
|
|
<col>
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2">구분</th>
|
|
<th rowspan="2">과금대상<br/>업무</th>
|
|
<th rowspan="2">수수료<br/>유형</th>
|
|
<th rowspan="2">과금<br/>기준</th>
|
|
<th rowspan="2">값구분</th>
|
|
<th rowspan="2">판매액</th>
|
|
<th colspan="4">조정 전</th>
|
|
<th colspan="4">조정 후</th>
|
|
<th rowspan="2">조정사유</th>
|
|
</tr>
|
|
<tr>
|
|
<th>적용<br/>수수료</th>
|
|
<th>처리<br/>건수</th>
|
|
<th>최저<br/>수수료</th>
|
|
<th>출금<br/>예상수수료</th>
|
|
<th>적용<br/>수수료</th>
|
|
<th>처리<br/>건수</th>
|
|
<th>최저<br/>수수료</th>
|
|
<th>출금<br/>예상수수료</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="saleTableBody">
|
|
<!-- 동적 생성 -->
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- 합계 테이블 -->
|
|
<table class="table table-bordered border-type voffset3">
|
|
<colgroup>
|
|
<col/>
|
|
<col style="width: 13%"/>
|
|
<col style="width: 13%"/>
|
|
<col style="width: 13%"/>
|
|
<col style="width: 13%"/>
|
|
<col style="width: 13%"/>
|
|
<col style="width: 13%"/>
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2">구분</th>
|
|
<th colspan="3">조정 전</th>
|
|
<th colspan="3">조정 후</th>
|
|
</tr>
|
|
<tr>
|
|
<th>판매액</th>
|
|
<th>처리건수(건)</th>
|
|
<th>출금예상금액</th>
|
|
<th>판매액</th>
|
|
<th>처리건수(건)</th>
|
|
<th>출금예상금액</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr class="summary-row">
|
|
<td class="text-center"><strong id="totalTitle">합계</strong></td>
|
|
<td class="text-right"><strong id="totalSalesAmount1">-</strong></td>
|
|
<td class="text-right"><strong id="totalCount1">-</strong></td>
|
|
<td class="text-right"><strong class="summary-amount" id="totalAmount1">-</strong></td>
|
|
<td class="text-right"><strong id="totalSalesAmount2">-</strong></td>
|
|
<td class="text-right"><strong id="totalCount2">-</strong></td>
|
|
<td class="text-right"><strong class="summary-amount" id="totalAmount2">-</strong></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
</th:block>
|
|
|
|
<th:block layout:fragment="contentScript">
|
|
<script th:inline="javascript">
|
|
// 페이지 로드 시 초기화 및 자동 조회
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
var noOrgCode = /*[[${noOrgCode}]]*/ false;
|
|
if (noOrgCode) {
|
|
customPopups.showAlert('제휴기관코드가 등록되지 않았습니다.<br/>관리자에게 문의하세요.', function() {
|
|
history.back();
|
|
});
|
|
return;
|
|
}
|
|
initializeDateSelects();
|
|
// 페이지 로딩 후 자동 조회
|
|
loadData();
|
|
});
|
|
|
|
function initializeDateSelects() {
|
|
const now = new Date();
|
|
const currentYear = now.getFullYear();
|
|
const currentMonth = now.getMonth() + 1; // 0-indexed
|
|
|
|
// 전월 계산
|
|
let lastMonth = currentMonth - 1;
|
|
let lastMonthYear = currentYear;
|
|
if (lastMonth === 0) {
|
|
lastMonth = 12;
|
|
lastMonthYear = currentYear - 1;
|
|
}
|
|
|
|
// 연도 옵션 동적 생성 (최근 3년)
|
|
const yearSelect = document.getElementById('forYear');
|
|
for (let year = currentYear; year >= currentYear - 2; year--) {
|
|
const option = document.createElement('option');
|
|
option.value = year;
|
|
option.textContent = year;
|
|
if (year === lastMonthYear) {
|
|
option.selected = true;
|
|
}
|
|
yearSelect.appendChild(option);
|
|
}
|
|
|
|
// 월 기본값 설정 (전월)
|
|
const monthSelect = document.getElementById('forMonth');
|
|
monthSelect.value = lastMonth.toString();
|
|
}
|
|
|
|
function showSearchedPeriod(year, month) {
|
|
const searchedPeriodEl = document.getElementById('searchedPeriod');
|
|
searchedPeriodEl.textContent = year + '년 ' + month + '월 조회완료';
|
|
searchedPeriodEl.style.display = 'inline';
|
|
}
|
|
|
|
function hideSearchedPeriod() {
|
|
const searchedPeriodEl = document.getElementById('searchedPeriod');
|
|
searchedPeriodEl.style.display = 'none';
|
|
}
|
|
|
|
function formatNumber(num) {
|
|
return new Intl.NumberFormat('ko-KR').format(num);
|
|
}
|
|
|
|
function loadData() {
|
|
const year = document.getElementById('forYear').value;
|
|
const month = document.getElementById('forMonth').value;
|
|
|
|
if (!year || !month) {
|
|
customPopups.showAlert('조회 기간을 선택해주세요.');
|
|
return;
|
|
}
|
|
|
|
// 서버에서 데이터 조회 API 호출
|
|
fetch('/commission', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-XSRF-TOKEN': /*[[${_csrf.token}]]*/ ''
|
|
},
|
|
body: JSON.stringify({
|
|
year: year,
|
|
month: month
|
|
})
|
|
})
|
|
.then(response => {
|
|
return response.json().then(data => {
|
|
if (!response.ok) {
|
|
// 서버에서 반환한 에러 메시지 추출
|
|
const errorMessage = data.description || data.message || '데이터 조회에 실패했습니다.';
|
|
throw new Error(errorMessage);
|
|
}
|
|
return data;
|
|
});
|
|
})
|
|
.then(data => renderCommissionData(data, year, month))
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
hideSearchedPeriod();
|
|
customPopups.showAlert(error.message || '데이터 조회 중 오류가 발생했습니다.');
|
|
});
|
|
|
|
}
|
|
|
|
function renderCommissionData(data, year, month) {
|
|
// API 수수료 항목 필터링
|
|
const apiCommissions = data.list.filter(item => item.paymentTargetType === '01');
|
|
const saleCommissions = data.list.filter(item => item.paymentTargetType !== '01');
|
|
|
|
// API 수수료 테이블 렌더링
|
|
const apiTableBody = document.getElementById('apiTableBody');
|
|
apiTableBody.innerHTML = '';
|
|
|
|
let apiTotal1 = 0;
|
|
let apiTotal2 = 0;
|
|
let apiCount1 = 0;
|
|
let apiCount2 = 0;
|
|
|
|
apiCommissions.forEach((item, index) => {
|
|
if (index === 0) {
|
|
apiTableBody.innerHTML += `
|
|
<tr>
|
|
<td rowspan="${apiCommissions.length}" class="text-center">API<br/>수수료</td>
|
|
<td class="text-left">${item.paymentTargetName}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.value || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum || 0)}</span></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(item.totalCount2 || 0)}</strong></td>
|
|
<td class="text-right">${formatNumber(item.value2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum2 || 0)}</span></td>
|
|
<td>${item.changeReason2 || ''}</td>
|
|
</tr>
|
|
`;
|
|
} else {
|
|
apiTableBody.innerHTML += `
|
|
<tr>
|
|
<td class="text-left">${item.paymentTargetName}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.value || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum || 0)}</span></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(item.totalCount2 || 0)}</strong></td>
|
|
<td class="text-right">${formatNumber(item.value2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum2 || 0)}</span></td>
|
|
<td>${item.changeReason2 || ''}</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
apiTotal1 += parseFloat(item.sum || 0);
|
|
apiTotal2 += parseFloat(item.sum2 || 0);
|
|
apiCount1 += parseInt(item.totalCount || 0);
|
|
apiCount2 += parseInt(item.totalCount2 || 0);
|
|
});
|
|
|
|
// API 소계
|
|
apiTableBody.innerHTML += `
|
|
<tr>
|
|
<td colspan="2" class="text-center">${year}년 ${month}월 API 수수료 소계</td>
|
|
<td class="text-right">${formatNumber(apiCount1)}</td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(apiTotal1)}</strong></td>
|
|
<td class="text-right">${formatNumber(apiCount2)}</td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(apiTotal2)}</strong></td>
|
|
<td></td>
|
|
</tr>
|
|
`;
|
|
|
|
// 판매 수수료 테이블 렌더링
|
|
const saleTableBody = document.getElementById('saleTableBody');
|
|
saleTableBody.innerHTML = '';
|
|
|
|
let saleTotal1 = 0;
|
|
let saleTotal2 = 0;
|
|
let saleCount1 = 0;
|
|
let saleCount2 = 0;
|
|
let saleSalesAmount = 0;
|
|
|
|
saleCommissions.forEach((item, index) => {
|
|
const isPercentageFee = item.paymentBaseName === '금액';
|
|
if (index === 0) {
|
|
saleTableBody.innerHTML += `
|
|
<tr>
|
|
<td rowspan="${saleCommissions.length}" class="text-center">판매<br/>수수료</td>
|
|
<td class="text-left">${item.paymentTargetName}</td>
|
|
<td>${item.detailFeeTypeName || ''}</td>
|
|
<td>${item.paymentBaseName || ''}</td>
|
|
<td>${item.valueDivisionName || ''}</td>
|
|
<td class="text-right">${item.totalValue ? formatNumber(item.totalValue) : ''}</td>
|
|
<td class="text-right">${isPercentageFee ? (parseFloat(item.value || 0) * 100) + '%' : formatNumber(item.value || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum || 0)}</span></td>
|
|
<td class="text-right">${isPercentageFee ? (parseFloat(item.value2 || 0) * 100) + '%' : formatNumber(item.value2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum2 || 0)}</span></td>
|
|
<td>${item.changeReason2 || ''}</td>
|
|
</tr>
|
|
`;
|
|
} else {
|
|
saleTableBody.innerHTML += `
|
|
<tr>
|
|
<td class="text-left">${item.paymentTargetName}</td>
|
|
<td>${item.detailFeeTypeName || ''}</td>
|
|
<td>${item.paymentBaseName || ''}</td>
|
|
<td>${item.valueDivisionName || ''}</td>
|
|
<td class="text-right">${item.totalValue ? formatNumber(item.totalValue) : ''}</td>
|
|
<td class="text-right">${isPercentageFee ? (parseFloat(item.value || 0) * 100) + '%' : formatNumber(item.value || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum || 0)}</span></td>
|
|
<td class="text-right">${isPercentageFee ? (parseFloat(item.value2 || 0) * 100) + '%' : formatNumber(item.value2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.totalCount2 || 0)}</td>
|
|
<td class="text-right">${formatNumber(item.minimumAmount2 || 0)}</td>
|
|
<td class="text-right"><span class="color_darkRed">${formatNumber(item.sum2 || 0)}</span></td>
|
|
<td>${item.changeReason2 || ''}</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
saleTotal1 += parseFloat(item.sum || 0);
|
|
saleTotal2 += parseFloat(item.sum2 || 0);
|
|
saleCount1 += parseInt(item.totalCount || 0);
|
|
saleCount2 += parseInt(item.totalCount2 || 0);
|
|
saleSalesAmount += parseFloat(item.totalValue || 0);
|
|
});
|
|
|
|
// 판매 소계
|
|
saleTableBody.innerHTML += `
|
|
<tr>
|
|
<td colspan="5" class="text-center">${year}년 ${month}월 판매 수수료 소계</td>
|
|
<td class="text-right">${formatNumber(saleSalesAmount)}</td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right">${formatNumber(saleCount1)}</td>
|
|
<td></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(saleTotal1)}</strong></td>
|
|
<td class="text-right"></td>
|
|
<td class="text-right">${formatNumber(saleCount2)}</td>
|
|
<td></td>
|
|
<td class="text-right"><strong class="color_blue">${formatNumber(saleTotal2)}</strong></td>
|
|
<td></td>
|
|
</tr>
|
|
`;
|
|
|
|
// 합계 업데이트
|
|
document.getElementById('totalTitle').textContent = `${year}년 ${month}월 합계`;
|
|
document.getElementById('totalSalesAmount1').textContent = formatNumber(saleSalesAmount);
|
|
document.getElementById('totalCount1').textContent = formatNumber(apiCount1 + saleCount1);
|
|
document.getElementById('totalAmount1').textContent = formatNumber(apiTotal1 + saleTotal1);
|
|
document.getElementById('totalSalesAmount2').textContent = formatNumber(saleSalesAmount);
|
|
document.getElementById('totalCount2').textContent = formatNumber(apiCount2 + saleCount2);
|
|
document.getElementById('totalAmount2').textContent = formatNumber(apiTotal2 + saleTotal2);
|
|
|
|
// 출력 버튼 표시
|
|
document.getElementById('printBtn').style.display = 'inline-block';
|
|
|
|
// 조회 기간 표시
|
|
showSearchedPeriod(year, month);
|
|
}
|
|
|
|
function printCommission() {
|
|
const year = document.getElementById('forYear').value;
|
|
const month = document.getElementById('forMonth').value;
|
|
|
|
if (!year || !month) {
|
|
customPopups.showAlert('조회 기간을 선택해주세요.');
|
|
return;
|
|
}
|
|
|
|
// 먼저 청구서 출력용 API로 데이터 조회하여 에러 여부 확인
|
|
fetch('/commission/print/check', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-XSRF-TOKEN': /*[[${_csrf.token}]]*/ ''
|
|
},
|
|
body: JSON.stringify({
|
|
year: year,
|
|
month: month
|
|
})
|
|
})
|
|
.then(response => {
|
|
return response.json().then(data => {
|
|
if (!response.ok) {
|
|
const errorMessage = data.description || data.message || '데이터 조회에 실패했습니다.';
|
|
throw new Error(errorMessage);
|
|
}
|
|
return data;
|
|
});
|
|
})
|
|
.then(data => {
|
|
// 에러가 없으면 청구서 출력 페이지 열기
|
|
const printUrl = '/commission/print/' + year + '/' + month;
|
|
window.open(printUrl, '_blank', 'width=800,height=900,scrollbars=yes,resizable=yes');
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
customPopups.showAlert(error.message || '청구서 조회 중 오류가 발생했습니다.');
|
|
});
|
|
}
|
|
</script>
|
|
</th:block>
|
|
</body>
|
|
</html>
|