|
|
|
|
@ -6,70 +6,44 @@
|
|
|
|
|
|
|
|
|
|
<!--
|
|
|
|
|
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
|
|
|
|
■ 부과예고 이행강제금 산출조사서 계산 로직 상세 명세서 (VO 컬럼명 기준) - BigDecimal 서버 계산 방식
|
|
|
|
|
■ 부과예고 이행강제금 산출조사서 통합 계산 시스템 (VO 컬럼명 기준) - 단일 API 방식
|
|
|
|
|
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
|
|
|
|
|
|
|
|
|
1. 건축물과세시가(bdstTxtnMprc) 계산 【서버 API】
|
|
|
|
|
- 공식: bldgCrtrMprcAmt × strctIdx × usgIdx × pstnIdx × elpsYrRdvlrt × bscsCstrnRt
|
|
|
|
|
- 설명: 건물신축가격기준액 × 구조지수 × 용도지수 × 위치지수 × 경과년수별잔가율 × 기초공사율
|
|
|
|
|
- 정확도: BigDecimal 사용으로 부동소수점 오차 방지
|
|
|
|
|
- 반올림: 소수점 없이 반올림 (RoundingMode.HALF_UP)
|
|
|
|
|
- API: POST /calculateTaxableMarketPrice.ajax
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcController.calculateTaxableMarketPrice()
|
|
|
|
|
■ 통합 계산 API: /calculateAll.ajax
|
|
|
|
|
- 한번의 API 호출로 모든 계산 단계를 수행합니다
|
|
|
|
|
- BigDecimal 사용으로 완전한 정확도 보장
|
|
|
|
|
- 사용자는 "계산하기" 버튼 클릭 시에만 계산 수행
|
|
|
|
|
|
|
|
|
|
2. 시가표준액(mprcStdAmt) 계산 【서버 API】
|
|
|
|
|
- 공식: bdstTxtnMprc.divide(1000).multiply(1000) with RoundingMode.DOWN
|
|
|
|
|
■ 4단계 계산 프로세스 (서버에서 순차 처리)
|
|
|
|
|
|
|
|
|
|
1. 건축물과세시가(bdstTxtnMprc) 계산 - 이부분은 율 이라고 표현되지만 0.85, 1 등 이미지 % 100 처리 된 값으로 표현됨
|
|
|
|
|
- 공식: bldgNewPrcCrtrAmt × strctIdx × usgIdx × pstnIdx × (elpsYrRdvlrt) × (bscsCstrnRt)
|
|
|
|
|
- 설명: 건물기준시가액 × 구조지수 × 용도지수 × 위치지수 × 경과년수별잔가율 × 기초공사율
|
|
|
|
|
- 반올림: setScale(0, RoundingMode.HALF_UP) - 소수점 반올림
|
|
|
|
|
|
|
|
|
|
2. 시가표준액(mprcStdAmt) 계산
|
|
|
|
|
- 공식: bdstTxtnMprc.divide(1000, RoundingMode.DOWN).multiply(1000)
|
|
|
|
|
- 설명: 건축물과세시가에서 1,000원 미만 절사
|
|
|
|
|
- 정확도: BigDecimal 사용으로 정확한 절사 보장
|
|
|
|
|
- API: POST /calculateStandardMarketPrice.ajax
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcController.calculateStandardMarketPrice()
|
|
|
|
|
|
|
|
|
|
3. 가감산시행령률(adsbmtnEnfcRt) 계산 【서버 API】
|
|
|
|
|
- 공식: baseRate + adtnRt - sbtrRt (BigDecimal 연산)
|
|
|
|
|
- 기본값: 100%
|
|
|
|
|
- 가산 적용 시: 100 + adtnRt (가산율)
|
|
|
|
|
- 감산 적용 시: 100 - sbtrRt (감산율)
|
|
|
|
|
- 범위 제한: 0 ≤ rate ≤ 1000% (서버에서 검증)
|
|
|
|
|
- API: POST /calculateAdsbmtnEnfcRt.ajax
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcController.calculateAdsbmtnEnfcRt()
|
|
|
|
|
|
|
|
|
|
4. 산정률(cmpttnRt) / 산정률 비율값(cmpttnRtRate)
|
|
|
|
|
- 표시용 값(cmpttnRt): 행위유형별 고정값 (예: 40.00%)
|
|
|
|
|
- 계산용 값(cmpttnRtRate): 소수점 비율 (예: 0.40)
|
|
|
|
|
- 변환: cmpttnRtRate = cmpttnRt ÷ 100 (서버에서 BigDecimal 처리)
|
|
|
|
|
- 데이터 출처: 행위정보에서 자동 설정
|
|
|
|
|
|
|
|
|
|
5. 산정률2(cmpttnRt2) / 산정률2 비율값(cmpttnRt2Rate)
|
|
|
|
|
- 표시용 값(cmpttnRt2): 위반사항별 값 (예: 50.00%)
|
|
|
|
|
- 계산용 값(cmpttnRt2Rate): 소수점 비율 (예: 0.50)
|
|
|
|
|
- 변환: cmpttnRt2Rate = cmpttnRt2 ÷ 100 (서버에서 BigDecimal 처리)
|
|
|
|
|
- 선택: 담당자가 드롭다운에서 선택
|
|
|
|
|
|
|
|
|
|
6. 산정액(cmpttnAmt) 계산 【서버 API】
|
|
|
|
|
- 공식: mprcStdAmt × vltnArea × (adsbmtnEnfcRt ÷ 100) × cmpttnRtRate × cmpttnRt2Rate
|
|
|
|
|
- 예시: 1,234,567원 → 1,234,000원
|
|
|
|
|
|
|
|
|
|
3. 산정액(cmpttnAmt) 계산
|
|
|
|
|
- 공식: mprcStdAmt × vltnArea × (adsbmtnEnfcRt÷100) × cmpttnRtRate × cmpttnRt2Rate
|
|
|
|
|
- 설명: 시가표준액 × 위반면적 × 가감산시행령률(%) × 산정률(비율) × 산정률2(비율)
|
|
|
|
|
- 정확도: BigDecimal.multiply() 체인 연산으로 정확도 보장
|
|
|
|
|
- 반올림: setScale(0, RoundingMode.DOWN) - 소수점 버림
|
|
|
|
|
- API: POST /calculateLevyAmount.ajax
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcController.calculateLevyAmount()
|
|
|
|
|
|
|
|
|
|
7. 부과총액(levyWholAmt) 계산 【서버 API】
|
|
|
|
|
4. 부과총액(levyWholAmt) 계산
|
|
|
|
|
- 공식: cmpttnAmt.divide(10, RoundingMode.DOWN).multiply(10)
|
|
|
|
|
- 설명: 산정액에서 1의 자리 절사 (10원 단위 버림)
|
|
|
|
|
- 정확도: BigDecimal 연산으로 정확한 절사 보장
|
|
|
|
|
- 설명: 산정액에서 10원 단위 절사 (1의 자리 버림)
|
|
|
|
|
- 예시: 1,234,567원 → 1,234,560원
|
|
|
|
|
- API: POST /calculateLevyAmount.ajax (산정액과 함께 반환)
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcController.calculateLevyAmount()
|
|
|
|
|
|
|
|
|
|
8. 이행강제금(impltCpsrAmt) 계산
|
|
|
|
|
5. 이행강제금(impltCpsrAmt) 계산 (별도 서비스 로직)
|
|
|
|
|
- 공식: SUM(levyWholAmt) WHERE crdnYr = ? AND crdnNo = ? AND impltTaskSeCd = ?
|
|
|
|
|
- 설명: 해당 단속의 모든 행위정보별 부과총액 합계
|
|
|
|
|
- 조건: 모든 행위정보에 대한 부과정보가 등록된 경우에만 계산
|
|
|
|
|
- 정확도: DB에서 SUM 집계 함수 사용으로 정확성 보장
|
|
|
|
|
- 조건: 모든 행위정보에 대한 부과정보가 등록된 경우에만 자동 계산
|
|
|
|
|
- 처리위치: CrdnLevyPrvntcServiceImpl.updateImpltCpsrAmt()
|
|
|
|
|
|
|
|
|
|
■ 주요 VO 컬럼 설명
|
|
|
|
|
- bldgCrtrMprcAmt: 건물신축가격기준액 (BigDecimal)
|
|
|
|
|
- bldgNewPrcCrtrAmt: 건물기준시가액 (BigDecimal)
|
|
|
|
|
- strctIdx: 구조지수 (BigDecimal)
|
|
|
|
|
- usgIdx: 용도지수 (BigDecimal)
|
|
|
|
|
- pstnIdx: 위치지수 (BigDecimal)
|
|
|
|
|
@ -87,27 +61,22 @@
|
|
|
|
|
- levyWholAmt: 부과총액 (BigDecimal)
|
|
|
|
|
- impltCpsrAmt: 이행강제금 (BigDecimal)
|
|
|
|
|
|
|
|
|
|
■ 계산 처리 흐름 (완전한 서버 사이드 BigDecimal 계산)
|
|
|
|
|
■ 사용자 인터페이스 흐름
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
│ 1단계: 건축물과세시가 계산 【calculateTaxableMarketPrice.ajax】 │
|
|
|
|
|
│ ├─ Input: 건물기준시가액, 구조지수, 용도지수, 위치지수, 경과년수별잔가율, 기초공사율 │
|
|
|
|
|
│ ├─ Process: BigDecimal 6개 값 곱셈 연산 │
|
|
|
|
|
│ └─ Output: 정확한 건축물과세시가 │
|
|
|
|
|
│ 1. 사용자 입력: 모든 필수 데이터 입력 │
|
|
|
|
|
│ - 건물기준시가액, 구조지수, 용도지수, 위치지수, 경과년수별잔가율, 기초공사율 │
|
|
|
|
|
│ - 위반면적, 가감산시행령률, 산정률, 산정률2 │
|
|
|
|
|
│ ↓ │
|
|
|
|
|
│ 2단계: 시가표준액 계산 【calculateStandardMarketPrice.ajax】 │
|
|
|
|
|
│ ├─ Input: 건축물과세시가 │
|
|
|
|
|
│ ├─ Process: BigDecimal.divide(1000).multiply(1000) 절사 연산 │
|
|
|
|
|
│ └─ Output: 1,000원 미만 절사된 시가표준액 │
|
|
|
|
|
│ 2. "계산하기" 버튼 클릭 → 단일 API 호출 【calculateAll.ajax】 │
|
|
|
|
|
│ - 입력값 validation 수행 │
|
|
|
|
|
│ - 모든 계산을 서버에서 한번에 처리 │
|
|
|
|
|
│ ↓ │
|
|
|
|
|
│ 3단계: 산정액/부과총액 계산 【calculateLevyAmount.ajax】 │
|
|
|
|
|
│ ├─ Input: 시가표준액, 위반면적, 가감산시행령률, 산정률, 산정률2 │
|
|
|
|
|
│ ├─ Process: BigDecimal 5개 값 곱셈 → 소수점 버림 → 10원 단위 절사 │
|
|
|
|
|
│ └─ Output: 정확한 산정액 + 부과총액 │
|
|
|
|
|
│ 3. 계산 결과 일괄 표시 │
|
|
|
|
|
│ - 건축물과세시가, 시가표준액, 산정액, 부과총액 동시 업데이트 │
|
|
|
|
|
│ - 계산하기 버튼 자동 숨김 │
|
|
|
|
|
│ ↓ │
|
|
|
|
|
│ 4단계: 이행강제금 계산 【Service Layer + DB SUM】 │
|
|
|
|
|
│ ├─ Input: 모든 행위정보별 부과총액 │
|
|
|
|
|
│ ├─ Process: DB SUM 집계 함수로 합산 │
|
|
|
|
|
│ └─ Output: 최종 이행강제금 │
|
|
|
|
|
│ 4. 데이터 저장 시 이행강제금 자동 계산 │
|
|
|
|
|
│ - 모든 행위정보 완료 시 자동 합산 │
|
|
|
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
|
|
|
|
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
|
|
|
|
@ -292,7 +261,7 @@
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td rowspan="2" class="b-right-0 b-bottom-0">
|
|
|
|
|
<input type="text" class="input numericMask" id="standardMarketPrice_top" readonly/><!-- 시가표준액 -->
|
|
|
|
|
<input type="text" class="input numericMask" id="standardMarketPrice_bottom" readonly/><!-- 시가표준액 -->
|
|
|
|
|
</td>
|
|
|
|
|
<td rowspan="2" class="op-cell b-right-0 b-bottom-0">X</td>
|
|
|
|
|
<td rowspan="2" class="b-right-0 b-bottom-0">
|
|
|
|
|
@ -349,7 +318,12 @@
|
|
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="12" class="b-top-0">
|
|
|
|
|
<h2><strong>부과총액 = <span id="levyWholAmtDisplay">0 원</span></strong></h2>
|
|
|
|
|
<h2 style="max-height: 45px;">
|
|
|
|
|
<strong>부과총액 = <span id="levyWholAmtDisplay"></span></strong>
|
|
|
|
|
<c:if test="${mode ne 'V'}">
|
|
|
|
|
<button type="button" id="btnCalculate" class="newbtns bg3" style="vertical-align: top; margin-left: 10px;">계산하기</button>
|
|
|
|
|
</c:if>
|
|
|
|
|
</h2>
|
|
|
|
|
<input type="hidden" class="input numericMask" id="levyWholAmt" value="">
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
@ -668,6 +642,14 @@
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.instance.on('click', function(ev) {
|
|
|
|
|
if (ev.rowKey !== undefined && ev.rowKey !== null) {
|
|
|
|
|
var rowData = self.instance.getRow(ev.rowKey);
|
|
|
|
|
LevyPrvntcPopup.actInfoIdSelect = rowData.actInfoId;
|
|
|
|
|
handleRowSelection(rowData);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.instance.on('focusChange', function(ev) {
|
|
|
|
|
if (ev.rowKey !== undefined && ev.rowKey !== null) {
|
|
|
|
|
var rowData = self.instance.getRow(ev.rowKey);
|
|
|
|
|
@ -796,9 +778,12 @@
|
|
|
|
|
$('#levyWholAmt').val(existingData.levyWholAmt || '');
|
|
|
|
|
$('#levyWholAmtDisplay').text((existingData.levyWholAmt ? Number(existingData.levyWholAmt).toLocaleString() : '0') + ' 원');
|
|
|
|
|
|
|
|
|
|
// 기존 데이터 로딩 시 계산하기 버튼 숨김 (이미 계산된 결과가 있으므로)
|
|
|
|
|
hideCalculateButton();
|
|
|
|
|
|
|
|
|
|
// 시가표준액
|
|
|
|
|
$('#standardMarketPrice').val(existingData.mprcStdAmt || '').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_top').val(existingData.mprcStdAmt || '').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_bottom').val(existingData.mprcStdAmt || '').trigger('focus');
|
|
|
|
|
|
|
|
|
|
// 건축물과세시가
|
|
|
|
|
$('#taxableMarketPrice').val(existingData.bdstTxtnMprc || '').trigger('focus');
|
|
|
|
|
@ -848,6 +833,16 @@
|
|
|
|
|
$('#bscsCstrnRt').val(''); // 기초공사율
|
|
|
|
|
$('#bscsCstrnSeCd').val(''); // 기초공사구분
|
|
|
|
|
|
|
|
|
|
// 기초공사율 계산을 위한 기준 비율들 초기화 (hidden으로)
|
|
|
|
|
if (!$('#bscsCstrnYBdstCmpttnRt').length) {
|
|
|
|
|
$('<input type="hidden" id="bscsCstrnYBdstCmpttnRt">').appendTo('body');
|
|
|
|
|
$('<input type="hidden" id="bscsCstrnNBdstCmpttnRt">').appendTo('body');
|
|
|
|
|
$('<input type="hidden" id="dupEtbldgBdstCmpttnRt">').appendTo('body');
|
|
|
|
|
}
|
|
|
|
|
$('#bscsCstrnYBdstCmpttnRt').val('');
|
|
|
|
|
$('#bscsCstrnNBdstCmpttnRt').val('');
|
|
|
|
|
$('#dupEtbldgBdstCmpttnRt').val('');
|
|
|
|
|
|
|
|
|
|
$('#bldgNewPrcCrtrAmtNo').val(rowData.bldgNewPrcCrtrAmtNo); // 건물기준시가액(NO)
|
|
|
|
|
$('#bldgNewPrcCrtrAmtDisplay').val(rowData.bdstUsg); // 건물기준시가액(건축물 용도)
|
|
|
|
|
$('#bldgNewPrcCrtrAmt').val(rowData.bldgNewPrcCrtrAmt).trigger('focus'); // 건물기준시가액(하단)
|
|
|
|
|
@ -869,8 +864,8 @@
|
|
|
|
|
|
|
|
|
|
$('#bscsCstrnSeCd').trigger('change'); // 기초공사구분 변경 이벤트 트리거
|
|
|
|
|
|
|
|
|
|
// 산정액 계산 함수 호출
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
// 계산하기 버튼 표시 (값이 변경된 경우)
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -978,8 +973,8 @@
|
|
|
|
|
|
|
|
|
|
$('#bscsCstrnRt').val(rate).trigger('focus'); // 기초공사율 설정
|
|
|
|
|
|
|
|
|
|
// 자동계산 함수 호출
|
|
|
|
|
calculateAuto();
|
|
|
|
|
// 계산하기 버튼 표시 (값이 변경된 경우)
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 산정률2 선택 시 산정률2 input에 값 설정
|
|
|
|
|
@ -991,19 +986,26 @@
|
|
|
|
|
$('#cmpttnRt2Rate').val(rateValue2 || '');
|
|
|
|
|
$('#cmpttnRt2Display').val((rateValue || '') + ' %').trigger('focus');
|
|
|
|
|
|
|
|
|
|
// 산정액 계산 함수 호출
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
// 계산하기 버튼 표시 (값이 변경된 경우)
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 위반면적 변경 시 산정액 계산 함수 호출
|
|
|
|
|
// 위반면적 변경 시 계산하기 버튼 표시
|
|
|
|
|
$('#vltnArea').on('change keyup', function() {
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 계산에 사용되는 입력 필드 변경 시 자동 계산 호출
|
|
|
|
|
var calculationInputs = '#bldgNewPrcCrtrAmt, #strctIdx, #usgIdx, #pstnIdx, #elpsYrRdvlrt';
|
|
|
|
|
$(document).on('change', calculationInputs, calculateAuto);
|
|
|
|
|
// 계산에 사용되는 입력 필드 변경 시 계산하기 버튼 표시 (기초공사율 포함)
|
|
|
|
|
var calculationInputs = '#bldgNewPrcCrtrAmt, #strctIdx, #usgIdx, #pstnIdx, #elpsYrRdvlrt, #bscsCstrnRt';
|
|
|
|
|
$(document).on('change', calculationInputs, function() {
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 계산하기 버튼 클릭 이벤트
|
|
|
|
|
$('#btnCalculate').on('click', function() {
|
|
|
|
|
performCalculation();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// ========================================
|
|
|
|
|
@ -1178,8 +1180,8 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$('#bscsCstrnSeCd').val()) {
|
|
|
|
|
alert('기초공사구분을 선택해주세요.');
|
|
|
|
|
$('#bscsCstrnSeCd').focus();
|
|
|
|
|
alert('기초공사구분을 선택해주세요.');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1196,6 +1198,16 @@
|
|
|
|
|
$('#vltnArea').focus();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var taxableMarketPrice = $("#taxableMarketPrice").val();
|
|
|
|
|
var standardMarketPrice = $("#standardMarketPrice").val();
|
|
|
|
|
var standardMarketPrice_bottom = $("#standardMarketPrice_bottom").val();
|
|
|
|
|
var cmpttnAmt = $("#cmpttnAmt").val();
|
|
|
|
|
var levyWholAmt = $("#levyWholAmt").val();
|
|
|
|
|
if( !(taxableMarketPrice && standardMarketPrice && standardMarketPrice_bottom && cmpttnAmt && levyWholAmt) ){
|
|
|
|
|
alert('[계산하기] 버튼을 클릭 하여 계산을 완료하시기 바랍니다.');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
@ -1231,188 +1243,313 @@
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 행정처분 간격일 자동 계산 함수
|
|
|
|
|
* 중요한 로직 주석: 시작일과 종료일 입력시 자동으로 간격일을 계산한다.
|
|
|
|
|
*/
|
|
|
|
|
calculateDaysBetween: function() {
|
|
|
|
|
var startDate = $('#impltBgngYmd').inputmask("unmaskedvalue");
|
|
|
|
|
var endDate = $('#impltEndYmd').inputmask("unmaskedvalue");
|
|
|
|
|
|
|
|
|
|
if (startDate && endDate && startDate.length === 8 && endDate.length === 8) {
|
|
|
|
|
var start = new Date(startDate.substring(0,4),
|
|
|
|
|
parseInt(startDate.substring(4,6)) - 1,
|
|
|
|
|
startDate.substring(6,8));
|
|
|
|
|
var end = new Date(endDate.substring(0,4),
|
|
|
|
|
parseInt(endDate.substring(4,6)) - 1,
|
|
|
|
|
endDate.substring(6,8));
|
|
|
|
|
|
|
|
|
|
var timeDiff = end.getTime() - start.getTime();
|
|
|
|
|
var daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
|
|
|
|
|
|
|
|
|
$('#impltDaysCnt').val(daysDiff);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 가감산 팝업에서 선택된 데이터를 받아 처리하는 함수
|
|
|
|
|
* @param {string} type - 'add' 또는 'minus'
|
|
|
|
|
* @param {Array} data - 선택된 행 데이터 배열
|
|
|
|
|
*/
|
|
|
|
|
setAddMinusData: function(type, data) {
|
|
|
|
|
// 단건 선택
|
|
|
|
|
const selectedRow = data;
|
|
|
|
|
if (!selectedRow) return;
|
|
|
|
|
|
|
|
|
|
const rate = parseFloat(selectedRow.adsbmtnRt) || 0;
|
|
|
|
|
const rateForCalc = parseFloat(selectedRow.adsbmtnRtRate) || 0;
|
|
|
|
|
const rateForDisplay = rate + '%';
|
|
|
|
|
let rateForTotal = 100;
|
|
|
|
|
|
|
|
|
|
if (type === '1') { // '1' for 가산(add)
|
|
|
|
|
$('#adtnRtCd').val(selectedRow.adsbmtnRtCd);
|
|
|
|
|
$('#adtnRt').val(rate);
|
|
|
|
|
$('#adtnRtRate').val(rateForCalc);
|
|
|
|
|
$('#btnOpenAddPopup').text('+ 가산 [' + rateForDisplay + ']');
|
|
|
|
|
|
|
|
|
|
} else if (type === '2') { // '2' for 감산(minus)
|
|
|
|
|
$('#sbtrRtCd').val(selectedRow.adsbmtnRtCd);
|
|
|
|
|
$('#sbtrRt').val(rate);
|
|
|
|
|
$('#sbtrRtRate').val(rateForCalc);
|
|
|
|
|
$('#btnOpenMinusPopup').text('- 감산 [' + rateForDisplay + ']');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var addRate = $('#adtnRt').val();
|
|
|
|
|
var minusRate = $('#sbtrRt').val();
|
|
|
|
|
const totalRateCalcAdd = parseFloat(addRate) || 0;
|
|
|
|
|
const totalRateCalcMinus = parseFloat(minusRate) || 0;
|
|
|
|
|
const totalRateCalc = 100 + totalRateCalcAdd - totalRateCalcMinus;
|
|
|
|
|
|
|
|
|
|
$("#adsbmtnEnfcRt").val( totalRateCalc );
|
|
|
|
|
$("#adsbmtnEnfcRtDisplay").val( totalRateCalc+" %" );
|
|
|
|
|
|
|
|
|
|
// 계산하기 버튼 표시 (값이 변경된 경우)
|
|
|
|
|
showCalculateButton();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ========================================
|
|
|
|
|
// 6. 계산 관련 유틸리티 함수들
|
|
|
|
|
// ========================================
|
|
|
|
|
|
|
|
|
|
// ========================================
|
|
|
|
|
// 🧮 계산하기 버튼 방식 계산 시스템
|
|
|
|
|
// ========================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 이행강제금 산정액 및 부과총액 계산
|
|
|
|
|
* 중요로직: 시가표준액, 위반면적, 가감산시행령률, 산정률, 산정률2가 모두 입력되었을 때 산정액과 부과총액을 자동으로 계산합니다.
|
|
|
|
|
* @description
|
|
|
|
|
* - 산정액 = 시가표준액 * 위반면적 * (가감산시행령률 / 100) * 산정률(비율) * 산정률2(비율)
|
|
|
|
|
* - 부과총액 = 산정액의 1의 자리 절사 (10원 단위 버림)
|
|
|
|
|
* 계산하기 버튼 표시 함수
|
|
|
|
|
* 중요로직: select box 값이 변경되었을 때 계산하기 버튼을 표시합니다.
|
|
|
|
|
*/
|
|
|
|
|
function calculateLevyAmount() {
|
|
|
|
|
var standardMarketPrice = $('#standardMarketPrice_top').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
var vltnArea = $('#vltnArea').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
var adsbmtnEnfcRt = $('#adsbmtnEnfcRt').val() || '0';
|
|
|
|
|
var cmpttnRtRate = $('#cmpttnRtRate').val() || '0';
|
|
|
|
|
var cmpttnRt2Rate = $('#cmpttnRt2Rate').val() || '0';
|
|
|
|
|
|
|
|
|
|
// 모든 값이 0보다 큰지 확인 (필수 입력값 체크)
|
|
|
|
|
if (parseFloat(standardMarketPrice) > 0 && parseFloat(vltnArea) > 0 && parseFloat(adsbmtnEnfcRt) > 0 &&
|
|
|
|
|
parseFloat(cmpttnRtRate) > 0 && parseFloat(cmpttnRt2Rate) > 0) {
|
|
|
|
|
|
|
|
|
|
// 서버 API로 정확한 계산 요청 (BigDecimal 사용)
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/calculateLevyAmount.ajax"/>',
|
|
|
|
|
type: 'POST',
|
|
|
|
|
data: {
|
|
|
|
|
mprcStdAmt: standardMarketPrice,
|
|
|
|
|
vltnArea: vltnArea,
|
|
|
|
|
adsbmtnEnfcRt: adsbmtnEnfcRt,
|
|
|
|
|
cmpttnRtRate: cmpttnRtRate,
|
|
|
|
|
cmpttnRt2Rate: cmpttnRt2Rate
|
|
|
|
|
},
|
|
|
|
|
success: function(response) {
|
|
|
|
|
if (response && response.data && response.success) {
|
|
|
|
|
var cmpttnAmt = response.data.cmpttnAmt;
|
|
|
|
|
var levyWholAmt = response.data.levyWholAmt;
|
|
|
|
|
|
|
|
|
|
// '산정액' 필드에 값 설정
|
|
|
|
|
$('#cmpttnAmt').val(parseInt(cmpttnAmt)).trigger('focus');
|
|
|
|
|
|
|
|
|
|
// '부과총액' 필드 및 표시에 값 설정
|
|
|
|
|
$('#levyWholAmt').val(parseInt(levyWholAmt));
|
|
|
|
|
$('#levyWholAmtDisplay').text(parseInt(levyWholAmt).toLocaleString() + ' 원');
|
|
|
|
|
|
|
|
|
|
console.log('산정액 (서버계산):', cmpttnAmt);
|
|
|
|
|
console.log('부과총액 (서버계산):', levyWholAmt);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error: function() {
|
|
|
|
|
alert('산정액 및 부과총액 계산 중 오류가 발생했습니다.');
|
|
|
|
|
// 오류 시 필드 초기화
|
|
|
|
|
$('#cmpttnAmt').val('').trigger('focus');
|
|
|
|
|
$('#levyWholAmt').val('');
|
|
|
|
|
$('#levyWholAmtDisplay').text('0 원');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 값이 부족할 때 필드 초기화
|
|
|
|
|
function showCalculateButton() {
|
|
|
|
|
var btnCalculate = $('#btnCalculate');
|
|
|
|
|
if (btnCalculate.length > 0) {
|
|
|
|
|
btnCalculate.show().addClass('btn-highlight');
|
|
|
|
|
|
|
|
|
|
//건축물 과세시가, 시가표준액(상단), 시가표준액(하단), 산정액 값 초기화 처리
|
|
|
|
|
// 오류 시 필드 초기화
|
|
|
|
|
$('#taxableMarketPrice').val('').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice').val('').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_bottom').val('').trigger('focus');
|
|
|
|
|
$('#cmpttnAmt').val('').trigger('focus');
|
|
|
|
|
$('#levyWholAmt').val('');
|
|
|
|
|
$('#levyWholAmtDisplay').text('0 원');
|
|
|
|
|
|
|
|
|
|
console.log('🔄 계산하기 버튼 표시됨 - 값이 변경됨');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 건축물과세시가 자동 계산 (서버 API 호출)
|
|
|
|
|
* 중요로직: 각 항목의 값을 서버로 보내 건축물과세시가를 계산하고, 그 결과를 받아 시가표준액을 계산합니다.
|
|
|
|
|
* @description
|
|
|
|
|
* - 건축물과세시가 = 서버 API를 통해 계산
|
|
|
|
|
* - 시가표준액 = 건축물과세시가에서 1,000원 미만 절사
|
|
|
|
|
* 계산하기 버튼 숨김 함수
|
|
|
|
|
* 중요로직: 계산이 완료되었을 때 계산하기 버튼을 숨깁니다.
|
|
|
|
|
*/
|
|
|
|
|
function calculateAuto() {
|
|
|
|
|
var bldgNewPrcCrtrAmt = $('#bldgNewPrcCrtrAmt').inputmask('unmaskedvalue') || '0'; // 건물기준시가액
|
|
|
|
|
var strctIdx = $('#strctIdx').inputmask('unmaskedvalue') || '0'; // 구조지수
|
|
|
|
|
var usgIdx = $('#usgIdx').inputmask('unmaskedvalue') || '0'; // 용도지수
|
|
|
|
|
var pstnIdx = $('#pstnIdx').inputmask('unmaskedvalue') || '0'; // 위치지수
|
|
|
|
|
var elpsYrRdvlrt = $('#elpsYrRdvlrt').inputmask('unmaskedvalue') || '0'; // 경과년수별잔가율
|
|
|
|
|
var bscsCstrnRt = $('#bscsCstrnRt').inputmask('unmaskedvalue') || '0'; // 기초공사율
|
|
|
|
|
|
|
|
|
|
// 기초공사율이 선택되지 않았으면 계산을 수행하지 않고 필드를 초기화합니다.
|
|
|
|
|
if (!bscsCstrnRt || parseFloat(bscsCstrnRt) === 0) {
|
|
|
|
|
$('#taxableMarketPrice').val('').trigger('focus'); // 건축물과세시가
|
|
|
|
|
$('#standardMarketPrice').val('').trigger('focus'); // 시가표준액
|
|
|
|
|
$('#standardMarketPrice_top').val('').trigger('focus'); // 시가표준액(상단)
|
|
|
|
|
// 필드 초기화 시 산정액/부과총액도 초기화
|
|
|
|
|
$('#cmpttnAmt').val('').trigger('focus');
|
|
|
|
|
$('#levyWholAmt').val('');
|
|
|
|
|
$('#levyWholAmtDisplay').text('0 원');
|
|
|
|
|
function hideCalculateButton() {
|
|
|
|
|
var btnCalculate = $('#btnCalculate');
|
|
|
|
|
if (btnCalculate.length > 0) {
|
|
|
|
|
btnCalculate.hide().removeClass('btn-highlight');
|
|
|
|
|
console.log('✅ 계산하기 버튼 숨김됨 - 계산 완료');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 계산 수행 함수 - 단일 API 호출
|
|
|
|
|
* 중요로직: 모든 필수값 validation 후 단일 API로 모든 계산을 한번에 수행합니다.
|
|
|
|
|
* - 감산, 가산은 선택사항 (기본 100%)
|
|
|
|
|
* - 나머지는 모두 필수
|
|
|
|
|
*/
|
|
|
|
|
function performCalculation() {
|
|
|
|
|
console.log('🧮 통합 계산하기 버튼 클릭됨');
|
|
|
|
|
|
|
|
|
|
// 1. 필수값 validation
|
|
|
|
|
var validationResult = validateCalculationInputs();
|
|
|
|
|
if (!validationResult.isValid) {
|
|
|
|
|
alert(validationResult.message);
|
|
|
|
|
if (validationResult.focusElement) {
|
|
|
|
|
$(validationResult.focusElement).focus();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var params = {
|
|
|
|
|
bldgNewPrcCrtrAmt: bldgNewPrcCrtrAmt,
|
|
|
|
|
strctIdx: strctIdx,
|
|
|
|
|
usgIdx: usgIdx,
|
|
|
|
|
pstnIdx: pstnIdx,
|
|
|
|
|
elpsYrRdvlrt: elpsYrRdvlrt,
|
|
|
|
|
bscsCstrnRt: bscsCstrnRt
|
|
|
|
|
};
|
|
|
|
|
// 2. 입력값 수집
|
|
|
|
|
var params = collectAllCalculationInputs();
|
|
|
|
|
console.log('📊 수집된 통합 계산 파라미터:', params);
|
|
|
|
|
|
|
|
|
|
// 3. 로딩 상태 표시
|
|
|
|
|
$('#levyWholAmtDisplay').text('계산 중...');
|
|
|
|
|
$('#btnCalculate').prop('disabled', true).text('계산 중...');
|
|
|
|
|
|
|
|
|
|
// 4. 단일 API 호출로 모든 계산 수행
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/calculateTaxableMarketPrice.ajax"/>',
|
|
|
|
|
url: '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/calculateAll.ajax"/>',
|
|
|
|
|
type: 'POST',
|
|
|
|
|
data: params,
|
|
|
|
|
success: function(response) {
|
|
|
|
|
if (response && response.data && response.success) {
|
|
|
|
|
var taxableMarketPrice = response.data.taxableMarketPrice;
|
|
|
|
|
if (response && response.success && response.data) {
|
|
|
|
|
var data = response.data;
|
|
|
|
|
|
|
|
|
|
// 건축물과세시가 설정
|
|
|
|
|
$('#taxableMarketPrice').val(taxableMarketPrice).trigger('focus');
|
|
|
|
|
// 모든 결과값을 한번에 설정
|
|
|
|
|
// 1. 건축물과세시가
|
|
|
|
|
$('#taxableMarketPrice').val(data.bdstTxtnMprc).trigger('focus');
|
|
|
|
|
|
|
|
|
|
// 시가표준액 계산을 서버 API로 요청 (BigDecimal 정확도 보장)
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/calculateStandardMarketPrice.ajax"/>',
|
|
|
|
|
type: 'POST',
|
|
|
|
|
data: { bdstTxtnMprc: taxableMarketPrice },
|
|
|
|
|
success: function(standardResponse) {
|
|
|
|
|
if (standardResponse && standardResponse.data && standardResponse.success) {
|
|
|
|
|
var standardMarketPrice = standardResponse.data.mprcStdAmt;
|
|
|
|
|
|
|
|
|
|
// 시가표준액 설정
|
|
|
|
|
$('#standardMarketPrice').val(standardMarketPrice).trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_top').val(standardMarketPrice).trigger('focus');
|
|
|
|
|
|
|
|
|
|
console.log('건축물과세시가:', taxableMarketPrice);
|
|
|
|
|
console.log('시가표준액:', standardMarketPrice);
|
|
|
|
|
|
|
|
|
|
// 산정액 계산 함수 호출
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error: function() {
|
|
|
|
|
alert('시가표준액 계산 중 오류가 발생했습니다.');
|
|
|
|
|
}
|
|
|
|
|
// 2. 시가표준액
|
|
|
|
|
$('#standardMarketPrice').val(data.mprcStdAmt).trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_bottom').val(data.mprcStdAmt).trigger('focus');
|
|
|
|
|
|
|
|
|
|
// 3. 산정액
|
|
|
|
|
$('#cmpttnAmt').val(parseInt(data.cmpttnAmt)).trigger('focus');
|
|
|
|
|
|
|
|
|
|
// 4. 부과총액
|
|
|
|
|
$('#levyWholAmt').val(parseInt(data.levyWholAmt));
|
|
|
|
|
$('#levyWholAmtDisplay').text(data.levyWholAmtDisplay);
|
|
|
|
|
|
|
|
|
|
console.log('✅ 통합 계산 완료!', {
|
|
|
|
|
건축물과세시가: data.bdstTxtnMprc,
|
|
|
|
|
시가표준액: data.mprcStdAmt,
|
|
|
|
|
산정액: data.cmpttnAmt,
|
|
|
|
|
부과총액: data.levyWholAmt
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 계산하기 버튼 숨김
|
|
|
|
|
hideCalculateButton();
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
alert(response.message || '계산 중 오류가 발생했습니다.');
|
|
|
|
|
$('#taxableMarketPrice').val('').trigger('focus'); // 건축물과세시가
|
|
|
|
|
$('#standardMarketPrice').val('').trigger('focus'); // 시가표준액
|
|
|
|
|
$('#standardMarketPrice_top').val('').trigger('focus'); // 시가표준액(상단)
|
|
|
|
|
throw new Error(response.message || '서버에서 올바른 계산 결과를 받지 못했습니다.');
|
|
|
|
|
}
|
|
|
|
|
// 산정액 계산 함수 호출
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
},
|
|
|
|
|
error: function() {
|
|
|
|
|
alert('서버와 통신 중 오류가 발생했습니다.');
|
|
|
|
|
$('#taxableMarketPrice').val('').trigger('focus'); // 건축물과세시가
|
|
|
|
|
$('#standardMarketPrice').val('').trigger('focus'); // 시가표준액
|
|
|
|
|
$('#standardMarketPrice_top').val('').trigger('focus'); // 시가표준액(상단)
|
|
|
|
|
// 오류 시 산정액/부과총액도 초기화
|
|
|
|
|
error: function(xhr, status, error) {
|
|
|
|
|
console.error('❌ 통합 계산 오류:', error);
|
|
|
|
|
alert('계산 중 오류가 발생했습니다.');
|
|
|
|
|
|
|
|
|
|
// 오류 시 필드 초기화
|
|
|
|
|
$('#taxableMarketPrice').val('').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice').val('').trigger('focus');
|
|
|
|
|
$('#standardMarketPrice_bottom').val('').trigger('focus');
|
|
|
|
|
$('#cmpttnAmt').val('').trigger('focus');
|
|
|
|
|
$('#levyWholAmt').val('');
|
|
|
|
|
$('#levyWholAmtDisplay').text('0 원');
|
|
|
|
|
},
|
|
|
|
|
complete: function() {
|
|
|
|
|
// 로딩 상태 해제
|
|
|
|
|
$('#btnCalculate').prop('disabled', false).text('계산하기');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 행정처분 간격일 자동 계산 함수
|
|
|
|
|
* 중요한 로직 주석: 시작일과 종료일 입력시 자동으로 간격일을 계산한다.
|
|
|
|
|
* 통합 계산 입력값 validation 함수
|
|
|
|
|
* 중요로직: 건축물과세시가 계산부터 부과총액까지 전체 계산에 필요한 모든 필수값을 검증합니다.
|
|
|
|
|
*/
|
|
|
|
|
window.calculateDaysBetween = function() {
|
|
|
|
|
var startDate = $('#impltBgngYmd').inputmask("unmaskedvalue");
|
|
|
|
|
var endDate = $('#impltEndYmd').inputmask("unmaskedvalue");
|
|
|
|
|
|
|
|
|
|
if (startDate && endDate && startDate.length === 8 && endDate.length === 8) {
|
|
|
|
|
var start = new Date(startDate.substring(0,4),
|
|
|
|
|
parseInt(startDate.substring(4,6)) - 1,
|
|
|
|
|
startDate.substring(6,8));
|
|
|
|
|
var end = new Date(endDate.substring(0,4),
|
|
|
|
|
parseInt(endDate.substring(4,6)) - 1,
|
|
|
|
|
endDate.substring(6,8));
|
|
|
|
|
|
|
|
|
|
var timeDiff = end.getTime() - start.getTime();
|
|
|
|
|
var daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
|
|
|
|
|
|
|
|
|
$('#impltDaysCnt').val(daysDiff);
|
|
|
|
|
function validateCalculationInputs() {
|
|
|
|
|
// 1. 건축물과세시가 계산에 필요한 값들 검증
|
|
|
|
|
var bldgNewPrcCrtrAmt = $('#bldgNewPrcCrtrAmt').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!bldgNewPrcCrtrAmt || parseFloat(bldgNewPrcCrtrAmt) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '건물기준시가액을 입력해주세요.',
|
|
|
|
|
focusElement: '#bldgNewPrcCrtrAmt'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var strctIdx = $('#strctIdx').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!strctIdx || parseFloat(strctIdx) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '구조지수를 입력해주세요.',
|
|
|
|
|
focusElement: '#strctIdx'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var usgIdx = $('#usgIdx').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!usgIdx || parseFloat(usgIdx) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '용도지수를 입력해주세요.',
|
|
|
|
|
focusElement: '#usgIdx'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pstnIdx = $('#pstnIdx').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!pstnIdx || parseFloat(pstnIdx) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '위치지수를 입력해주세요.',
|
|
|
|
|
focusElement: '#pstnIdx'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var elpsYrRdvlrt = $('#elpsYrRdvlrt').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!elpsYrRdvlrt || parseFloat(elpsYrRdvlrt) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '경과년수별잔가율을 입력해주세요.',
|
|
|
|
|
focusElement: '#elpsYrRdvlrt'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bscsCstrnRt = $('#bscsCstrnRt').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!bscsCstrnRt || parseFloat(bscsCstrnRt) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '기초공사율을 선택해주세요.',
|
|
|
|
|
focusElement: '#bscsCstrnSeCd'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 위반면적 검증
|
|
|
|
|
var vltnArea = $('#vltnArea').inputmask('unmaskedvalue') || '0';
|
|
|
|
|
if (!vltnArea || parseFloat(vltnArea) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '위반면적을 입력해주세요.',
|
|
|
|
|
focusElement: '#vltnArea'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 산정률 검증
|
|
|
|
|
var cmpttnRtRate = $('#cmpttnRtRate').val();
|
|
|
|
|
if (!cmpttnRtRate || parseFloat(cmpttnRtRate) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '산정률을 선택해주세요.',
|
|
|
|
|
focusElement: '#cmpttnRtCd'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 산정률2 검증
|
|
|
|
|
var cmpttnRt2Rate = $('#cmpttnRt2Rate').val();
|
|
|
|
|
if (!cmpttnRt2Rate || parseFloat(cmpttnRt2Rate) <= 0) {
|
|
|
|
|
return {
|
|
|
|
|
isValid: false,
|
|
|
|
|
message: '산정률2를 선택해주세요.',
|
|
|
|
|
focusElement: '#cmpttnRt2Cd'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { isValid: true };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 통합 계산용 입력값 수집 함수
|
|
|
|
|
* 중요로직: 모든 계산에 필요한 파라미터를 한번에 수집합니다.
|
|
|
|
|
*/
|
|
|
|
|
function collectAllCalculationInputs() {
|
|
|
|
|
return {
|
|
|
|
|
// 건축물과세시가 계산용 파라미터
|
|
|
|
|
bldgNewPrcCrtrAmt: $('#bldgNewPrcCrtrAmt').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
strctIdx: $('#strctIdx').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
usgIdx: $('#usgIdx').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
pstnIdx: $('#pstnIdx').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
elpsYrRdvlrt: $('#elpsYrRdvlrt').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
bscsCstrnRt: $('#bscsCstrnRt').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
|
|
|
|
|
// 산정액/부과총액 계산용 파라미터
|
|
|
|
|
vltnArea: $('#vltnArea').inputmask('unmaskedvalue') || '0',
|
|
|
|
|
adsbmtnEnfcRt: $('#adsbmtnEnfcRt').val() || '100',
|
|
|
|
|
cmpttnRtRate: $('#cmpttnRtRate').val() || '0',
|
|
|
|
|
cmpttnRt2Rate: $('#cmpttnRt2Rate').val() || '0'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================
|
|
|
|
|
// 7. 초기화 실행
|
|
|
|
|
@ -1429,47 +1566,46 @@
|
|
|
|
|
// 전역 네임스페이스에 모듈 노출
|
|
|
|
|
window.LevyPrvntcPopup = LevyPrvntcPopup;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 가감산 팝업에서 선택된 데이터를 받아 처리하는 함수
|
|
|
|
|
* @param {string} type - 'add' 또는 'minus'
|
|
|
|
|
* @param {Array} data - 선택된 행 데이터 배열
|
|
|
|
|
*/
|
|
|
|
|
window.setAddMinusData = function(type, data) {
|
|
|
|
|
// 단건 선택
|
|
|
|
|
const selectedRow = data;
|
|
|
|
|
if (!selectedRow) return;
|
|
|
|
|
|
|
|
|
|
const rate = parseFloat(selectedRow.adsbmtnRt) || 0;
|
|
|
|
|
const rateForCalc = parseFloat(selectedRow.adsbmtnRtRate) || 0;
|
|
|
|
|
const rateForDisplay = rate + '%';
|
|
|
|
|
let rateForTotal = 100;
|
|
|
|
|
|
|
|
|
|
if (type === '1') { // '1' for 가산(add)
|
|
|
|
|
$('#adtnRtCd').val(selectedRow.adsbmtnRtCd);
|
|
|
|
|
$('#adtnRt').val(rate);
|
|
|
|
|
$('#adtnRtRate').val(rateForCalc);
|
|
|
|
|
$('#btnOpenAddPopup').text('+ 가산 [' + rateForDisplay + ']');
|
|
|
|
|
|
|
|
|
|
} else if (type === '2') { // '2' for 감산(minus)
|
|
|
|
|
$('#sbtrRtCd').val(selectedRow.adsbmtnRtCd);
|
|
|
|
|
$('#sbtrRt').val(rate);
|
|
|
|
|
$('#sbtrRtRate').val(rateForCalc);
|
|
|
|
|
$('#btnOpenMinusPopup').text('- 감산 [' + rateForDisplay + ']');
|
|
|
|
|
}
|
|
|
|
|
// 외부 페이지에서 호출할 수 있도록 전역 함수로 노출
|
|
|
|
|
window.calculateDaysBetween = LevyPrvntcPopup.calculateDaysBetween;
|
|
|
|
|
window.setAddMinusData = LevyPrvntcPopup.setAddMinusData;
|
|
|
|
|
|
|
|
|
|
var addRate = $('#adtnRt').val();
|
|
|
|
|
var minusRate = $('#sbtrRt').val();
|
|
|
|
|
const totalRateCalcAdd = parseFloat(addRate) || 0;
|
|
|
|
|
const totalRateCalcMinus = parseFloat(minusRate) || 0;
|
|
|
|
|
const totalRateCalc = 100 + totalRateCalcAdd - totalRateCalcMinus;
|
|
|
|
|
|
|
|
|
|
$("#adsbmtnEnfcRt").val( totalRateCalc );
|
|
|
|
|
$("#adsbmtnEnfcRtDisplay").val( totalRateCalc+" %" );
|
|
|
|
|
})(window, jQuery);
|
|
|
|
|
|
|
|
|
|
// 산정액 계산 함수 호출
|
|
|
|
|
calculateLevyAmount();
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
})(window, jQuery);
|
|
|
|
|
<style>
|
|
|
|
|
/* 계산하기 버튼 기본 스타일 */
|
|
|
|
|
#btnCalculate {
|
|
|
|
|
display: none; /* 기본적으로 숨김 */
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
/* 계산하기 버튼 강조 스타일 */
|
|
|
|
|
#btnCalculate.btn-highlight {
|
|
|
|
|
background-color: #ff6b35 !important;
|
|
|
|
|
border-color: #ff6b35 !important;
|
|
|
|
|
box-shadow: 0 0 10px rgba(255, 107, 53, 0.3);
|
|
|
|
|
animation: pulse 5s infinite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 계산하기 버튼 펄스 애니메이션 */
|
|
|
|
|
@keyframes pulse {
|
|
|
|
|
0% {
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(255, 107, 53, 0.7);
|
|
|
|
|
}
|
|
|
|
|
70% {
|
|
|
|
|
box-shadow: 0 0 0 10px rgba(255, 107, 53, 0);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
box-shadow: 0 0 0 0 rgba(255, 107, 53, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 계산하기 버튼 비활성 상태 */
|
|
|
|
|
#btnCalculate:disabled {
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
animation: none;
|
|
|
|
|
}
|
|
|
|
|
</style>
|