소유자·행위자 관리: 병합처리

dev
박성영 4 months ago
parent 946766dd44
commit db110c4992

@ -1,95 +0,0 @@
package go.kr.project.crdn.crndRegistAndView.crdnActrSelect.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.model.CrdnActrSelectVO;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.service.CrdnActrSelectService;
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.actrSelect.controller
* fileName : ActrSelectController
* author :
* date : 2025-08-28
* description :
* : TB_OWNR API . (setTotalCountsetPagingYn) .
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-28
*/
@Controller
@RequestMapping("/crdn/crndRegistAndView/crdnActrSelect")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "행위자 선택", description = "행위자 선택 팝업 API")
public class CrdnActrSelectController {
private final CrdnActrSelectService service;
/**
* .
* .
*
* @param crdnYr
* @param crdnNo
* @param actInfoId
* @param model
* @return ModelAndView
*/
@GetMapping("/crdnActrSelectPopup.do")
@Operation(summary = "행위자 선택 팝업", description = "행위자 선택을 위한 팝업 화면을 제공합니다.")
public ModelAndView popup(
@Parameter(description = "단속 연도") @RequestParam String crdnYr,
@Parameter(description = "단속 번호") @RequestParam String crdnNo,
@Parameter(description = "행위 번호") @RequestParam String actInfoId,
Model model) {
log.debug("행위자 선택 팝업 조회 - 단속년도: {}, 단속번호: {}, 행위번호: {}", crdnYr, crdnNo, actInfoId);
ModelAndView mav = new ModelAndView("crdn/crndRegistAndView/crdnActrSelect/crdnActrSelectPopup" + TilesConstants.POPUP);
mav.addObject("crdnYr", crdnYr);
mav.addObject("crdnNo", crdnNo);
mav.addObject("actInfoId", actInfoId);
return mav;
}
/**
* AJAX
* (ApiResponse) .
*
* @param vo VO
* @return ResponseEntity
*/
@Operation(summary = "행위자 목록 조회 (AJAX)", description = "TB_OWNR 테이블에서 행위자 목록을 조회하고 JSON 형식으로 반환합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "행위자 목록 조회 성공"),
@ApiResponse(responseCode = "400", description = "행위자 목록 조회 실패"),
@ApiResponse(description = "오류로 인한 실패")
})
@PostMapping("/list.ajax")
public ResponseEntity<?> listAjax(@ModelAttribute CrdnActrSelectVO vo) {
log.debug("행위자 목록 AJAX 조회 - 검색조건: {}", vo);
// 1. 총 개수 조회
int totalCount = service.selectActrListTotalCount(vo);
// 2. 응답 데이터 구성
//vo.setTotalCount(totalCount);
List<CrdnActrSelectVO> list = service.selectActrList(vo);
return ApiResponseUtil.successWithGrid(list, vo);
}
}

@ -1,23 +0,0 @@
package go.kr.project.crdn.crndRegistAndView.crdnActrSelect.mapper;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.model.CrdnActrSelectVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* MyBatis
* : tb_ownr . .
*/
@Mapper
public interface CrdnActrSelectMapper {
/** 목록 조회 */
List<CrdnActrSelectVO> selectActrList(CrdnActrSelectVO vo);
/** 총 개수 */
int selectActrListTotalCount(CrdnActrSelectVO vo);
/** 상세 조회 */
CrdnActrSelectVO selectActrByPk(String actrId);
}

@ -1,82 +0,0 @@
package go.kr.project.crdn.crndRegistAndView.crdnActrSelect.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import go.kr.project.common.model.PagingVO;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* VO (TB_OWNR )
* : tb_ownr , .
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CrdnActrSelectVO extends PagingVO {
// ============ 테이블 컬럼 ============
private String ownrId; // 행위자 ID
private String sggCd; // 시군구 코드
private String flnm; // 성명
private String rrno; // 주민등록번호
private String ownrSeCd; // 소유자 구분 코드
private String addr; // 주소
private String daddr; // 상세주소
private String lotnoWholAddr; // 지번 전체 주소
private String roadNmWholAddr; // 도로명 전체 주소
private String zip; // 우편번호
private String lotnoAddr; // 지번 주소
private String roadNmAddr; // 도로명 주소
private String refAddr; // 참고 주소
private String pbadmsZoneCd; // 행정 구역 코드
private String roadNmCd; // 도로명 코드
private String lotnoMno; // 지번 본번
private String lotnoSno; // 지번 부번
private String bldgMno; // 건물 본번
private String bldgSno; // 건물 부번
private String udgdYnCd; // 지하 여부 코드
private String rmrk; // 비고
@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; // 등록 일시
private String rgtr; // 등록자
@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 mdfcnDt; // 수정 일시
private String mdfr; // 수정자
private String delYn; // 삭제 여부
@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 delDt; // 삭제 일시
private String dltr; // 삭제자
private String mtnYnCd; // 산 여부 코드
private String telno; // 전화번호
private String eml; // 이메일
// ============ 조인 컬럼(코드명) ============
private String sggCdNm; // 시군구 코드명
private String ownrSeCdNm; // 소유자 구분 코드명
// ============ 조인 컬럼(사용자정보) ============
private String rgtrAcnt; // 등록자 계정
private String rgtrNm; // 등록자명
private String mdfrAcnt; // 수정자 계정
private String mdfrNm; // 수정자명
private String dltrAcnt; // 삭제자 계정
private String dltrNm; // 삭제자명
// ============ 검색 용도 ============
private String crdnYr; // 단속 연도
private String crdnNo; // 단속 번호
private String actInfoId; // 행위 번호
private String actrInfoId; // 행위 번호
}

@ -1,20 +0,0 @@
package go.kr.project.crdn.crndRegistAndView.crdnActrSelect.service;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.model.CrdnActrSelectVO;
import java.util.List;
/**
*
*/
public interface CrdnActrSelectService {
/** 행위자 목록 조회 */
List<CrdnActrSelectVO> selectActrList(CrdnActrSelectVO vo);
/** 행위자 목록 총 개수 조회 */
int selectActrListTotalCount(CrdnActrSelectVO vo);
/** 행위자 상세 조회 */
CrdnActrSelectVO selectActrByPk(String ownrId);
}

@ -1,45 +0,0 @@
package go.kr.project.crdn.crndRegistAndView.crdnActrSelect.service.impl;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.mapper.CrdnActrSelectMapper;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.model.CrdnActrSelectVO;
import go.kr.project.crdn.crndRegistAndView.crdnActrSelect.service.CrdnActrSelectService;
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.ownrSelect.service.impl
* fileName : ActrSelectServiceImpl
* author :
* date : 2025-08-28
* description :
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-08-28
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class CrdnActrSelectSelectServiceImpl extends EgovAbstractServiceImpl implements CrdnActrSelectService {
private final CrdnActrSelectMapper mapper;
@Override
public List<CrdnActrSelectVO> selectActrList(CrdnActrSelectVO vo) {
return mapper.selectActrList(vo);
}
@Override
public int selectActrListTotalCount(CrdnActrSelectVO vo) {
return mapper.selectActrListTotalCount(vo);
}
@Override
public CrdnActrSelectVO selectActrByPk(String ownrId) {
return mapper.selectActrByPk(ownrId);
}
}

@ -44,32 +44,38 @@ public class CrdnOwnrSelectController {
* .
* .
*
* @param popupGubun
* @param crdnYr
* @param crdnNo
* @param actInfoId
* @param model
* @return ModelAndView
*/
@GetMapping("/crdnOwnrSelectPopup.do")
@Operation(summary = "소유자 선택 팝업", description = "소유자 선택을 위한 팝업 화면을 제공합니다.")
public ModelAndView popup(
@Parameter(description = "팝업 구분") @RequestParam String popupGubun,
@Parameter(description = "단속 연도") @RequestParam String crdnYr,
@Parameter(description = "단속 번호") @RequestParam String crdnNo,
@Parameter(description = "위치 정보") @RequestParam String pstnInfoId,
@Parameter(description = "위치 정보") @RequestParam(required = false) String pstnInfoId,
@Parameter(description = "불법행위 정보") @RequestParam(required = false) String actInfoId,
Model model) {
log.debug("소유자 선택 팝업 조회 - 단속년도: {}, 단속번호: {}", crdnYr, crdnNo);
ModelAndView mav = new ModelAndView("crdn/crndRegistAndView/crdnOwnrSelect/crdnOwnrSelectPopup" + TilesConstants.POPUP);
mav.addObject("popupGubun", popupGubun);
mav.addObject("crdnYr", crdnYr);
mav.addObject("crdnNo", crdnNo);
mav.addObject("pstnInfoId", pstnInfoId);
mav.addObject("actInfoId", actInfoId);
return mav;
}
/**
* AJAX
* (ApiResponse) .
*
*
* @param vo VO
* @return ResponseEntity
*/
@ -86,7 +92,7 @@ public class CrdnOwnrSelectController {
// 1. 총 개수 조회
int totalCount = service.selectOwnrListTotalCount(vo);
// 2. 응답 데이터 구성
//vo.setTotalCount(totalCount);
vo.setTotalCount(totalCount);
List<CrdnOwnrSelectVO> list = service.selectOwnrList(vo);
return ApiResponseUtil.successWithGrid(list, vo);

@ -17,7 +17,10 @@ import java.time.LocalDateTime;
@AllArgsConstructor
@NoArgsConstructor
public class CrdnOwnrSelectVO extends PagingVO {
// ============ 팝업 구분 ============
private String popupGubun;
// ============ 테이블 컬럼 ============
private String ownrId; // 소유자 ID
private String sggCd; // 시군구 코드
@ -78,4 +81,6 @@ public class CrdnOwnrSelectVO extends PagingVO {
private String crdnYr; // 단속 연도
private String crdnNo; // 단속 번호
private String pstnInfoId; // 위치 정보 ID
private String actInfoId; // 행위 번호
private String actrInfoId; // 행위 번호
}

@ -1,162 +0,0 @@
<?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.crdnActrSelect.mapper.CrdnActrSelectMapper">
<!-- 행위자 목록 조회 -->
<select id="selectActrList" parameterType="CrdnActrSelectVO"
resultType="CrdnActrSelectVO">
/* ActrSelectMapper.selectActrList : 행위자 목록 조회 */
SELECT
o.OWNR_ID,
o.SGG_CD,
sgg.CD_NM AS SGG_CD_NM,
o.FLNM,
o.RRNO,
o.OWNR_SE_CD,
ownrSe.CD_NM AS OWNR_SE_CD_NM,
o.ADDR,
o.DADDR,
o.LOTNO_WHOL_ADDR,
o.ROAD_NM_WHOL_ADDR,
o.ZIP,
o.LOTNO_ADDR,
o.ROAD_NM_ADDR,
o.REF_ADDR,
o.PBADMS_ZONE_CD,
o.ROAD_NM_CD,
o.LOTNO_MNO,
o.LOTNO_SNO,
o.BLDG_MNO,
o.BLDG_SNO,
o.UDGD_YN_CD,
o.RMRK,
o.REG_DT,
o.RGTR,
regUser.USER_ACNT AS RGTR_ACNT,
regUser.USER_NM AS RGTR_NM,
o.MDFCN_DT,
o.MDFR,
modUser.USER_ACNT AS MDFR_ACNT,
modUser.USER_NM AS MDFR_NM,
o.DEL_YN,
o.DEL_DT,
o.DLTR,
delUser.USER_ACNT AS DLTR_ACNT,
delUser.USER_NM AS DLTR_NM,
o.MTN_YN_CD,
o.TELNO,
o.EML
FROM tb_ownr o
LEFT JOIN tb_cd_detail sgg ON sgg.CD_GROUP_ID = 'ORG_CD' AND sgg.CD_ID = o.SGG_CD
LEFT JOIN tb_cd_detail ownrSe ON ownrSe.CD_GROUP_ID = 'OWNR_SE_CD' AND ownrSe.CD_ID = o.OWNR_SE_CD
LEFT JOIN tb_user regUser ON regUser.USER_ID = o.RGTR
LEFT JOIN tb_user modUser ON modUser.USER_ID = o.MDFR
LEFT JOIN tb_user delUser ON delUser.USER_ID = o.DLTR
WHERE NOT EXISTS (SELECT 1 FROM tb_actr_info oi WHERE oi.OWNR_ID = o.OWNR_ID AND oi.DEL_YN = 'N' AND oi.CRDN_NO = #{crdnNo} AND oi.CRDN_YR = #{crdnYr} AND oi.ACT_INFO_ID = #{actInfoId} )
AND o.DEL_YN = 'N'
<if test='flnm != null and flnm != ""'>
AND o.FLNM LIKE CONCAT('%', #{flnm}, '%')
</if>
<if test='rrno != null and rrno != ""'>
AND o.RRNO LIKE CONCAT('%', #{rrno}, '%')
</if>
<if test='telno != null and telno != ""'>
AND o.TELNO LIKE CONCAT('%', #{telno}, '%')
</if>
<if test='eml != null and eml != ""'>
AND o.EML LIKE CONCAT('%', #{eml}, '%')
</if>
<if test='sggCd != null and sggCd != ""'>
AND o.SGG_CD = #{sggCd}
</if>
<if test='ownrSeCd != null and ownrSeCd != ""'>
AND o.OWNR_SE_CD = #{ownrSeCd}
</if>
ORDER BY o.REG_DT DESC, o.OWNR_ID DESC
<if test='pagingYn != null and pagingYn == "Y"'>
limit #{startIndex}, #{perPage} /* 서버사이드 페이징 처리 */
</if>
</select>
<!-- 행위자 총 개수 조회 -->
<select id="selectActrListTotalCount" parameterType="CrdnActrSelectVO" resultType="int">
/* ActrSelectMapper.selectActrListTotalCount : 행위자 총 개수 조회 */
SELECT COUNT(*)
FROM tb_ownr o
WHERE NOT EXISTS (SELECT 1 FROM tb_actr_info oi WHERE oi.OWNR_ID = o.OWNR_ID AND oi.DEL_YN = 'N' AND oi.CRDN_NO = #{crdnNo} AND oi.CRDN_YR = #{crdnYr} AND oi.ACT_INFO_ID = #{actInfoId} )
AND o.DEL_YN = 'N'
<if test='flnm != null and flnm != ""'>
AND o.FLNM LIKE CONCAT('%', #{flnm}, '%')
</if>
<if test='rrno != null and rrno != ""'>
AND o.RRNO LIKE CONCAT('%', #{rrno}, '%')
</if>
<if test='telno != null and telno != ""'>
AND o.TELNO LIKE CONCAT('%', #{telno}, '%')
</if>
<if test='eml != null and eml != ""'>
AND o.EML LIKE CONCAT('%', #{eml}, '%')
</if>
<if test='sggCd != null and sggCd != ""'>
AND o.SGG_CD = #{sggCd}
</if>
<if test='ownrSeCd != null and ownrSeCd != ""'>
AND o.OWNR_SE_CD = #{ownrSeCd}
</if>
</select>
<!-- 행위자 상세 조회 -->
<select id="selectActrByPk" parameterType="String" resultType="CrdnActrSelectVO">
/* ActrSelectMapper.selectActrByPk : 행위자 상세 조회 */
SELECT
o.OWNR_ID,
o.SGG_CD,
sgg.CD_NM AS SGG_CD_NM,
o.FLNM,
o.RRNO,
o.OWNR_SE_CD,
ownrSe.CD_NM AS OWNR_SE_CD_NM,
o.ADDR,
o.DADDR,
o.LOTNO_WHOL_ADDR,
o.ROAD_NM_WHOL_ADDR,
o.ZIP,
o.LOTNO_ADDR,
o.ROAD_NM_ADDR,
o.REF_ADDR,
o.PBADMS_ZONE_CD,
o.ROAD_NM_CD,
o.LOTNO_MNO,
o.LOTNO_SNO,
o.BLDG_MNO,
o.BLDG_SNO,
o.UDGD_YN_CD,
o.RMRK,
o.REG_DT,
o.RGTR,
regUser.USER_ACNT AS RGTR_ACNT,
regUser.USER_NM AS RGTR_NM,
o.MDFCN_DT,
o.MDFR,
modUser.USER_ACNT AS MDFR_ACNT,
modUser.USER_NM AS MDFR_NM,
o.DEL_YN,
o.DEL_DT,
o.DLTR,
delUser.USER_ACNT AS DLTR_ACNT,
delUser.USER_NM AS DLTR_NM,
o.MTN_YN_CD,
o.TELNO,
o.EML
FROM tb_ownr o
LEFT JOIN tb_cd_detail sgg ON sgg.CD_GROUP_ID = 'ORG_CD' AND sgg.CD_ID = o.SGG_CD
LEFT JOIN tb_cd_detail ownrSe ON ownrSe.CD_GROUP_ID = 'OWNR_SE_CD' AND ownrSe.CD_ID = o.OWNR_SE_CD
LEFT JOIN tb_user regUser ON regUser.USER_ID = o.RGTR
LEFT JOIN tb_user modUser ON modUser.USER_ID = o.MDFR
LEFT JOIN tb_user delUser ON delUser.USER_ID = o.DLTR
WHERE o.OWNR_ID = #{ownrId}
AND o.DEL_YN = 'N'
</select>
</mapper>

@ -5,7 +5,7 @@
<!-- 소유자 목록 조회 -->
<select id="selectOwnrList" parameterType="CrdnOwnrSelectVO"
resultType="CrdnActrSelectVO">
resultType="CrdnOwnrSelectVO">
/* OwnrSelectMapper.selectOwnrList : 소유자 목록 조회 */
SELECT
o.OWNR_ID,
@ -53,7 +53,26 @@
LEFT JOIN tb_user regUser ON regUser.USER_ID = o.RGTR
LEFT JOIN tb_user modUser ON modUser.USER_ID = o.MDFR
LEFT JOIN tb_user delUser ON delUser.USER_ID = o.DLTR
WHERE NOT EXISTS (SELECT 1 FROM tb_ownr_info oi WHERE oi.OWNR_ID = o.OWNR_ID AND oi.DEL_YN = 'N' AND oi.CRDN_NO = #{crdnNo} AND oi.CRDN_YR = #{crdnYr} AND oi.PSTN_INFO_ID = #{pstnInfoId} )
<if test='popupGubun != null and popupGubun == "ownr"'>
WHERE NOT EXISTS
( SELECT 1 FROM tb_ownr_info oi
WHERE oi.OWNR_ID = o.OWNR_ID
AND oi.DEL_YN = 'N'
AND oi.CRDN_NO = #{crdnNo}
AND oi.CRDN_YR = #{crdnYr}
AND oi.PSTN_INFO_ID = #{pstnInfoId}
)
</if>
<if test='popupGubun != null and popupGubun == "actr"'>
WHERE NOT EXISTS
( SELECT 1 FROM tb_actr_info oi
WHERE oi.OWNR_ID = o.OWNR_ID
AND oi.DEL_YN = 'N'
AND oi.CRDN_NO = #{crdnNo}
AND oi.CRDN_YR = #{crdnYr}
AND oi.ACT_INFO_ID = #{actInfoId}
)
</if>
AND o.DEL_YN = 'N'
<if test='flnm != null and flnm != ""'>
AND o.FLNM LIKE CONCAT('%', #{flnm}, '%')
@ -80,11 +99,30 @@
</select>
<!-- 소유자 총 개수 조회 -->
<select id="selectOwnrListTotalCount" parameterType="CrdnActrSelectVO" resultType="int">
<select id="selectOwnrListTotalCount" parameterType="CrdnOwnrSelectVO" resultType="int">
/* OwnrSelectMapper.selectOwnrListTotalCount : 소유자 총 개수 조회 */
SELECT COUNT(*)
FROM tb_ownr o
WHERE NOT EXISTS (SELECT 1 FROM tb_ownr_info oi WHERE oi.OWNR_ID = o.OWNR_ID AND oi.DEL_YN = 'N' AND oi.CRDN_NO = #{crdnNo} AND oi.CRDN_YR = #{crdnYr} AND oi.PSTN_INFO_ID = #{pstnInfoId} )
<if test='popupGubun != null and popupGubun == "ownr"'>
WHERE NOT EXISTS
( SELECT 1 FROM tb_ownr_info oi
WHERE oi.OWNR_ID = o.OWNR_ID
AND oi.DEL_YN = 'N'
AND oi.CRDN_NO = #{crdnNo}
AND oi.CRDN_YR = #{crdnYr}
AND oi.PSTN_INFO_ID = #{pstnInfoId}
)
</if>
<if test='popupGubun != null and popupGubun == "actr"'>
WHERE NOT EXISTS
( SELECT 1 FROM tb_actr_info oi
WHERE oi.OWNR_ID = o.OWNR_ID
AND oi.DEL_YN = 'N'
AND oi.CRDN_NO = #{crdnNo}
AND oi.CRDN_YR = #{crdnYr}
AND oi.ACT_INFO_ID = #{actInfoId}
)
</if>
AND o.DEL_YN = 'N'
<if test='flnm != null and flnm != ""'>
AND o.FLNM LIKE CONCAT('%', #{flnm}, '%')
@ -107,7 +145,7 @@
</select>
<!-- 소유자 상세 조회 -->
<select id="selectOwnrByPk" parameterType="String" resultType="CrdnActrSelectVO">
<select id="selectOwnrByPk" parameterType="String" resultType="CrdnOwnrSelectVO">
/* OwnrSelectMapper.selectOwnrByPk : 소유자 상세 조회 */
SELECT
o.OWNR_ID,

@ -1,369 +0,0 @@
<%@ 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" %>
<div class="popup_wrap">
<div class="popup_inner">
<div class="popup_tit">
<h2 class="tit">행위자 선택</h2>
<a href="#" class="pop-x-btn modalclose" id="btnCloseTop"></a>
</div>
<!-- 중요로직: 단속 정보 파라미터를 hidden input으로 관리 -->
<input type="hidden" id="crdnYr" name="crdnYr" value="${crdnYr}" />
<input type="hidden" id="crdnNo" name="crdnNo" value="${crdnNo}" />
<input type="hidden" id="actInfoId" name="actInfoId" value="${actInfoId}" />
<div class="popup_con">
<!-- 검색 영역 -->
<div class="box_column">
<div class="containers">
<div class="forms_table_non">
<form id="searchForm" name="searchForm">
<table>
<tr>
<th class="th">성명</th>
<td>
<input type="text" id="searchFlnm" name="searchFlnm" class="input" maxlength="100" placeholder="성명을 입력하세요"/>
</td>
<th class="th">주민등록번호</th>
<td>
<input type="text" id="searchRrno" name="searchRrno" class="input" maxlength="100" placeholder="주민등록번호를 입력하세요"/>
</td>
<td style="text-align: right; border: 0px;">
<button type="button" id="searchBtn" class="newbtn bg1">검색</button>
<button type="button" id="resetBtn" class="newbtn bg5" style="margin-left: 5px;">초기화</button>
</td>
</tr>
<tr>
<th class="th">이메일</th>
<td>
<input type="text" id="searchEml" name="searchEml" class="input" maxlength="50" placeholder="이메일을 입력하세요"/>
</td>
<th class="th">전화번호</th>
<td>
<input type="text" id="searchTelno" name="searchTelno" class="input" maxlength="11" placeholder="전화번호를 입력하세요"/>
</td>
<td style="text-align: right; border: 0px;"></td>
</tr>
</table>
</form>
</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="actrSelectGrid"></div>
</div>
</div>
</div>
<div class="popup_foot">
<button type="button" id="selectBtn" class="newbtns bg1">선택</button>
<button type="button" id="closeBtn" class="newbtns bg2">닫기</button>
</div>
</div>
</div>
<script type="text/javascript">
(function(window, $) {
'use strict';
/**
* 행위자 선택 팝업 관리 네임스페이스
*/
var CrdnActrSelectPopup = {
/**
* 그리드 관련 객체
*/
grid: {
/**
* 그리드 인스턴스
*/
instance: null,
/**
* 그리드 설정 초기화
* @returns {Object} 그리드 설정 객체
*/
initConfig: function() {
// 데이터 소스 설정
var dataSource = this.createDataSource();
// 그리드 설정 객체 생성
var gridConfig = new XitTuiGridConfig();
// 기본 설정
gridConfig.setOptDataSource(dataSource); // 데이터소스 연결
gridConfig.setOptGridId('actrSelectGrid'); // 그리드를 출력할 Element ID
gridConfig.setOptGridHeight(350); // 그리드 높이(단위: px)
gridConfig.setOptRowHeight(30); // 그리드 행 높이(단위: px)
gridConfig.setOptRowHeaderType('checkbox'); // 행 첫번째 셀 타입(checkbox: 체크박스)
gridConfig.setOptUseClientSort(true); // 클라이언트 사이드 정렬
gridConfig.setOptColumns(this.getGridColumns());
return gridConfig;
},
/**
* 그리드 컬럼 정의
* @returns {Array} 그리드 컬럼 배열
*/
getGridColumns: function() {
return [
{
header: '번호',
name: '_rowNum',
align: 'center',
width: 60,
sortable: false,
formatter: function(e) {
return XitReverseRowNumberRenderer.format(CrdnActrSelectPopup.grid.instance.getData().length, e);
}
},
{ header: '행위자ID', name: 'ownrId', align: 'center', width: 100, hidden: true },
{ header: '성명', name: 'flnm', align: 'center', width: 120, sortable: true },
{ header: '주민등록번호', name: 'rrno', align: 'center', width: 150 },
{ header: '행위자구분', name: 'ownrSeCdNm', align: 'center', width: 100 },
{ header: '전화번호', name: 'telno', align: 'center', width: 120 },
{ header: '이메일', name: 'eml', align: 'left', width: 200 },
{ header: '주소', name: 'addr', align: 'left', width: 200 },
{ header: '상세주소', name: 'daddr', align: 'left', width: 200 },
{ header: '지번전체주소', name: 'lotnoWholAddr', align: 'left', width: 300 },
{ header: '도로명전체주소', name: 'roadNmWholAddr', align: 'left', width: 300 },
{ header: '우편번호', name: 'zip', align: 'center', width: 80 },
{ header: '비고', name: 'rmrk', align: 'left', width: 200 },
{ header: '등록일시', name: 'regDt', align: 'center', width: 150}
];
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 설정 객체
*/
createDataSource: function() {
return {
api: {
readData: {
url: '<c:url value="/crdn/crndRegistAndView/crdnActrSelect/list.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: true, // 초기 데이터 요청 여부
serializer: function(params) {
// 기본 파라미터 (페이지 정보 등)
var defaultParams = $.param(params);
// 검색 조건 추가
var searchParams = $.param({
flnm: $('#searchFlnm').val() || '',
rrno: $('#searchRrno').val() || '',
telno: $('#searchTelno').val() || '',
eml: $('#searchEml').val() || '',
crdnYr: $('#crdnYr').val() || '',
crdnNo: $('#crdnNo').val() || '',
actInfoId: $('#actInfoId').val() || ''
});
return defaultParams + '&' + searchParams;
}
};
},
/**
* 그리드 인스턴스 생성
*/
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);
if( responseObj ){
var totalCount = responseObj.data.contents.length;
$("#totalCount").text('총 ' + totalCount.toLocaleString() + '건');
}
});
// 행 더블클릭 시 선택
this.instance.on('dblclick', function(ev) {
var rowData = self.instance.getRow(ev.rowKey);
if (rowData) {
CrdnActrSelectPopup.selectActors([rowData]);
}
});
},
/**
* 체크된 행들 가져오기
*/
getCheckedRows: function() {
return this.instance ? this.instance.getCheckedRows() : [];
}
},
/**
* 모듈 초기화
*/
init: function() {
// 그리드 생성
this.grid.create();
this.bindEvents();
},
/**
* 이벤트 바인딩
*/
bindEvents: function() {
var self = this;
// 검색 버튼 클릭 이벤트
$('#searchBtn').on('click', function() {
self.search();
});
// 초기화 버튼 클릭 이벤트
$('#resetBtn').on('click', function() {
$('#searchForm')[0].reset();
self.search();
});
// 선택 버튼 클릭 이벤트
$('#selectBtn').on('click', function() {
var checkedRows = self.grid.getCheckedRows();
if (checkedRows.length === 0) {
alert('선택할 행위자를 체크해주세요.');
return;
}
self.selectActors(checkedRows);
});
// 닫기 버튼 클릭 이벤트
$('#closeBtn, #btnCloseTop').on('click', function(e) {
e.preventDefault();
window.close();
});
// Enter 키로 검색
$('#searchForm input').on('keypress', function(e) {
if (e.which === 13) {
e.preventDefault();
$('#searchBtn').click();
}
});
},
/**
* 검색 함수
*/
search: function() {
if (this.grid.instance) {
this.grid.instance.readData();
}
},
// 중요로직: 선택된 행위자들을 TB_ACTR_INFO에 일괄 저장
selectActors: function(selectedActors) {
if (!selectedActors || selectedActors.length === 0) {
alert('선택할 행위자가 없습니다.');
return;
}
var self = this;
var crdnYr = $('#crdnYr').val();
var crdnNo = $('#crdnNo').val();
var actInfoId = $('#actInfoId').val();
if (!crdnYr || !crdnNo || !actInfoId) {
alert('단속 기본정보가 없습니다.');
return;
}
var actorList = selectedActors.map(function(actor) {
return {
crdnYr: crdnYr,
crdnNo: crdnNo,
actInfoId: actInfoId,
ownrId: actor.ownrId // 행위자 ID (ownrId로 되어있음)
};
});
$.ajax({
url: '<c:url value="/crdn/crndRegistAndView/crdnActrInfo/saveSelectedActrList.ajax"/>',
type: 'POST',
data: JSON.stringify(actorList),
contentType: 'application/json; charset=utf-8',
success: function(response) {
if (response && response.success) {
self.showSaveResult(actorList.length);
} else {
alert(response.message || '행위자 정보 저장에 실패했습니다.');
}
},
error: function(xhr, status, error) {
console.error('행위자 저장 오류:', error);
var errorMessage = '행위자 저장 중 오류가 발생했습니다.';
if(xhr.responseJSON && xhr.responseJSON.message){
errorMessage = xhr.responseJSON.message;
}
alert(errorMessage);
}
});
},
// 중요로직: 저장 결과 표시 및 부모창 새로고침
showSaveResult: function(saveCount) {
var message = '';
if (saveCount > 0) {
message += saveCount + '건의 행위자 정보가 저장되었습니다.\n';
}
if (message) {
alert(message.trim());
}
if (saveCount > 0) {
if (window.opener && window.opener.CrdnDetailViewActrInfo && window.opener.CrdnDetailViewActrInfo.search) {
window.opener.CrdnDetailViewActrInfo.search();
}
}
window.close();
},
// 체크된 행들 가져오기
getCheckedRows: function() {
return this.instance ? this.instance.getCheckedRows() : [];
}
};
// DOM 준비 완료 시 초기화
$(document).ready(function() {
// 중요로직: 행위자 선택 그리드 초기화
CrdnActrSelectPopup.init();
});
// 전역 네임스페이스에 모듈 노출
window.CrdnActrSelectPopup = CrdnActrSelectPopup;
})(window, jQuery);
</script>

@ -3,16 +3,20 @@
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="popupGubunName" value="${popupGubun eq 'ownr' ? '소유자':'행위자'}"/>
<div class="popup_wrap">
<div class="popup_inner">
<div class="popup_tit">
<h2 class="tit">소유자 선택</h2>
<h2 class="tit">${popupGubunName} 선택</h2>
<a href="#" class="pop-x-btn modalclose" id="btnCloseTop"></a>
</div>
<!-- 중요로직: 단속 정보 파라미터를 hidden input으로 관리 -->
<input type="hidden" id="popupGubun" name="popupGubun" value="${popupGubun}" />
<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="${pstnInfoId}" />
<input type="hidden" id="actInfoId" name="actInfoId" value="${actInfoId}" />
<div class="popup_con">
<!-- 검색 영역 -->
<div class="box_column">
@ -128,7 +132,7 @@
{ header: '소유자ID', name: 'ownrId', align: 'center', width: 100, hidden: true },
{ header: '성명', name: 'flnm', align: 'center', width: 120, sortable: true },
{ header: '주민등록번호', name: 'rrno', align: 'center', width: 150 },
{ header: '소유자구분', name: 'ownrSeCdNm', align: 'center', width: 100 },
{ header: '구분', name: 'ownrSeCdNm', align: 'center', width: 100 },
{ header: '전화번호', name: 'telno', align: 'center', width: 120 },
{ header: '이메일', name: 'eml', align: 'left', width: 200 },
{ header: '주소', name: 'addr', align: 'left', width: 200 },
@ -167,7 +171,9 @@
eml: $('#searchEml').val() || '',
crdnYr: $('#crdnYr').val() || '',
crdnNo: $('#crdnNo').val() || '',
pstnInfoId: $('#pstnInfoId').val() || ''
pstnInfoId: $('#pstnInfoId').val() || '',
actInfoId: $('#actInfoId').val() || '',
popupGubun: '${popupGubun}' || ''
});
return defaultParams + '&' + searchParams;
}
@ -250,7 +256,7 @@
$('#selectBtn').on('click', function() {
var checkedRows = self.grid.getCheckedRows();
if (checkedRows.length === 0) {
alert('선택할 소유자를 체크해주세요.');
alert('선택할 ${popupGubunName}를 체크해주세요.');
return;
}
self.selectOwners(checkedRows);
@ -283,7 +289,7 @@
// 중요로직: 선택된 소유자들을 TB_OWNR_INFO에 일괄 저장
selectOwners: function(selectedOwners) {
if (!selectedOwners || selectedOwners.length === 0) {
alert('선택할 소유자가 없습니다.');
alert('선택할 ${popupGubunName}가 없습니다.');
return;
}
@ -291,23 +297,36 @@
var crdnYr = $('#crdnYr').val();
var crdnNo = $('#crdnNo').val();
var pstnInfoId = $('#pstnInfoId').val();
var actInfoId = $('#actInfoId').val();
<c:if test = "${popupGubun eq 'ownr'}">
if (!crdnYr || !crdnNo || !pstnInfoId) {
alert('단속 기본정보가 없습니다.');
return;
}
</c:if>
<c:if test = "${popupGubun eq 'actr'}">
if (!crdnYr || !crdnNo || !actInfoId) {
alert('단속 기본정보가 없습니다.');
return;
}
</c:if>
var ownerList = selectedOwners.map(function(owner) {
return {
crdnYr: crdnYr,
crdnNo: crdnNo,
pstnInfoId: pstnInfoId,
actInfoId: actInfoId,
ownrId: owner.ownrId
};
});
var url = '${popupGubun}' === 'ownr' ?
'<c:url value="/crdn/crndRegistAndView/crdnOwnrInfo/saveSelectedOwnrList.ajax"/>'
: '<c:url value="/crdn/crndRegistAndView/crdnActrInfo/saveSelectedActrList.ajax"/>';
$.ajax({
url: '<c:url value="/crdn/crndRegistAndView/crdnOwnrInfo/saveSelectedOwnrList.ajax"/>',
url: url,
type: 'POST',
data: JSON.stringify(ownerList),
contentType: 'application/json; charset=utf-8',
@ -315,12 +334,12 @@
if (response && response.success) {
self.showSaveResult(ownerList.length, 0, 0, []);
} else {
alert(response.message || '소유자 정보 저장에 실패했습니다.');
alert(response.message || '${popupGubunName} 정보 저장에 실패했습니다.');
}
},
error: function(xhr, status, error) {
console.error('소유자 저장 오류:', error);
var errorMessage = '소유자 저장 중 오류가 발생했습니다.';
console.error('${popupGubunName} 저장 오류:', error);
var errorMessage = '${popupGubunName} 저장 중 오류가 발생했습니다.';
if(xhr.responseJSON && xhr.responseJSON.message){
errorMessage = xhr.responseJSON.message;
}
@ -334,7 +353,7 @@
var message = '';
if (saveCount > 0) {
message += saveCount + '건의 소유자 정보가 저장되었습니다.\n';
message += saveCount + '건의 ${popupGubunName} 정보가 저장되었습니다.\n';
}
if (message) {
@ -343,8 +362,14 @@
// 중요로직: 저장 성공 시 부모창 소유자 정보 그리드 새로고침
if (saveCount > 0) {
if (window.opener && window.opener.CrdnDetailViewOwnrInfo && window.opener.CrdnDetailViewOwnrInfo.search) {
window.opener.CrdnDetailViewOwnrInfo.search();
if( '${popupGubun}' === 'ownr' ){
if (window.opener && window.opener.CrdnDetailViewOwnrInfo && window.opener.CrdnDetailViewOwnrInfo.search) {
window.opener.CrdnDetailViewOwnrInfo.search();
}
} else if( '${popupGubun}' === 'actr' ){
if (window.opener && window.opener.CrdnDetailViewActrInfo && window.opener.CrdnDetailViewActrInfo.search) {
window.opener.CrdnDetailViewActrInfo.search();
}
}
}

@ -175,8 +175,9 @@
return;
}
var url = '<c:url value="/crdn/crndRegistAndView/crdnActrSelect/crdnActrSelectPopup.do"/>' +
'?crdnYr=' + encodeURIComponent(crdnYr) +
var url = '<c:url value="/crdn/crndRegistAndView/crdnOwnrSelect/crdnOwnrSelectPopup.do"/>' +
'?popupGubun=' + encodeURIComponent("actr") +
'&crdnYr=' + encodeURIComponent(crdnYr) +
'&crdnNo=' + encodeURIComponent(crdnNo) +
'&actInfoId=' + encodeURIComponent(actInfoId || '');
var w = 1000, h = 800;

@ -175,7 +175,8 @@
}
var url = '<c:url value="/crdn/crndRegistAndView/crdnOwnrSelect/crdnOwnrSelectPopup.do"/>' +
'?crdnYr=' + encodeURIComponent(crdnYr) +
'?popupGubun=' + encodeURIComponent("ownr") +
'&crdnYr=' + encodeURIComponent(crdnYr) +
'&crdnNo=' + encodeURIComponent(crdnNo) +
'&pstnInfoId=' + encodeURIComponent(pstnInfoId || '');
var w = 1000, h = 800;

@ -351,7 +351,6 @@
*/
refreshOtherGridsAfterLocation2: function() {
// 행위자 정보 그리드 로딩
console.log('refreshOtherGridsAfterLocation2', window.CrdnDetailView.actInfoId);
if (this.grids.actrInfo && this.grids.actrInfo.search) {
this.grids.actrInfo.search();
}

Loading…
Cancel
Save