기준자료 > 건물신축가격기준액

init
dev
박성영 4 months ago
parent 8ac78b2afc
commit a4459cc0fb

@ -0,0 +1,176 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import egovframework.util.SessionUtil;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.model.BldgNewPrcCrtrAmtVO;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.service.BldgNewPrcCrtrAmtService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
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.*;
/**
* packageName : go.kr.project.baseData.bldgNewPrcCrtrAmt.controller
* fileName : BldgNewPrcCrtrAmtController
* author :
* date : 2025-08-25
* description : >
* : 1) totalCount 2) setTotalCount 3) setPagingYn("Y") .
* // window.open , PK .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@Controller
@RequestMapping("/baseData/bldgNewPrcCrtrAmt")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "기준자료: 건물신축가격기준액", description = "건물신축가격기준액 관리 API")
public class BldgNewPrcCrtrAmtController {
/** 건물신축가격기준액 서비스 */
private final BldgNewPrcCrtrAmtService service;
/**
* .
* @param vo VO
* @param model
* @return
*/
@GetMapping("/list.do")
@Operation(summary = "건물신축가격기준액 목록 페이지", description = "목록 페이지를 조회합니다.")
public String listPage(BldgNewPrcCrtrAmtVO vo, Model model){
log.debug("건물신축가격기준액 목록 페이지 조회");
return "baseData/bldgNewPrcCrtrAmt/list" + TilesConstants.BASE;
}
/**
* AJAX .
* .
* @param vo VO
* @return ResponseEntity
*/
@PostMapping("/list.ajax")
@Operation(summary = "목록 조회(AJAX)", description = "페이징 목록을 JSON으로 반환")
@ApiResponse(responseCode = "200", description = "성공")
public ResponseEntity<?> listAjax(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 목록 AJAX 조회 - 검색조건: {}", vo);
int total = service.selectListTotalCount(vo); // 1. 총 개수 조회
vo.setTotalCount(total); // 2. setTotalCount
//vo.setPagingYn("Y"); // 3. 페이징 처리
return ApiResponseUtil.successWithGrid(service.selectList(vo), vo);
}
/**
* / .
* PK(, ) , .
* @param vo PK VO
* @param model
* @return
*/
@GetMapping("/popup.do")
@Operation(summary = "등록/수정 팝업", description = "window.open으로 호출되는 팝업")
public String popup(@ModelAttribute BldgNewPrcCrtrAmtVO vo, Model model){
log.debug("건물신축가격기준액 팝업 조회 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
if (vo.getYr() != null && vo.getNo() != null){
model.addAttribute("data", service.selectOne(vo));
}
return "baseData/bldgNewPrcCrtrAmt/popup"+ TilesConstants.POPUP;
}
/**
* .
* PK(+) .
* @param vo VO
* @return ResponseEntity
*/
@PostMapping("/register.ajax")
@Operation(summary = "등록", description = "신규 데이터 등록")
public ResponseEntity<?> register(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 등록 요청 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 등록 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// PK 중복 체크
int duplicateCount = service.selectDuplicateCheck(vo);
if (duplicateCount > 0) {
log.warn("건물신축가격기준액 등록 실패 - 중복된 PK: 연도={}, 번호={}", vo.getYr(), vo.getNo());
return ApiResponseUtil.error("이미 존재하는 연도와 번호입니다. 다른 값을 입력해주세요.");
}
// 등록자 정보 설정 및 등록 수행
vo.setRgtr(SessionUtil.getUserId());
int r = service.insert(vo);
log.debug("건물신축가격기준액 등록 완료 - 등록 건수: {}", r);
return ApiResponseUtil.success(r);
}
/**
* .
* PK(+) .
* @param vo VO
* @return ResponseEntity
*/
@PostMapping("/update.ajax")
@Operation(summary = "수정", description = "기존 데이터 수정")
public ResponseEntity<?> update(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 수정 요청 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 수정 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// 수정 수행
int r = service.update(vo);
log.debug("건물신축가격기준액 수정 완료 - 수정 건수: {}", r);
return ApiResponseUtil.success(r);
}
/**
* .
* PK(+) .
* @param vo PK (yr, no) VO
* @return ResponseEntity
*/
@PostMapping("/delete.ajax")
@Operation(summary = "삭제", description = "기존 데이터 삭제")
public ResponseEntity<?> delete(@ModelAttribute BldgNewPrcCrtrAmtVO vo){
log.debug("건물신축가격기준액 삭제 요청 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
// PK(연도+번호) 필수값 검증
if (vo.getYr() == null || vo.getYr().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 연도 미입력");
return ApiResponseUtil.error("연도는 필수값입니다.");
}
if (vo.getNo() == null || vo.getNo().trim().isEmpty()) {
log.warn("건물신축가격기준액 삭제 실패 - 번호 미입력");
return ApiResponseUtil.error("번호는 필수값입니다.");
}
// 삭제 수행
int r = service.delete(vo);
log.debug("건물신축가격기준액 삭제 완료 - 삭제 건수: {}", r);
return ApiResponseUtil.success(r);
}
}

@ -0,0 +1,71 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.mapper;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.model.BldgNewPrcCrtrAmtVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* packageName : go.kr.project.baseData.bldgNewPrcCrtrAmt.mapper
* fileName : BldgNewPrcCrtrAmtMapper
* author :
* date : 2025-08-25
* description : MyBatis Mapper
* : SQL .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@Mapper
public interface BldgNewPrcCrtrAmtMapper {
/**
* .
* @param vo VO
* @return
*/
List<BldgNewPrcCrtrAmtVO> selectList(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int selectListTotalCount(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
BldgNewPrcCrtrAmtVO selectOne(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int insert(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int update(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
int delete(BldgNewPrcCrtrAmtVO vo);
/**
* PK(+) .
* @param vo PK (yr, no) VO
* @return (0 , 1 )
*/
int selectDuplicateCheck(BldgNewPrcCrtrAmtVO vo);
}

@ -0,0 +1,54 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import go.kr.project.common.model.PagingVO;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* packageName : go.kr.project.baseData.bldgNewPrcCrtrAmt.model
* fileName : BldgNewPrcCrtrAmtVO
* author :
* date : 2025-08-25
* description : VO (// )
* : VO MyBatis camelCase DB (YR, NO, BDST_USG, BLDG_NEW_PRC_CRTR_AMT, REG_DT, RGTR)
* (yr, no, bdstUsg, bldgNewPrcCrtrAmt, regDt, rgtr) .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class BldgNewPrcCrtrAmtVO extends PagingVO {
/** 연도 (PK1) - 4자리 연도 형식 (예: 2025) */
private String yr;
/** 번호 (PK2) - 1~9 범위의 1자리 번호 */
private String no;
/** 건축물 용도 - 건축물의 종류나 사용 목적을 나타내는 텍스트 */
private String bdstUsg;
/** 건물 신축 가격 기준 액 - 원/㎡ 단위의 기준 금액 */
private BigDecimal bldgNewPrcCrtrAmt;
/** 등록 일시 - 테이블은 date 컬럼을 사용하지만 화면 표시용으로 문자열 타입 사용 */
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime regDt;
/** 등록자 - 데이터를 등록한 사용자 ID */
private String rgtr;
/** 검색용 연도 - 목록 조회 시 연도 검색 조건으로 사용 */
private String schYr;
}

@ -0,0 +1,69 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.service;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.model.BldgNewPrcCrtrAmtVO;
import java.util.List;
/**
* packageName : go.kr.project.baseData.bldgNewPrcCrtrAmt.service
* fileName : BldgNewPrcCrtrAmtService
* author :
* date : 2025-08-25
* description :
* : .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
public interface BldgNewPrcCrtrAmtService {
/**
* .
* @param vo VO
* @return
*/
List<BldgNewPrcCrtrAmtVO> selectList(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int selectListTotalCount(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
BldgNewPrcCrtrAmtVO selectOne(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int insert(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo VO
* @return
*/
int update(BldgNewPrcCrtrAmtVO vo);
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
int delete(BldgNewPrcCrtrAmtVO vo);
/**
* PK(+) .
* @param vo PK (yr, no) VO
* @return (0 , 1 )
*/
int selectDuplicateCheck(BldgNewPrcCrtrAmtVO vo);
}

@ -0,0 +1,109 @@
package go.kr.project.baseData.bldgNewPrcCrtrAmt.service.impl;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.mapper.BldgNewPrcCrtrAmtMapper;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.model.BldgNewPrcCrtrAmtVO;
import go.kr.project.baseData.bldgNewPrcCrtrAmt.service.BldgNewPrcCrtrAmtService;
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.baseData.bldgNewPrcCrtrAmt.service.impl
* fileName : BldgNewPrcCrtrAmtServiceImpl
* author :
* date : 2025-08-25
* description :
* : .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-25
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class BldgNewPrcCrtrAmtServiceImpl extends EgovAbstractServiceImpl implements BldgNewPrcCrtrAmtService {
/** 건물신축가격기준액 매퍼 */
private final BldgNewPrcCrtrAmtMapper mapper;
/**
* .
* @param vo VO
* @return
*/
@Override
public List<BldgNewPrcCrtrAmtVO> selectList(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 목록 조회 - 검색조건: {}", vo);
return mapper.selectList(vo);
}
/**
* .
* @param vo VO
* @return
*/
@Override
public int selectListTotalCount(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 총 개수 조회 - 검색조건: {}", vo);
return mapper.selectListTotalCount(vo);
}
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
@Override
public BldgNewPrcCrtrAmtVO selectOne(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 단건 조회 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
return mapper.selectOne(vo);
}
/**
* .
* @param vo VO
* @return
*/
@Override
public int insert(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 등록 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
return mapper.insert(vo);
}
/**
* .
* @param vo VO
* @return
*/
@Override
public int update(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 수정 - 연도: {}, 번호: {}, 용도: {}", vo.getYr(), vo.getNo(), vo.getBdstUsg());
return mapper.update(vo);
}
/**
* .
* @param vo PK (yr, no) VO
* @return
*/
@Override
public int delete(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 삭제 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
return mapper.delete(vo);
}
/**
* PK(+) .
* @param vo PK (yr, no) VO
* @return (0 , 1 )
*/
@Override
public int selectDuplicateCheck(BldgNewPrcCrtrAmtVO vo) {
log.debug("건물신축가격기준액 중복 체크 - 연도: {}, 번호: {}", vo.getYr(), vo.getNo());
return mapper.selectDuplicateCheck(vo);
}
}

@ -0,0 +1,121 @@
<?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.baseData.bldgNewPrcCrtrAmt.mapper.BldgNewPrcCrtrAmtMapper">
<!--
건물신축가격기준액 목록 조회
- 검색 조건: 연도(schYr)
- 정렬: 연도 내림차순, 번호 오름차순
- 페이징: startIndex, perPage를 사용한 LIMIT 구문 적용
-->
<select id="selectList" parameterType="BldgNewPrcCrtrAmtVO" resultType="BldgNewPrcCrtrAmtVO">
select YR /* 연도 */
, NO /* 번호 */
, BDST_USG /* 건축물 용도 */
, BLDG_NEW_PRC_CRTR_AMT /* 건물 신축 가격 기준 액 */
, REG_DT /* 등록 일시 */
, RGTR /* 등록자 */
from tb_bldg_new_prc_crtr_amt
where 1=1
<if test='schYr != null and schYr != ""'>
and YR = #{schYr} /* 연도 검색 조건 */
</if>
order by YR desc, NO asc /* 연도 내림차순, 번호 오름차순 정렬 */
<if test='pagingYn != null and pagingYn == "Y"'>
limit #{startIndex}, #{perPage} /* 서버사이드 페이징 처리 */
</if>
</select>
<!--
건물신축가격기준액 목록 총 개수 조회
- 검색 조건: 연도(schYr)
- 페이징 처리를 위한 전체 건수 반환
-->
<select id="selectListTotalCount" parameterType="BldgNewPrcCrtrAmtVO" resultType="int">
select count(*) /* 총 개수 조회 */
from tb_bldg_new_prc_crtr_amt
where 1=1
<if test='schYr != null and schYr != ""'>
and YR = #{schYr} /* 연도 검색 조건 */
</if>
</select>
<!--
건물신축가격기준액 단건 조회
- 조건: PK(연도 + 번호)
- 팝업에서 수정/삭제 모드 시 사용
-->
<select id="selectOne" parameterType="BldgNewPrcCrtrAmtVO" resultType="BldgNewPrcCrtrAmtVO">
select YR /* 연도 */
, NO /* 번호 */
, BDST_USG /* 건축물 용도 */
, BLDG_NEW_PRC_CRTR_AMT /* 건물 신축 가격 기준 액 */
, REG_DT /* 등록 일시 */
, RGTR /* 등록자 */
from tb_bldg_new_prc_crtr_amt
where YR = #{yr} /* 연도 조건 */
and NO = #{no} /* 번호 조건 */
</select>
<!--
건물신축가격기준액 정보 등록
- PK: 연도(YR) + 번호(NO)
- 등록일시는 CURDATE() 함수로 자동 설정
-->
<insert id="insert" parameterType="BldgNewPrcCrtrAmtVO">
insert into tb_bldg_new_prc_crtr_amt (
YR /* 연도 */
, NO /* 번호 */
, BDST_USG /* 건축물 용도 */
, BLDG_NEW_PRC_CRTR_AMT /* 건물 신축 가격 기준 액 */
, REG_DT /* 등록 일시 */
, RGTR /* 등록자 */
) values (
#{yr} /* 연도 */
, #{no} /* 번호 */
, #{bdstUsg} /* 건축물 용도 */
, #{bldgNewPrcCrtrAmt} /* 건물 신축 가격 기준 액 */
, NOW() /* 등록 일시 - 현재 날짜 자동 설정 */
, #{rgtr} /* 등록자 - 세션 사용자 ID */
)
</insert>
<!--
건물신축가격기준액 정보 수정
- 조건: PK(연도 + 번호)
- 수정 대상: 건축물 용도, 기준액
- 등록일시와 등록자는 수정하지 않음
-->
<update id="update" parameterType="BldgNewPrcCrtrAmtVO">
update tb_bldg_new_prc_crtr_amt
set BDST_USG = #{bdstUsg} /* 건축물 용도 수정 */
, BLDG_NEW_PRC_CRTR_AMT = #{bldgNewPrcCrtrAmt} /* 기준액 수정 */
where YR = #{yr} /* 연도 조건 */
and NO = #{no} /* 번호 조건 */
</update>
<!--
건물신축가격기준액 정보 삭제
- 조건: PK(연도 + 번호)
- 물리적 삭제 수행
-->
<delete id="delete" parameterType="BldgNewPrcCrtrAmtVO">
delete from tb_bldg_new_prc_crtr_amt
where YR = #{yr} /* 연도 조건 */
and NO = #{no} /* 번호 조건 */
</delete>
<!--
PK(연도+번호) 중복 체크
- 등록 시 동일한 PK가 존재하는지 확인
- 반환값: 0이면 중복 없음, 1이상이면 중복 존재
-->
<select id="selectDuplicateCheck" parameterType="BldgNewPrcCrtrAmtVO" resultType="int">
select count(*) /* 중복 건수 조회 */
from tb_bldg_new_prc_crtr_amt
where YR = #{yr} /* 연도 조건 */
and NO = #{no} /* 번호 조건 */
</select>
</mapper>

@ -0,0 +1,359 @@
<%@ 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" %>
<!-- Main body -->
<div class="main_body">
<section id="section8" class="main_bars">
<div class="bgs-main">
<section id="section5">
<div class="sub_title"></div>
<button type="button" id="registerBtn" class="newbtn bg1 info_a1">등록</button>
</section>
</div>
</section>
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
<li class="th">연도</li>
<li>
<input type="text" id="schYr" name="schYr" maxlength="4" class="input calender" style="width: 80px;" autocomplete="off" value="${dateUtil:getCurrentDateTime('yyyy')}"/>
</li>
<li class="th">건축물 용도</li>
<li>
<input type="text" id="schBdstUsg" name="schBdstUsg" maxlength="100" class="input"/>
</li>
</ul>
<ul class="rig2">
<li><button type="button" id="search_btn" class="newbtnss bg1">검색</button></li>
</ul>
</div>
<div class="gs_booking">
<div class="row">
<div class="col-sm-12">
<div class="box_column">
<ul class="box_title" style="display: flex; justify-content: space-between; align-items: center;">
<li class="tit">건물신축가격기준액 목록</li>
<li style="text-align: right;">
</li>
</ul>
<div class="containers">
<div id="grid"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /Main body -->
<script type="text/javascript">
/**
* 건물신축가격기준액 목록 관리 모듈
* 건물신축가격기준액 목록을 조회하고 관리하는 기능을 제공합니다.
*/
(function(window, $) {
'use strict';
var SEARCH_COND = {};
// 검색정보 설정
var setSearchCond = function() {
var schYr = $.trim(nvl($("#schYr").val(), ""));
var schBdstUsg = $.trim(nvl($("#schBdstUsg").val(), ""));
SEARCH_COND.schYr = schYr;
SEARCH_COND.schBdstUsg = schBdstUsg;
};
/**
* 건물신축가격기준액 목록 관리 네임스페이스
*/
var BldgNewPrcCrtrAmtList = {
/**
* 선택된 행 정보
*/
selectedRow: null,
/**
* 그리드 관련 객체
*/
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(550); // 그리드 높이(단위: px)
gridConfig.setOptRowHeight(30); // 그리드 행 높이(단위: px)
gridConfig.setOptRowHeaderType('rowNum'); // 행 첫번째 셀 타입(rowNum: 순번, checkbox: 체크박스, '': 출력 안함)
gridConfig.setOptUseClientSort(true); // 서버사이드 정렬 false
gridConfig.setOptColumns(this.getGridColumns());
return gridConfig;
},
/**
* 그리드 컬럼 정의
* @returns {Array} 그리드 컬럼 배열
*/
getGridColumns: function() {
return [
{
header: '연도',
name: 'yr',
width: 100,
align: 'center'
},
{
header: '번호',
name: 'no',
width: 80,
align: 'center'
},
{
header: '건축물 용도',
name: 'bdstUsg',
minWidth: 200,
align: 'left'
},
{
header: '기준액(원/㎡)',
name: 'bldgNewPrcCrtrAmt',
width: 200,
align: 'right',
formatter: function(props) {
var value = props.value;
return (value == null || value === '') ? '' : Number(value).toLocaleString();
}
},
{
header: '등록일',
name: 'regDt',
width: 200,
align: 'center'
},
{
header: '등록자',
name: 'rgtr',
width: 150,
align: 'center'
}
];
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 객체
*/
createDataSource: function() {
return {
api: {
readData: {
url: '<c:url value="/baseData/bldgNewPrcCrtrAmt/list.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: true, // 초기 데이터 요청 여부
serializer: function(params) {
// 기본 파라미터 (페이지 정보 등)
var defaultParams = $.param(params);
// 검색 폼 데이터
setSearchCond();
var searchParams = $.param(SEARCH_COND);
// 모든 파라미터 조합
console.log(defaultParams + '&' + searchParams);
return defaultParams + '&' + searchParams;
}
};
},
/**
* 그리드 인스턴스 생성
*/
create: function() {
var gridConfig = this.initConfig();
var Grid = tui.Grid;
this.instance = gridConfig.instance(Grid);
// 그리드 테마 설정
Grid.applyTheme('striped');
// 드롭다운 메뉴가 잘리지 않도록 overflow 설정 조정
$('#grid').css('overflow', 'visible');
$('.containers').css('overflow', 'visible');
$('.gs_booking').css('overflow', 'visible');
// 그리드 이벤트 설정
this.gridBindEvents();
},
/**
* 그리드 이벤트 바인딩
*/
gridBindEvents: function() {
var self = this;
// 요청 성공 시 총 건수 표시
this.instance.on('successResponse', function(ev) {
var responseObj = JSON.parse(ev.xhr.response);
});
}
},
/**
* 이벤트 핸들러 설정
*/
eventBindEvents: function() {
var self = this;
// 검색 버튼 클릭 이벤트
$('#search_btn').on('click', function() {
// 페이지를 1로 리셋
self.grid.instance.readData(1);
});
// 검색어 입력 필드에서 엔터키 이벤트 처리
$('#schYr, #schBdstUsg').on('keypress', function(e) {
if (e.which === 13) { // 엔터키 코드는 13
e.preventDefault(); // 기본 이벤트 방지
$('#search_btn').trigger('click'); // 검색 버튼 클릭 이벤트 트리거
}
});
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', function() {
var perPage = parseInt($(this).val(), 10);
// Grid의 perPage 설정 변경 및 데이터 리로드
self.grid.instance.setPerPage(perPage);
});
// 등록 버튼 클릭 이벤트
$('#registerBtn').on('click', function() {
self.openRegisterPopup();
});
// 수정 버튼 클릭 이벤트
$('#btnEdit').on('click', function() {
self.openEditPopup();
});
// 삭제 버튼 클릭 이벤트
$('#btnDelete').on('click', function() {
self.openDeletePopup();
});
},
/**
* 등록 팝업 열기
*/
openRegisterPopup: function() {
window.open('<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>', 'bldgNewPrcCrtrAmtReg', 'width=700,height=500,scrollbars=yes');
},
/**
* 수정 팝업 열기
*/
openEditPopup: function() {
if (!this.selectedRow) {
alert('수정할 행을 선택하세요.');
return;
}
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>?yr=' +
encodeURIComponent(this.selectedRow.yr) + '&no=' +
encodeURIComponent(this.selectedRow.no);
window.open(url, 'bldgNewPrcCrtrAmtEdit', 'width=700,height=500,scrollbars=yes');
},
/**
* 삭제 팝업 열기
*/
openDeletePopup: function() {
if (!this.selectedRow) {
alert('삭제할 행을 선택하세요.');
return;
}
var url = '<c:url value="/baseData/bldgNewPrcCrtrAmt/popup.do"/>?yr=' +
encodeURIComponent(this.selectedRow.yr) + '&no=' +
encodeURIComponent(this.selectedRow.no) + '&mode=D';
window.open(url, 'bldgNewPrcCrtrAmtDel', 'width=700,height=500,scrollbars=yes');
},
/**
* 목록 새로고침
*/
refreshList: function() {
if (this.grid.instance) {
var currentPage = this.grid.instance.getPagination().getCurrentPage() || 1;
this.grid.instance.readData(currentPage);
}
},
/**
* 연도 검색 yearpicker 초기화
*/
initYearPicker: function() {
// 연도 검색 필드에 yearpicker 적용
$('#schYr').datepicker({
format: "yyyy",
startView: "years",
minViewMode: "years",
autoclose: true,
language: "ko"
});
},
/**
* 모듈 초기화
*/
init: function() {
// 그리드 생성
this.grid.create();
// 이벤트 핸들러 설정
this.eventBindEvents();
// 연도 검색 yearpicker 초기화
this.initYearPicker();
}
};
// 페이지 로드 시 초기화
$(function() {
BldgNewPrcCrtrAmtList.init();
});
// 전역 네임스페이스에 모듈 노출
window.BldgNewPrcCrtrAmtList = BldgNewPrcCrtrAmtList;
// 팝업에서 호출할 새로고침 함수
window.refreshList = function() {
BldgNewPrcCrtrAmtList.refreshList();
};
})(window, jQuery);
</script>

@ -0,0 +1,396 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="popup_wrap">
<div class="popup_inner">
<div class="popup_tit">
<h2 class="tit">건물신축가격기준액 관리</h2>
<a href="#" class="pop-x-btn modalclose"></a>
</div>
<div class="popup_con">
<div class="forms_table_non">
<form id="bldgNewPrcCrtrAmtForm" name="bldgNewPrcCrtrAmtForm">
<input type="hidden" id="mode" name="mode" value="${param.mode}" />
<table>
<tr>
<th class="th"><span class="required">*</span> 연도</th>
<td>
<input type="text" id="yr" name="yr" class="input calender"
value="${data.yr}" maxlength="4"
validation-check="required"
style="width: 100px;"
placeholder="YYYY" readonly />
<div class="hint-message">※ 4자리 연도를 선택하세요. (클릭하여 연도 선택)</div>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 번호</th>
<td>
<input type="text" id="no" name="no" class="input"
value="${data.no}" maxlength="1"
validation-check="required"
style="width: 80px;"
placeholder="1" />
<div class="hint-message">※ 1~9 사이의 한 자리 번호를 입력하세요.</div>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 건축물 용도</th>
<td>
<input type="text" id="bdstUsg" name="bdstUsg" class="input"
value="${data.bdstUsg}" maxlength="60"
validation-check="required"
style="width: 400px;"
placeholder="건축물 용도를 입력하세요" />
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 기준액(원/㎡)</th>
<td>
<input type="text" id="bldgNewPrcCrtrAmt" name="bldgNewPrcCrtrAmt" class="input"
value="${data.bldgNewPrcCrtrAmt}"
validation-check="required"
style="width: 200px; text-align: right;" />
<div class="hint-message">※ 숫자만 입력하세요. (천단위 콤마는 자동으로 처리됩니다.)</div>
</td>
</tr>
</table>
</form>
</div>
</div>
<div class="popup_foot">
<c:choose>
<c:when test="${param.mode eq 'D'}">
<!-- 삭제 모드 -->
<a href="#" id="btnDelete" class="newbtns bg3">삭제</a>
</c:when>
<c:when test="${not empty data.yr and not empty data.no}">
<!-- 수정 모드 -->
<a href="#" id="btnSave" class="newbtns bg4">수정</a>
</c:when>
<c:otherwise>
<!-- 등록 모드 -->
<a href="#" id="btnSave" class="newbtns bg4">저장</a>
</c:otherwise>
</c:choose>
<a href="#" class="newbtns bg1 modalclose">취소</a>
</div>
</div>
</div>
<script type="text/javascript">
/**
* 건물신축가격기준액 팝업 관리 모듈
* 건물신축가격기준액 등록/수정/삭제를 처리합니다.
* form.jsp 스타일과 동일한 구조와 패턴을 사용합니다.
*/
(function(window, $) {
'use strict';
/**
* 건물신축가격기준액 팝업 네임스페이스
*/
var BldgNewPrcCrtrAmtForm = {
/**
* 현재 모드 ('', 'D')
*/
mode: '${param.mode}',
/**
* 번호 입력 제한 (1~9)
* @param {string} value 검증할 값
* @returns {boolean} 검증 결과
*/
validateNoRange: function(value) {
if (!value) return false;
var numVal = parseInt(value, 10);
return numVal >= 1 && numVal <= 9;
},
/**
* 연도 형식 검증 (4자리)
* @param {string} year 검증할 연도
* @returns {boolean} 검증 결과
*/
validateYear: function(year) {
if (!year || year.length !== 4) return false;
var yearNum = parseInt(year, 10);
var currentYear = new Date().getFullYear();
return yearNum >= 1900 && yearNum <= currentYear + 10;
},
/**
* 기준액 숫자 검증
* @param {string} value 검증할 값
* @returns {boolean} 검증 결과
*/
validateAmount: function(value) {
if (!value) return false;
// 콤마 제거 후 숫자인지 확인
var numStr = value.replace(/,/g, '');
return /^\d+$/.test(numStr);
},
/**
* 폼 유효성 검증
* @returns {boolean} 유효성 검증 결과
*/
validateForm: function() {
// 기본 validation-check 속성 기반 검증
var isValid = validateFormByAttributes('bldgNewPrcCrtrAmtForm');
if (isValid) {
var year = $.trim($('#yr').val());
var no = $.trim($('#no').val());
var amount = $.trim($('#bldgNewPrcCrtrAmt').val());
// 연도 검증
if (!this.validateYear(year)) {
alert('올바른 4자리 연도를 입력하세요. (1900~' + (new Date().getFullYear() + 10) + ')');
$('#yr').focus();
return false;
}
// 번호 검증 (1~9)
if (!this.validateNoRange(no)) {
alert('번호는 1~9 사이의 한 자리 숫자를 입력하세요.');
$('#no').focus();
return false;
}
// 기준액 검증
if (!this.validateAmount(amount)) {
alert('기준액은 숫자만 입력 가능합니다.');
$('#bldgNewPrcCrtrAmt').focus();
return false;
}
}
return isValid;
},
/**
* 숫자 포맷팅 (천단위 콤마)
* @param {string} value 포맷팅할 값
* @returns {string} 포맷팅된 값
*/
formatNumber: function(value) {
if (!value) return '';
var numStr = value.replace(/,/g, '');
if (!/^\d+$/.test(numStr)) return value;
return parseInt(numStr, 10).toLocaleString();
},
/**
* 폼 데이터 수집
* @returns {Object} 폼 데이터 객체
*/
getFormData: function() {
return {
yr: $.trim($('#yr').val()),
no: $.trim($('#no').val()),
bdstUsg: $.trim($('#bdstUsg').val()),
bldgNewPrcCrtrAmt: $.trim($('#bldgNewPrcCrtrAmt').val()).replace(/,/g, '')
};
},
/**
* 데이터 저장/수정
*/
save: function() {
var self = this;
if (!this.validateForm()) {
return;
}
var formData = this.getFormData();
var isEdit = (this.mode !== 'D' && formData.yr && formData.no && '${data.yr}' && '${data.no}');
var url = isEdit ?
'<c:url value="/baseData/bldgNewPrcCrtrAmt/update.ajax"/>' :
'<c:url value="/baseData/bldgNewPrcCrtrAmt/register.ajax"/>';
$.ajax({
url: url,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
alert(isEdit ? '수정되었습니다.' : '저장되었습니다.');
if (window.opener && window.opener.refreshList) {
window.opener.refreshList();
}
window.close();
} else {
alert(response.message || (isEdit ? '수정에 실패했습니다.' : '저장에 실패했습니다.'));
}
},
error: function(xhr, status, error) {
// 에러 처리는 xit-common.js의 ajaxError에서 처리됨
}
});
},
/**
* 데이터 삭제
*/
delete: function() {
var self = this;
if (!confirm('정말로 삭제하시겠습니까?')) {
return;
}
var formData = this.getFormData();
$.ajax({
url: '<c:url value="/baseData/bldgNewPrcCrtrAmt/delete.ajax"/>',
type: 'POST',
data: {
yr: formData.yr,
no: formData.no
},
success: function(response) {
if (response.success) {
alert('삭제되었습니다.');
if (window.opener && window.opener.refreshList) {
window.opener.refreshList();
}
window.close();
} else {
alert(response.message || '삭제에 실패했습니다.');
}
},
error: function(xhr, status, error) {
// 에러 처리는 xit-common.js의 ajaxError에서 처리됨
}
});
},
/**
* 닫기 처리
*/
cancel: function() {
if (confirm('입력한 내용이 저장되지 않습니다. 창을 닫으시겠습니까?')) {
window.close();
}
},
/**
* 이벤트 핸들러 설정
*/
eventBindEvents: function() {
var self = this;
// 저장/수정 버튼 클릭 이벤트
$('#btnSave').on('click', function(e) {
e.preventDefault();
self.save();
});
// 삭제 버튼 클릭 이벤트
$('#btnDelete').on('click', function(e) {
e.preventDefault();
self.delete();
});
// 취소/닫기 버튼 클릭 이벤트 (modalclose 클래스 포함)
$('.modalclose').on('click', function(e) {
e.preventDefault();
self.cancel();
});
// 연도 yearpicker 동적 초기화 (document 기반)
$(document).on('focus', '#yr', function() {
if (!$(this).hasClass('hasDatepicker')) {
$(this).datepicker({
container: '.popup_inner',
format: "yyyy",
startView: "years",
minViewMode: "years",
autoclose: true,
language: "ko"
});
}
});
// 번호 입력 제한 (1자리 숫자, 1~9)
$('#no').on('input', function() {
var value = $(this).val().replace(/[^1-9]/g, '');
if (value.length > 1) {
value = value.substring(0, 1);
}
$(this).val(value);
});
// 기준액 입력 제한 및 실시간 콤마 처리
$('#bldgNewPrcCrtrAmt').on('input', function() {
var value = $(this).val().replace(/[^0-9]/g, '');
if (value) {
// 실시간으로 콤마 추가
$(this).val(parseInt(value, 10).toLocaleString());
} else {
$(this).val('');
}
});
// 기준액 포맷팅 (blur 이벤트 - 추가 보완)
$('#bldgNewPrcCrtrAmt').on('blur', function() {
var value = $(this).val();
if (value) {
$(this).val(self.formatNumber(value));
}
});
// 엔터키 처리
$('#bldgNewPrcCrtrAmtForm').on('keypress', function(e) {
if (e.which === 13) { // 엔터키
e.preventDefault();
if (self.mode === 'D') {
self.delete();
} else {
self.save();
}
}
});
},
/**
* 삭제 모드 처리
*/
initDeleteMode: function() {
if (this.mode === 'D') {
// 입력 필드 비활성화
$('#bldgNewPrcCrtrAmtForm input[type="text"]').prop('disabled', true);
$('#bldgNewPrcCrtrAmtForm input[type="text"]').addClass('disabled');
}
},
/**
* 모듈 초기화
*/
init: function() {
// 삭제 모드 처리
this.initDeleteMode();
// 이벤트 핸들러 설정
this.eventBindEvents();
// 첫 번째 입력 필드에 포커스 (연도 필드는 자동 포커스 제외하여 datepicker 자동 오픈 방지)
if (this.mode !== 'D') {
//$('#no').focus();
}
}
};
// 페이지 로드 시 초기화
$(function() {
BldgNewPrcCrtrAmtForm.init();
});
// 전역 네임스페이스에 모듈 노출
window.BldgNewPrcCrtrAmtForm = BldgNewPrcCrtrAmtForm;
})(window, jQuery);
</script>

@ -74,7 +74,7 @@
<script type="text/javascript" src="<c:url value='/xit/menu-path.js' />"></script>
<script type="text/javascript" src="<c:url value='/xit/common_util.js' />"></script>
<script type="text/javascript" src="<c:url value='/xit/datatables_util.js' />"></script>
<script type="text/javascript" src="<c:url value='/xit/moment.js' />"></script>
<script type="text/javascript" src="<c:url value='/js/moment.js' />"></script>
<%-- popup 스타일 --%>
<link rel="stylesheet" type="text/css" href="<c:url value='/xit/xit-popup.css' />">

Loading…
Cancel
Save