부과예고 초기 작업

dev
박성영 3 months ago
parent 405f3b1cec
commit 4a8c753e3e

@ -0,0 +1,162 @@
package go.kr.project.crdn.crndRegistAndView.main.controller;
import egovframework.constant.ImpltTaskSeConstants;
import egovframework.constant.TilesConstants;
import egovframework.exception.MessageException;
import egovframework.util.ApiResponseUtil;
import egovframework.util.SessionUtil;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.model.CrdnActInfoVO;
import go.kr.project.crdn.crndRegistAndView.crdnActInfo.service.CrdnActInfoService;
import go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.model.CrdnPstnInfoVO;
import go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.service.CrdnPstnInfoService;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTaskVO;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTrprInfoVO;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnRegistAndViewVO;
import go.kr.project.crdn.crndRegistAndView.main.model.LevyPrvntcActInfoVO;
import go.kr.project.crdn.crndRegistAndView.main.service.CrdnImpltTaskService;
import go.kr.project.crdn.crndRegistAndView.main.service.CrdnLevyPrvntcService;
import go.kr.project.crdn.crndRegistAndView.main.service.CrdnRegistAndViewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
/**
* packageName : go.kr.project.crdn.crndRegistAndView.controller
* fileName : CrdnLevyPrvntcController
* author :
* date : 2025-08-25
* description : /
* : CRUD API
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@Controller
@RequestMapping("/crdn/crndRegistAndView/crdnLevyPrvntc")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "부과예고 등록/조회", description = "부과예고 등록/조회 관련 API")
public class CrdnLevyPrvntcController {
/* 이행정보 서비스 */
private final CrdnImpltTaskService crdnImpltTaskService;
/* 단속 서비스 */
private final CrdnRegistAndViewService crdnRegistAndViewService;
/* 위치정보 서비스 */
private final CrdnPstnInfoService crdnPstnInfoService;
/* 행위정보 서비스 */
private final CrdnActInfoService crdnActInfoService;
/* 부과예고 서비스 */
private final CrdnLevyPrvntcService crdnLevyPrvntcService;
/**
* .
*
* @param crdnYr
* @param crdnNo
* @param mode (C:, U:, V:)
* @param model
* @return
*/
@GetMapping("/levyPrvntcPopup.do")
@Operation(summary = "부과예고 관리 팝업", description = "부과예고 관리 팝업 화면을 제공합니다.")
public ModelAndView levyPrvntcPopup(
@Parameter(description = "단속 연도") @RequestParam String crdnYr,
@Parameter(description = "단속 번호") @RequestParam String crdnNo,
@Parameter(description = "이행업무구분코드") @RequestParam String impltTaskSeCd,
@Parameter(description = "모드") @RequestParam(defaultValue = "C") String mode,
Model model) {
log.debug("부과예고 관리 팝업 요청 - 단속연도: {}, 단속번호: {}, 모드: {}",
crdnYr, crdnNo, mode);
ModelAndView mav = new ModelAndView("crdn/crndRegistAndView/main/crdnLevyPrvntc/levyPrvntcPopup" + TilesConstants.POPUP);
// 기본 파라미터 설정
mav.addObject("crdnYr", crdnYr);
mav.addObject("crdnNo", crdnNo);
mav.addObject("impltTaskSeCd", impltTaskSeCd);
mav.addObject("mode", mode);
// 이행업무구분코드명 설정
String impltTaskSeCdNm = ImpltTaskSeConstants.getImpltTaskSeCdNm(impltTaskSeCd);
mav.addObject("impltTaskSeCdNm", impltTaskSeCdNm);
// 단속정보
CrdnRegistAndViewVO crdnParamVO = new CrdnRegistAndViewVO();
crdnParamVO.setCrdnYr(crdnYr);
crdnParamVO.setCrdnNo(crdnNo);
CrdnRegistAndViewVO crdnData = crdnRegistAndViewService.selectOne(crdnParamVO);
mav.addObject("crdnData", crdnData);
// 위치정보
CrdnPstnInfoVO pstnParamVO = new CrdnPstnInfoVO();
pstnParamVO.setCrdnYr(crdnYr);
pstnParamVO.setCrdnNo(crdnNo);
CrdnPstnInfoVO pstnData = crdnPstnInfoService.selectPstnOne(pstnParamVO);
if( pstnData == null ){
throw new MessageException("위치정보를 찾을 수 없습니다.");
}
mav.addObject("pstnData", pstnData);
// 수정/보기 모드인 경우 기존 이행정보 조회
if ("U".equals(mode) || "V".equals(mode)) {
CrdnImpltTaskVO searchVO = new CrdnImpltTaskVO();
searchVO.setCrdnYr(crdnYr);
searchVO.setCrdnNo(crdnNo);
searchVO.setImpltTaskSeCd(impltTaskSeCd);
CrdnImpltTaskVO impltTaskInfo = crdnImpltTaskService.selectImpltInfo(searchVO);
if (impltTaskInfo != null) {
mav.addObject("impltTaskInfo", impltTaskInfo);
}
}
return mav;
}
/**
* (AJAX)
* @param vo
* @return
*/
@Operation(summary = "부과예고에 대한 불법위반행위정보 목록 조회", description = "부과예고에 대한 불법위반행위정보 목록을 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "500", description = "서버 오류")
})
@PostMapping("/actlist.ajax")
public ResponseEntity<?> listAjax(@ModelAttribute LevyPrvntcActInfoVO vo) {
log.debug("부과예고에 대한 불법위반행위정보 목록 조회 요청: {}", vo);
// 1. 총 개수 조회
int totalCount = crdnLevyPrvntcService.selectActInfoList(vo).size();
// 2. 응답 데이터 구성
vo.setTotalCount(totalCount);
// 3. 페이징 처리
//vo.setPagingYn("Y");
List<LevyPrvntcActInfoVO> list = crdnLevyPrvntcService.selectActInfoList(vo);
return ApiResponseUtil.successWithGrid(list, vo);
}
}

@ -0,0 +1,28 @@
package go.kr.project.crdn.crndRegistAndView.main.mapper;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTaskVO;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTrprInfoVO;
import go.kr.project.crdn.crndRegistAndView.main.model.LevyPrvntcActInfoVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* packageName : go.kr.project.crdn.crndRegistAndView.main.mapper
* fileName : CrdnLevyPrvntcMapper
* author :
* date : 2025-09-08
* description : MyBatis
* :CRUD .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-09-08
*/
@Mapper
public interface CrdnLevyPrvntcMapper {
List<LevyPrvntcActInfoVO> selectActInfoList(LevyPrvntcActInfoVO vo);
}

@ -0,0 +1,52 @@
package go.kr.project.crdn.crndRegistAndView.main.model;
import go.kr.project.common.model.PagingVO;
import lombok.*;
import java.math.BigDecimal;
/**
* packageName : go.kr.project.crdn.crndRegistAndView.main.model
* fileName : LevyPrvntcActInfoVO
* author :
* date : 25. 9. 18.
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25. 9. 18.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class LevyPrvntcActInfoVO extends PagingVO {
private String pstnInfoId; //위치정보ID
private String ldcgCd; //지목코드
private String ldcgCdNm; //지목코드명
private BigDecimal ptout; //지적
private BigDecimal oalp; //공시지가
private String lotnoWholAddr; //지번전체주소
private String zip; //우편번호
private String lotnoMno; //지번본번
private String lotnoSno; //지번부번
private String actInfoId; //행위정보ID
private String actBgngYmd; //행위시작일자
private String actTypeCd; //행위유형코드
private String actTypeCdNm; //행위유형코드명
private String vltnLwrgCd1; //위반법규코드
private String vltnLaw1; //위반법
private String crcLaw1; //시정법
private String impltLaw1; //이행법
private String strctIdxCd; //구조지수코드
private String strctIdxCdNm; //구조지수명
private String usgIdxCd; //용도지수코드
private String usgIdxCdNm; //용도지수명
private BigDecimal area; //면적
/* ======= 검색 조건 =========== */
private String crdnYr; //단속년도
private String crdnNo; //단속번호
}

@ -0,0 +1,28 @@
package go.kr.project.crdn.crndRegistAndView.main.service;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTaskVO;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnImpltTrprInfoVO;
import go.kr.project.crdn.crndRegistAndView.main.model.LevyPrvntcActInfoVO;
import java.util.List;
/**
* packageName : go.kr.project.crdn.crndRegistAndView.service
* fileName : CrdnLevyPrvntcService
* author :
* date : 2025-08-25
* description : /
* : CRUD API
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
public interface CrdnLevyPrvntcService {
/**
*
* */
List<LevyPrvntcActInfoVO> selectActInfoList(LevyPrvntcActInfoVO vo);
}

@ -42,7 +42,7 @@ import static egovframework.constant.CrdnPrcsSttsConstants.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class CrdnCrdnImpltTaskServiceImpl extends EgovAbstractServiceImpl implements CrdnImpltTaskService {
public class CrdnImpltTaskServiceImpl extends EgovAbstractServiceImpl implements CrdnImpltTaskService {
private final CrdnImpltTaskMapper crdnImpltTaskMapper;
private final CrdnRegistAndViewMapper crdnRegistAndViewMapper;

@ -0,0 +1,44 @@
package go.kr.project.crdn.crndRegistAndView.main.service.impl;
import go.kr.project.crdn.crndRegistAndView.main.mapper.CrdnImpltTaskMapper;
import go.kr.project.crdn.crndRegistAndView.main.mapper.CrdnLevyPrvntcMapper;
import go.kr.project.crdn.crndRegistAndView.main.model.CrdnRegistAndViewVO;
import go.kr.project.crdn.crndRegistAndView.main.model.LevyPrvntcActInfoVO;
import go.kr.project.crdn.crndRegistAndView.main.service.CrdnLevyPrvntcService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* packageName : go.kr.project.crdn.crndRegistAndView.service.impl
* fileName : CrdnLevyPrvntcServiceImpl
* author :
* date : 2025-08-25
* description : /
* : CRUD API
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class CrdnLevyPrvntcServiceImpl extends EgovAbstractServiceImpl implements CrdnLevyPrvntcService {
private final CrdnImpltTaskMapper crdnImpltTaskMapper;
private final CrdnLevyPrvntcMapper crdnLevyPrvntcMapper;
/**
*
* */
@Override
public List<LevyPrvntcActInfoVO> selectActInfoList(LevyPrvntcActInfoVO vo) {
return crdnLevyPrvntcMapper.selectActInfoList(vo);
}
}

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="go.kr.project.crdn.crndRegistAndView.main.mapper.CrdnLevyPrvntcMapper">
<select id="selectActInfoList" parameterType="LevyPrvntcActInfoVO" resultType="LevyPrvntcActInfoVO">
select t2.PSTN_INFO_ID,
t2.LDCG_CD,
ld.CD_NM AS LDCG_CD_NM, -- 지목코드명
t2.PTOUT,
t2.OALP,
t2.LOTNO_WHOL_ADDR,
t2.ZIP,
t2.LOTNO_MNO,
t2.LOTNO_SNO,
t3.ACT_INFO_ID,
t3.ACT_BGNG_YMD,
t3.ACT_TYPE_CD,
act.CD_NM AS ACT_TYPE_CD_NM,
t3.VLTN_LWRG_CD_1,
vltn1.VLTN_LAW as VLTN_LAW_1,
vltn1.IMPLT_LAW as IMPLT_LAW_1,
vltn1.CRC_LAW as CRC_LAW_1,
t3.STRCT_IDX_CD,
strct.STRCT_NM AS STRCT_IDX_CD_NM,
t3.USG_IDX_CD,
usg.USG_NM AS USG_IDX_CD_NM,
t3.AREA
from tb_crdn t1
inner join tb_pstn_info t2 on t1.CRDN_YR = t2.CRDN_YR and t1.CRDN_NO = t2.CRDN_NO and t2.DEL_YN = 'N'
inner join tb_act_info t3 on t2.CRDN_YR = t3.CRDN_YR and t2.CRDN_NO = t3.CRDN_NO and t2.PSTN_INFO_ID = t3.PSTN_INFO_ID and t3.DEL_YN = 'N'
LEFT JOIN tb_cd_detail sgg ON sgg.CD_GROUP_ID = 'ORG_CD' AND sgg.CD_ID = t2.SGG_CD
LEFT JOIN tb_cd_detail emd ON emd.CD_GROUP_ID = 'STDG_EMD_CD' AND emd.CD_ID = t2.STDG_EMD_CD
LEFT JOIN tb_cd_detail ld ON ld.CD_GROUP_ID = 'LDCG_CD' AND ld.CD_ID = t2.LDCG_CD
LEFT JOIN tb_cd_detail act ON act.CD_GROUP_ID = 'ACT_TYPE_CD' AND act.CD_ID = t3.ACT_TYPE_CD
LEFT JOIN tb_vltn_lwrg vltn1 ON vltn1.VLTN_LWRG_CD = t3.VLTN_LWRG_CD_1 AND vltn1.DEL_YN = 'N'
LEFT JOIN tb_vltn_lwrg vltn2 ON vltn2.VLTN_LWRG_CD = t3.VLTN_LWRG_CD_2 AND vltn2.DEL_YN = 'N'
LEFT JOIN tb_strct_idx strct ON strct.STRCT_IDX_CD = t3.STRCT_IDX_CD AND strct.DEL_YN = 'N'
LEFT JOIN tb_usg_idx usg ON usg.USG_IDX_CD = t3.USG_IDX_CD AND usg.DEL_YN = 'N'
where t1.CRDN_YR = #{crdnYr}
and t1.CRDN_NO = #{crdnNo}
</select>
</mapper>

@ -0,0 +1,584 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="dateUtil" uri="http://egovframework.go.kr/functions/date-util" %>
<!-- 부과예고 관리 팝업 -->
<div class="popup_wrap">
<div class="popup_inner">
<div class="popup_tit">
<h2 class="tit" id="popupTitle">
<c:choose>
<c:when test="${mode eq 'U'}">부과예고 수정</c:when>
<c:when test="${mode eq 'V'}">부과예고 보기</c:when>
<c:otherwise>부과예고 등록</c:otherwise>
</c:choose>
</h2>
<a href="#" class="pop-x-btn modalclose" id="btnCloseTop"></a>
</div>
<div class="popup_con">
<div class="cash_tables">
<form id="impltTaskForm" name="impltTaskForm">
<input type="hidden" id="mode" name="mode" value="${mode}" />
<input type="hidden" id="impltInfoId" name="impltInfoId" value="${impltTaskInfo.impltInfoId}" />
<input type="hidden" id="crdnYr" name="crdnYr" value="${crdnYr}" />
<input type="hidden" id="crdnNo" name="crdnNo" value="${crdnNo}" />
<input type="hidden" id="pstnInfoId" name="pstnInfoId" value="${pstnData.pstnInfoId}" />
<table>
<colgroup>
<col style="width: 120px;" />
<col style="width: 120px;" />
<col style="width: 150px;" />
<col style="width: 180px;" />
<col style="width: 180px;" />
<col />
</colgroup>
<thead>
<tr>
<th>연도</th>
<th>단속번호</th>
<th>구분</th>
<th>단속동</th>
<th>행정처분시작일</th>
<th>행정처분종료일</th>
<th>행정처분간격일</th>
</tr>
</thead>
<tbody>
<tr>
<td>${crdnYr}</td>
<td>${crdnNo}</td>
<td>${crdnData.rgnSeCdNm}</td>
<td>${pstnData.stdgEmdCdNm}</td>
<td>
<input type="text" id="impltBgngYmd" name="impltBgngYmd" class="input calender datepicker"
style="width: 120px;" maxlength="10" validation-check="required"
value="${dateUtil:formatDateString(impltTaskInfo.impltBgngYmd)}" onchange="calculateDaysBetween();" />
</td>
<td>
<input type="text" id="impltEndYmd" name="impltEndYmd" class="input calender datepicker"
style="width: 120px;" maxlength="10" validation-check="required"
value="${dateUtil:formatDateString(impltTaskInfo.impltEndYmd)}" onchange="calculateDaysBetween();" />
</td>
<td>
<input type="text" id="impltDaysCnt" name="impltDaysCnt" class="input"
style="width: 100px; text-align: right" readonly value="${impltTaskInfo.impltDaysCnt}" />
일 (자동계산)
</td>
</tr>
</tbody>
</table>
</form>
</div>
<!-- 위치정보 영역 -->
<div class="box_column" style="margin-top: 20px;">
<ul class="box_title">
<li class="tit">위치 정보</li>
</ul>
<div class="containers">
<div class="tabels cols2 no-info">
<table class="display">
<thead>
<tr>
<th>법정동</th>
<th>지목</th>
<th>우편번호</th>
<th>지번주소</th>
<th>지적</th>
<th>공시지가</th>
</tr>
</thead>
<tbody>
<tr>
<td>${pstnData.stdgEmdCdNm}</td>
<td>${pstnData.ldcgCdNm}</td>
<td>${pstnData.zip}</td>
<td>${pstnData.lotnoWholAddr} ${pstnData.lotnoMno} ${pstnData.lotnoSno}</td>
<td><fmt:formatNumber value="${pstnData.ptout}" pattern="#,##0.00" /></td>
<td><fmt:formatNumber value="${pstnData.oalp}" pattern="#,##0" /></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- 그리드 영역 -->
<div class="box_column" style="margin-top: 20px;">
<ul class="box_title">
<li class="tit">위반 목록</li>
<span id="totalCount" class="total-count" style="padding-left: 25px;padding-right: 25px;">총 0건</span>
</ul>
<div class="containers">
<div id="grid"></div>
</div>
</div>
<!-- 산출조사서 영역 -->
<div class="box_column" style="margin-top: 20px;">
<ul class="box_title">
<li class="tit">이행강제금 산출조사서</li>
</ul>
<div class="containers">
<div class="tabels cols2 no-info">
<table class="display">
<tr>
<th rowspan="3" style="width: 100px;">이행강제금산출</th>
<th>시가표준액</th>
<th rowspan="2" style="width: 23px;">X</th>
<th>위반면적</th>
<th rowspan="2" style="width: 23px;">X</th>
<th>가감산시행령률</th>
<th rowspan="2" style="width: 23px;">X</th>
<th>산정률</th>
<th rowspan="2" style="width: 23px;">X</th>
<th>산정률2</th>
<th rowspan="2" style="width: 23px;">=</th>
<th>산정액</th>
</tr>
<tr>
<td><input type="text" class="input" value=""/></td>
<td><input type="text" class="input" value=""/></td>
<td><input type="text" class="input" value=""/></td>
<td><input type="text" class="input" value=""/></td>
<td><input type="text" class="input" value=""/></td>
<td><input type="text" class="input" value=""/></td>
</tr>
<tr>
<td colspan="12">부과총액 = 결과값</td>
</tr>
</table>
</div>
</div>
<div class="containers">
<div class="tabels cols2 no-info">
<table class="display">
<tr>
<th rowspan="3" style="width: 100px;">${crdnData.crdnYr}<br/>년도</th>
<th>건물<br/>기준시가액</th>
<th rowspan="3" style="width: 23px;">X</th>
<th>구조지수</th>
<th rowspan="3" style="width: 23px;">X</th>
<th>용도지수</th>
<th rowspan="3" style="width: 23px;">X</th>
<th>위치지수</th>
<th rowspan="3" style="width: 23px;">X</th>
<th>경과년수<br/>별잔가율</th>
<th rowspan="3" style="width: 23px;">X</th>
<th>기초공시율</th>
<th rowspan="3" style="width: 23px;">=</th>
<th>건축물<br/>과세시가</th>
<th>시가표준액<br/>(1,000원미만절삭)</th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td rowspan="2"></td>
<td rowspan="2"></td>
<td rowspan="2"></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
</div>
</div>
<!-- 팝업 버튼 -->
<div class="popup_foot">
<c:if test="${mode ne 'V'}">
<button type="button" id="btnSave" class="newbtns bg1">저장</button>
</c:if>
<button type="button" class="newbtns bg2 modalclose" id="btnClose">닫기</button>
</div>
</div>
</div>
<script type="text/javascript">
/**
* 부과예고 관리 팝업 스크립트
* 중요한 로직 주석: datepicker 적용, 자동 간격일 계산, 소유자/행위자 선택 기능 구현
*/
(function(window, $) {
'use strict';
var ImpltTaskPopup = {
// 팝업 모드 및 기본 정보
mode: '${mode}',
crdnYr: '${crdnYr}',
crdnNo: '${crdnNo}',
impltTaskSeCd: '${impltTaskSeCd}',
impltTaskSeCdNm: '${impltTaskSeCdNm}',
/**
* 그리드 관련 객체
*/
grid: {
/**
* 그리드 인스턴스
*/
instance: null,
/**
* 그리드 설정 초기화
* @returns {Object} 그리드 설정 객체
*/
initConfig: function() {
// 데이터 소스 설정
var dataSource = this.createDataSource();
// 그리드 설정 객체 생성
var gridConfig = new XitTuiGridConfig();
// 기본 설정
gridConfig.setOptDataSource(dataSource); // 데이터소스 연결
gridConfig.setOptGridId('grid'); // 그리드를 출력할 Element ID
gridConfig.setOptGridHeight(100); // 그리드 높이(단위: px)
gridConfig.setOptRowHeight(30); // 그리드 행 높이(단위: px)
gridConfig.setOptUseClientSort(true); // 클라이언트 사이드 정렬
gridConfig.setOptRowHeaderType('checkbox');
gridConfig.setOptColumns(this.getGridColumns());
return gridConfig;
},
/**
* 그리드 컬럼 정의
* @returns {Array} 그리드 컬럼 배열
*/
getGridColumns: function() {
var self = this;
return [
{ header: '행위유형코드', name: 'actTypeCd', align: 'center', width: 60, hidden: true},
{ header: '행위유형명', name: 'actTypeCdNm', align: 'center', width: 180},
{ header: '위반법규코드', name: 'vltnLwrgCd1', align: 'center', width: 60, hidden: true},
{ header: '위반법', name: 'vltnLaw1', align: 'center', width: 130},
{ header: '시정법', name: 'crcLaw1', align: 'center', width: 130, hidden: true},
{ header: '이행법', name: 'impltLaw1', align: 'center', width: 130, hidden: true},
{header: '위치정보ID', name: 'pstnInfoId', align: 'center', width: 60, hidden: true},
{header: '지목', name: 'ldcgCd', align: 'center', width: 60, hidden: true},
{header: '지목명', name: 'ldcgCdNm', align: 'center', width: 130},
{header: '지적', name: 'ptout', align: 'right', width: 100, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : ''; } },
{header: '공시지가', name: 'oalp', align: 'right', width: 140, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString() : ''; } },
{ header: '면적', name: 'area', align: 'right', width: 100, formatter: function(e){
//return e.value != null ? Number(e.value).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : '';
return e.value ? parseFloat(e.value).toFixed(2) : '-';
}
},
{ header: '우편번호', name: 'zip', align: 'center', width: 90, hidden: true },
{ header: '지번 전체주소', name: 'lotnoWholAddr', align: 'left', width: 300, hidden: true },
{ header: '지번', name: 'lotnoMSno', align: 'center', width: 80, hidden: true, formatter: function(row, col, cellValue, item, rowIndex) {
var mno = row.row.lotnoMno || '';
var sno = row.row.lotnoSno || '';
return mno + (sno ? ' - ' + sno : '');
}
},
{ header: '행위정보ID', name: 'actInfoId', align: 'center', width: 60, hidden: true},
{ header: '행위시작일자', name: 'actBgngYmd', align: 'center', width: 130,
formatter: function (e) {
return e.value ? moment(e.value).format('YYYY-MM-DD') : '';
}
},
{ header: '구조지수코드', name: 'strctIdxCd', align: 'center', width: 60, hidden: true},
{ header: '구조지수명', name: 'strctIdxCdNm', align: 'left', width: 150},
{ header: '용도지수코드', name: 'usgIdxCd', align: 'center', width: 60, hidden: true},
{ header: '용도지수명', name: 'usgIdxCdNm', align: 'left'},
];
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 설정 객체
*/
createDataSource: function() {
return {
api: {
readData: {
url: '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/actlist.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: false, // 초기 데이터 요청 여부
serializer: function(params) {
var defaultParams = $.param(params);
var extra = $.param({ "crdnYr": ImpltTaskPopup.crdnYr, "crdnNo": ImpltTaskPopup.crdnNo, "impltInfoId": $("#impltInfoId").val() });
return defaultParams + '&' + extra;
}
};
},
/**
* 그리드 인스턴스 생성
*/
create: function() {
var gridConfig = this.initConfig();
var Grid = tui.Grid;
this.instance = gridConfig.instance(Grid);
// 그리드 테마 설정
Grid.applyTheme('striped');
this.gridBindEvents();
},
/**
* 그리드 이벤트 바인딩
*/
gridBindEvents: function() {
var self = this;
// 데이터 로딩 완료 이벤트
this.instance.on('successResponse', function(ev) {
var responseObj = JSON.parse(ev.xhr.response);
console.log(responseObj);
if( responseObj && responseObj.data ){
// 총 개수 업데이트
$('#totalCount').text('총 ' + responseObj.data.contents.length + '건');
}
});
// 렌더링완료 후 check box
this.instance.on('onGridUpdated', function() {
var allRows = self.instance.getData();
var rowKey = null;
allRows.forEach(function(row) {
if (row.selected) {
rowKey = row.rowKey
}
// 1. 체크박스 선택
self.instance.check(rowKey);
});
});
},
},
/**
* 초기화
*/
init: function() {
// 그리드 생성
this.grid.create();
// 이벤트 핸들러 설정
this.eventBindEvents();
// 그리드 조회
this.grid.instance.readData();
},
/**
* 이벤트 초기화
*/
eventBindEvents: function() {
var self = this;
$('.datepicker').datepicker({
container: '.popup_inner',
language: "kr"
});
// 저장 버튼
$('#btnSave').on('click', function() {
self.save();
});
// 닫기 버튼 이벤트 바인딩
$('.modalclose').on('click', function(e) {
e.preventDefault();
self.cancel();
});
},
/**
* 팝업 취소 처리
* 중요한 로직 주석: 팝업창을 닫는 기능을 제공합니다.
*/
cancel: function() {
window.close();
},
/**
* 저장
* 중요한 로직 주석: 폼 데이터와 그리드에서 선택된 이행 대상자 정보를 수집하여 저장 요청을 보냅니다.
*/
save: function() {
var self = this;
// 유효성 검증
if (!this.validateForm()) {
return;
}
// 폼 데이터 수집
var formData = this.collectFormData();
// 그리드에서 선택된 이행 대상자 정보 수집
var selectedTrprInfoList = this.collectSelectedTrprInfo();
// 선택된 이행 대상자가 없으면 경고
if (selectedTrprInfoList.length === 0) {
alert('이행 대상자를 선택해주세요.');
return;
}
// 이행 대상자 정보를 formData에 추가
for (var i = 0; i < selectedTrprInfoList.length; i++) {
var trprInfo = selectedTrprInfoList[i];
for (var key in trprInfo) {
formData['impltTrprInfoList[' + i + '].' + key] = trprInfo[key];
}
}
var url = this.mode === 'C' ?
'<c:url value="/crdn/crndRegistAndView/crdnImpltTask/insertImpltInfo.ajax"/>' :
'<c:url value="/crdn/crndRegistAndView/crdnImpltTask/updateImpltInfo.ajax"/>';
$.ajax({
url: url,
type: 'POST',
data: formData,
success: function(response) {
if (response && response.success) {
alert(response.message || '부과예고가 성공적으로 저장되었습니다.');
if (window.opener && window.opener.refreshCrdnList) {
window.opener.refreshCrdnList();
}
window.close();
} else {
alert(response.message || '저장 중 오류가 발생했습니다.');
}
}
});
},
/**
* 폼 데이터 수집
* 중요한 로직 주석: 부과예고 등록/수정에 필요한 폼 데이터를 수집합니다.
*/
collectFormData: function() {
return {
mode: $('#mode').val(),
impltInfoId: $('#impltInfoId').val(),
crdnYr: $('#crdnYr').val(),
crdnNo: $('#crdnNo').val(),
impltTaskSeCd: $('#impltTaskSeCd').val(),
sggCd: $('#sggCd').val(),
impltBgngYmd: $('#impltBgngYmd').val().replace(/\D/g, ''), // 숫자만 추출 (YYYYMMDD 형태로)
impltEndYmd: $('#impltEndYmd').val().replace(/\D/g, ''), // 숫자만 추출 (YYYYMMDD 형태로)
impltDaysCnt: $('#impltDaysCnt').val()
};
},
/**
* 그리드에서 선택된 이행 대상자 정보 수집
* 중요한 로직 주석: 체크박스가 선택된 행의 데이터를 수집하여 이행 대상자 정보 배열을 생성합니다.
*/
collectSelectedTrprInfo: function() {
var selectedTrprInfoList = [];
var checkedRowKeys = this.grid.instance.getCheckedRowKeys();
if (checkedRowKeys && checkedRowKeys.length > 0) {
for (var i = 0; i < checkedRowKeys.length; i++) {
var rowKey = checkedRowKeys[i];
var rowData = this.grid.instance.getRow(rowKey);
if (rowData) {
// 이행 대상자 정보 객체 생성
var trprInfo = {
ownrActrInfoId: rowData.ownrActrInfoId,
impltTrprSeCd: rowData.impltTrprSeCd || '1', // 1:소유자, 2:행위자 (기본값: 소유자)
impltTrprFlnm: rowData.impltTrprFlnm,
impltTrprZip: rowData.impltTrprZip,
impltTrprAddr: rowData.impltTrprAddr,
impltTrprDaddr: rowData.impltTrprDaddr,
actNo: rowData.actNo,
actTypeCd: rowData.actTypeCd,
lotnoMno: rowData.lotnoMno,
lotnoSno: rowData.lotnoSno
};
selectedTrprInfoList.push(trprInfo);
}
}
}
return selectedTrprInfoList;
},
/**
* 폼 유효성 검증
*/
validateForm: function() {
if (!$('#impltBgngYmd').val()) {
alert('행정처분 시작일을 입력해주세요.');
$('#impltBgngYmd').focus();
return false;
}
if (!$('#impltEndYmd').val()) {
alert('행정처분 종료일을 입력해주세요.');
$('#impltEndYmd').focus();
return false;
}
if ($('#impltBgngYmd').val() > $('#impltEndYmd').val()) {
alert('행정처분 시작일은 종료일보다 이전이어야 합니다.');
$('#impltBgngYmd').focus();
return false;
}
return true;
},
};
/**
* 행정처분 간격일 자동 계산 함수
* 중요한 로직 주석: 시작일과 종료일 입력시 자동으로 간격일을 계산한다.
*/
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);
}
};
// 초기화 실행
$(document).ready(function() {
ImpltTaskPopup.init();
});
})(window, jQuery);
</script>

@ -444,6 +444,35 @@
});
},
/**
* 부과예고 관리 팝업을 엽니다.
*
* @param crdnYr 단속 연도
* @param crdnNo 단속 번호
* @param impltTaskSeCd 이행업무구분코드 (4:부과예고)
*/
openLevyPrvntcPopup: function(crdnYr, crdnNo, impltTaskSeCd) {
// 기존 이행정보가 있는지 확인하여 모드 결정
var self = this;
$.ajax({
url: '<c:url value="/crdn/crndRegistAndView/crdnImpltTask/selectImpltInfo.ajax"/>',
type: 'GET',
data: {
crdnYr: crdnYr,
crdnNo: crdnNo,
impltTaskSeCd: impltTaskSeCd
},
success: function(response) {
var mode = (response && response.success && response.data) ? 'U' : 'C';
var url = '<c:url value="/crdn/crndRegistAndView/crdnLevyPrvntc/levyPrvntcPopup.do"/>?mode=' + mode +
'&crdnYr=' + encodeURIComponent(crdnYr) +
'&crdnNo=' + encodeURIComponent(crdnNo) +
'&impltTaskSeCd=' + encodeURIComponent(impltTaskSeCd);
openPopup(url, 1600, 1200, 'levyPrvntcPopup');
}
});
},
/**
* 목록 현재 페이징 새로고침
*/
@ -591,7 +620,14 @@
});
$("#btnLevyPrvntc").on('click', function() {
self.updateStatus('50', '부과예고');
// 선택된 행 확인
if (!self.selectedRow) {
alert('부과예고를 관리할 단속 건을 선택해주세요.');
return;
}
// 시정촉구 팝업 열기
self.openLevyPrvntcPopup(self.selectedRow.crdnYr, self.selectedRow.crdnNo, '4'); // 3: 부과예고
});
$("#btnLevy").on('click', function() {

@ -16,7 +16,7 @@
.popup_inner {
position: relative;
width: 97%;
max-width: 1200px;
max-width: 1600px;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);

Loading…
Cancel
Save