diff --git a/bin/main/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml b/bin/main/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml new file mode 100644 index 0000000..077b11a --- /dev/null +++ b/bin/main/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + INSERT INTO tb_act_type ( + ACT_TYPE_CD /* 행위 유형 코드 */ + , VLTN_BDST /* 위반 건축물 */ + , LAWLPRVS /* 법조문 */ + , CMPTTN_RT /* 산정률 */ + , VLTN_BDST_DTL /* 위반 건축물 상세 */ + , USE_YN /* 사용 여부 */ + , REG_DT /* 등록 일시 */ + , RGTR /* 등록자 */ + ) VALUES ( + #{actTypeCd} /* 행위 유형 코드 */ + , #{vltnBdst} /* 위반 건축물 */ + , #{lawlprvs} /* 법조문 */ + , #{cmpttnRt} /* 산정률 */ + , #{vltnBdstDtl} /* 위반 건축물 상세 */ + , #{useYn} /* 사용 여부 */ + , NOW() /* 등록 일시 - 현재 날짜 자동 설정 */ + , #{rgtr} /* 등록자 - 세션 사용자 ID */ + ) + + + + + UPDATE tb_act_type + SET VLTN_BDST = #{vltnBdst} /* 위반 건축물 */ + , LAWLPRVS = #{lawlprvs} /* 법조문 */ + , CMPTTN_RT = #{cmpttnRt} /* 산정률 */ + , VLTN_BDST_DTL = #{vltnBdstDtl} /* 위반 건축물 상세 */ + , USE_YN = #{useYn} /* 사용 여부 */ + , MDFCN_DT = NOW() /* 수정 일시 */ + , MDFR = #{mdfr} /* 수정자 */ + WHERE ACT_TYPE_CD = #{actTypeCd} /* 행위 유형 코드 */ + + + + + diff --git a/bin/main/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml b/bin/main/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml new file mode 100644 index 0000000..a263cc8 --- /dev/null +++ b/bin/main/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + INSERT INTO tb_cmpttn_rt_2 ( + CMPTTN_RT_2_CD /* 산정률2 코드 */ + , VLTN_MTTR /* 위반 사항 */ + , CMPTTN_RT_2 /* 산정률2 */ + , USE_YN /* 사용 여부 */ + , REG_DT /* 등록 일시 */ + , RGTR /* 등록자 */ + ) VALUES ( + #{cmpttnRt2Cd} /* 산정률2 코드 */ + , #{vltnMttr} /* 위반 사항 */ + , #{cmpttnRt2} /* 산정률2 */ + , #{useYn} /* 사용 여부 */ + , NOW() /* 등록 일시 - 현재 날짜 자동 설정 */ + , #{rgtr} /* 등록자 - 세션 사용자 ID */ + ) + + + + + UPDATE tb_cmpttn_rt_2 + SET VLTN_MTTR = #{vltnMttr} /* 위반 사항 */ + , CMPTTN_RT_2 = #{cmpttnRt2} /* 산정률2 */ + , USE_YN = #{useYn} /* 사용 여부 */ + , MDFCN_DT = NOW() /* 수정 일시 */ + , MDFR = #{mdfr} /* 수정자 */ + WHERE CMPTTN_RT_2_CD = #{cmpttnRt2Cd} /* 산정률2 코드 */ + + + + + diff --git a/src/main/java/go/kr/project/baseData/actType/controller/ActTypeController.java b/src/main/java/go/kr/project/baseData/actType/controller/ActTypeController.java new file mode 100644 index 0000000..b7021ff --- /dev/null +++ b/src/main/java/go/kr/project/baseData/actType/controller/ActTypeController.java @@ -0,0 +1,167 @@ +package go.kr.project.baseData.actType.controller; + +import egovframework.constant.MessageConstants; +import egovframework.constant.TilesConstants; +import egovframework.exception.MessageException; +import egovframework.util.ApiResponseUtil; +import egovframework.util.SessionUtil; +import go.kr.project.baseData.actType.model.ActTypeVO; +import go.kr.project.baseData.actType.service.ActTypeService; +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; + +/** + * packageName : go.kr.project.baseData.actType.controller + * fileName : ActTypeController + * author : 김의진 + * date : 2025-09-22 + * description : 기준자료 > 행위 유형 웹 컨트롤러 + * 중요 로직 주석: + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +@Controller +@RequestMapping("/baseData/actType") +@RequiredArgsConstructor +@Slf4j +@Tag(name = "기준자료: 행위 유형", description = "행위 유형 관리 API") +public class ActTypeController { + + /** 행위 유형 서비스 */ + private final ActTypeService service; + + /** + * 행위 유형 목록 페이지를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @param model 뷰에 전달할 데이터를 담는 모델 객체 + * @return 목록 페이지 뷰 이름 + */ + @GetMapping("/list.do") + @Operation(summary = "행위 유형 목록 페이지", description = "목록 페이지를 조회합니다.") + public String listPage(ActTypeVO vo, Model model){ + log.debug("행위 유형 목록 페이지 조회"); + return "baseData/actType/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 ActTypeVO 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); + } + + /** + * 행위 유형 등록/수정/조회 팝업 페이지를 조회한다. + * mode 파라미터에 따라 등록(C), 수정(U), 조회(V) 모드로 동작한다. + * @param vo PK 정보를 담은 VO 객체 + * @param mode 화면 모드 (C: 등록, U: 수정, V: 조회) + * @param model 뷰에 전달할 데이터를 담는 모델 객체 + * @return 팝업 페이지 뷰 이름 + */ + @GetMapping("/popup.do") + @Operation(summary = "등록/수정/조회 팝업", description = "window.open으로 호출되는 팝업, mode 파라미터로 C/U/V 구분") + public ModelAndView popup( + @Parameter(description = "행위 유형 코드") @RequestParam(required = false) String actTypeCd, + @Parameter(description = "화면 모드 (C:등록, U:수정, V:보기)") @RequestParam String mode, + Model model) { + + try { + log.debug("행위 유형 팝업 화면 요청 - 모드: {}, 구조지수코드: {}", mode, actTypeCd); + + ModelAndView mav = new ModelAndView("baseData/actType/popup" + TilesConstants.POPUP); + mav.addObject("mode", mode); + + // 수정/조회 모드인 경우 기존 데이터 조회 + if (("U".equals(mode) || "V".equals(mode)) && actTypeCd != null) { + ActTypeVO paramVO = new ActTypeVO(); + paramVO.setActTypeCd(actTypeCd); + + ActTypeVO data = service.selectOne(paramVO); + if (data != null) { + mav.addObject("data", data); + } else { + throw new MessageException("해당 행위 유형 정보를 찾을 수 없습니다."); + } + } + + return mav; + + } catch (Exception e) { + log.error("행위 유형 팝업 화면 제공 중 오류 발생", e); + throw new MessageException("팝업 화면을 불러오는 중 오류가 발생했습니다."); + } + } + + /** + * 새로운 행위 유형 정보를 등록한다. + * @param vo 등록할 행위 유형 정보를 담은 VO 객체 + * @return 등록 결과를 담은 ResponseEntity + */ + @Operation(summary = "행위 유형 등록", description = "새로운 행위 유형 정보를 등록합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "행위 유형 등록 성공"), + @ApiResponse(responseCode = "400", description = "행위 유형 등록 실패"), + @ApiResponse(description = "오류로 인한 실패") + }) + @PostMapping("/insert.ajax") + public ResponseEntity insert(@ModelAttribute ActTypeVO paramVO) throws Exception { + // 등록자 정보 설정 + paramVO.setRgtr(SessionUtil.getUserId()); + + int result = service.insert(paramVO); + + if (result > 0) { + return ApiResponseUtil.success(MessageConstants.Common.SAVE_SUCCESS); + } else { + return ApiResponseUtil.error(MessageConstants.Common.SAVE_ERROR); + } + } + + /** + * 기존 행위 유형 정보를 수정한다. + * @param vo 수정할 행위 유형 정보를 담은 VO 객체 + * @return 수정 결과를 담은 ResponseEntity + */ + @Operation(summary = "행위 유형 수정", description = "기존 행위 유형 정보를 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "행위 유형 수정 성공"), + @ApiResponse(responseCode = "400", description = "행위 유형 수정 실패"), + @ApiResponse(description = "오류로 인한 실패") + }) + @PostMapping("/update.ajax") + public ResponseEntity update(@ModelAttribute ActTypeVO paramVO) throws Exception { + // 수정자 정보 설정 + paramVO.setMdfr(SessionUtil.getUserId()); + + int result = service.update(paramVO); + + if (result > 0) { + return ApiResponseUtil.success(MessageConstants.Common.UPDATE_SUCCESS); + } else { + return ApiResponseUtil.error(MessageConstants.Common.UPDATE_ERROR); + } + } + +} diff --git a/src/main/java/go/kr/project/baseData/actType/mapper/ActTypeMapper.java b/src/main/java/go/kr/project/baseData/actType/mapper/ActTypeMapper.java new file mode 100644 index 0000000..e3bd997 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/actType/mapper/ActTypeMapper.java @@ -0,0 +1,71 @@ +package go.kr.project.baseData.actType.mapper; + +import go.kr.project.baseData.actType.model.ActTypeVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * packageName : go.kr.project.baseData.actType.mapper + * fileName : ActTypeMapper + * author : 김의진 + * date : 2025-09-22 + * description : 행위 유형 MyBatis Mapper 인터페이스 + * 중요한 로직 주석: SQL 쿼리와 매핑되는 메서드들을 정의하여 데이터베이스 접근을 담당한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +@Mapper +public interface ActTypeMapper { + + /** + * 행위 유형 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 행위 유형 목록 + */ + List selectList(ActTypeVO vo); + + /** + * 행위 유형 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + int selectListTotalCount(ActTypeVO vo); + + /** + * 특정 코드의 행위 유형 정보를 조회한다. + * @param vo 조회할 PK 정보(yr, no)를 담은 VO 객체 + * @return 조회된 행위 유형 정보 + */ + ActTypeVO selectOne(ActTypeVO vo); + + /** + * 새로운 행위 유형 정보를 등록한다. + * @param vo 등록할 행위 유형 정보를 담은 VO 객체 + * @return 등록된 행의 수 + */ + int insert(ActTypeVO vo); + + /** + * 기존 행위 유형 정보를 수정한다. + * @param vo 수정할 행위 유형 정보를 담은 VO 객체 + * @return 수정된 행의 수 + */ + int update(ActTypeVO vo); + + /** + * 행위 유형 정보를 삭제한다. + * @param vo 삭제할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 삭제된 행의 수 + */ + int delete(ActTypeVO vo); + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + int selectDuplicateCheck(ActTypeVO vo); +} diff --git a/src/main/java/go/kr/project/baseData/actType/model/ActTypeVO.java b/src/main/java/go/kr/project/baseData/actType/model/ActTypeVO.java new file mode 100644 index 0000000..decbab4 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/actType/model/ActTypeVO.java @@ -0,0 +1,86 @@ +package go.kr.project.baseData.actType.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.actType.model + * fileName : ActTypeVO + * author : 김의진 + * date : 2025-09-22 + * description : 행위 유형 관련 데이터를 담는 Value Object 클래스 + * 중요한 로직 주석: 행위 유형 테이블(tb_act_type)과 매핑되는 VO 클래스로 페이징 기능을 포함한다. * + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class ActTypeVO extends PagingVO { + + // ==================== 기본 테이블 컬럼 ==================== + + /** 행위 유형 코드 (PK) - 3자리 코드 */ + private String actTypeCd; + + /** 위반 건축물 */ + private String vltnBdst; + + /** 법조문 */ + private String lawlprvs; + + /** 산정률 - DECIMAL(3,0) */ + private BigDecimal cmpttnRt; + + /** 위반 건축물 상세 */ + private String vltnBdstDtl; + + /** 사용 여부 */ + private String useYn; + + /** 등록 일시 - 테이블은 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; + + /** 수정 일시 */ + @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; + + /** 수정자 ID */ + private String mdfr; + + // ==================== 조인 컬럼 (코드명) ==================== + + /** 등록자 */ + private String rgtrNm; + + /** 수정자 */ + private String mdfrNm; + + /** 행 번호 (그리드 표시용) */ + private Integer rowNum; + + // ==================== 검색 조건 ==================== + + /** 검색 조건 선택 */ + private String schType; + private String schTypeTxt; + + /** 검색 조건 - 사용 여부 */ + private String schUseYn; +} diff --git a/src/main/java/go/kr/project/baseData/actType/service/ActTypeService.java b/src/main/java/go/kr/project/baseData/actType/service/ActTypeService.java new file mode 100644 index 0000000..a7396df --- /dev/null +++ b/src/main/java/go/kr/project/baseData/actType/service/ActTypeService.java @@ -0,0 +1,69 @@ +package go.kr.project.baseData.actType.service; + +import go.kr.project.baseData.actType.model.ActTypeVO; + +import java.util.List; + +/** + * packageName : go.kr.project.baseData.actType.service + * fileName : ActTypeService + * author : 김의진 + * date : 2025-09-22 + * description : 행위 유형 비즈니스 로직 처리를 위한 서비스 인터페이스 + * 중요한 로직 주석: 컨트롤러와 매퍼 사이의 비즈니스 로직을 정의하고 데이터 처리 규칙을 관리한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +public interface ActTypeService { + + /** + * 행위 유형 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 행위 유형 목록 + */ + List selectList(ActTypeVO vo); + + /** + * 행위 유형 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + int selectListTotalCount(ActTypeVO vo); + + /** + * 특정 코드의 행위 유형 정보를 조회한다. + * @param vo 조회할 PK 정보를 담은 VO 객체 + * @return 조회된 행위 유형 정보 + */ + ActTypeVO selectOne(ActTypeVO vo); + + /** + * 새로운 행위 유형 정보를 등록한다. + * @param vo 등록할 행위 유형 정보를 담은 VO 객체 + * @return 등록된 행의 수 + */ + int insert(ActTypeVO vo); + + /** + * 기존 행위 유형 정보를 수정한다. + * @param vo 수정할 행위 유형 정보를 담은 VO 객체 + * @return 수정된 행의 수 + */ + int update(ActTypeVO vo); + + /** + * 행위 유형 정보를 삭제한다. + * @param vo 삭제할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 삭제된 행의 수 + */ + int delete(ActTypeVO vo); + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + int selectDuplicateCheck(ActTypeVO vo); +} diff --git a/src/main/java/go/kr/project/baseData/actType/service/impl/ActTypeServiceImpl.java b/src/main/java/go/kr/project/baseData/actType/service/impl/ActTypeServiceImpl.java new file mode 100644 index 0000000..9843291 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/actType/service/impl/ActTypeServiceImpl.java @@ -0,0 +1,194 @@ +package go.kr.project.baseData.actType.service.impl; + +import egovframework.exception.MessageException; +import egovframework.util.SessionUtil; +import egovframework.util.StringUtil; +import go.kr.project.baseData.actType.mapper.ActTypeMapper; +import go.kr.project.baseData.actType.model.ActTypeVO; +import go.kr.project.baseData.actType.service.ActTypeService; +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.actType.service.impl + * fileName : ActTypeServiceImpl + * author : 김의진 + * date : 2025-09-22 + * description : 행위 유형 비즈니스 로직 처리를 위한 서비스 구현체 + * 중요한 로직 주석: 서비스 인터페이스를 구현하여 실제 비즈니스 로직을 처리하고 매퍼를 호출한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class ActTypeServiceImpl extends EgovAbstractServiceImpl implements ActTypeService { + + /** 행위 유형 매퍼 */ + private final ActTypeMapper mapper; + + /** + * 행위 유형 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 행위 유형 목록 + */ + @Override + public List selectList(ActTypeVO vo) { + log.debug("행위 유형 목록 조회 - 검색조건: {}", vo); + return mapper.selectList(vo); + } + + /** + * 행위 유형 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + @Override + public int selectListTotalCount(ActTypeVO vo) { + log.debug("행위 유형 총 개수 조회 - 검색조건: {}", vo); + return mapper.selectListTotalCount(vo); + } + + /** + * 특정 코드에 해당하는 행위 유형 정보를 조회한다. + * @param vo 조회할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 조회된 행위 유형 정보 + */ + @Override + public ActTypeVO selectOne(ActTypeVO vo) { + log.debug("행위 유형 단건 조회 - 코드: {}", vo.getActTypeCd()); + return mapper.selectOne(vo); + } + + /** + * 새로운 행위 유형 정보를 등록한다. + * PK(코드) 필수값 검증과 중복 체크를 수행한 후 등록을 진행한다. + * @param vo 등록할 행위 유형 정보를 담은 VO 객체 + * @return 등록된 행의 수 + * @throws MessageException PK 필수값 누락 또는 중복 시 발생 + */ + @Override + public int insert(ActTypeVO vo) { + log.debug("행위 유형 등록 - 코드: {}, 위반 건축물: {}", vo.getActTypeCd(), vo.getVltnBdst()); + + // PK(코드) 필수값 검증 + if (vo.getActTypeCd() == null || vo.getActTypeCd().trim().isEmpty()) { + log.warn("행위 유형 등록 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // PK 중복 체크 + int duplicateCount = mapper.selectDuplicateCheck(vo); + if (duplicateCount > 0) { + log.warn("행위 유형 등록 실패 - 중복된 PK: 코드={}", vo.getActTypeCd()); + throw new MessageException("이미 존재하는 행위 유형 코드입니다. 다른 값을 입력해주세요."); + } + + // 위반 건축물 바이트 길이 검증 (한글 3바이트 기준 최대 100바이트) + if (vo.getVltnBdst() != null && !vo.getVltnBdst().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnBdst()); + if (byteLength > 100) { + log.warn("행위 유형 등록 실패 - 위반 건축물 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 건축물은 최대 100바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 위반 건축물 상세 바이트 길이 검증 (한글 3바이트 기준 최대 1000바이트) + if (vo.getVltnBdstDtl() != null && !vo.getVltnBdstDtl().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnBdstDtl()); + if (byteLength > 1000) { + log.warn("행위 유형 등록 실패 - 위반 건축물 상세 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 건축물은 최대 1000바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 등록자 정보 설정 및 등록 수행 + vo.setRgtr(SessionUtil.getUserId()); + int result = mapper.insert(vo); + log.debug("행위 유형 등록 완료 - 등록 건수: {}", result); + return result; + } + + /** + * 기존 행위 유형 정보를 수정한다. + * PK(코드) 필수값 검증을 수행한 후 수정을 진행한다. + * @param vo 수정할 행위 유형 정보를 담은 VO 객체 + * @return 수정된 행의 수 + * @throws MessageException PK 필수값 누락 시 발생 + */ + @Override + public int update(ActTypeVO vo) { + log.debug("행위 유형 수정 - 코드: {}, 위반 건축물: {}", vo.getActTypeCd(), vo.getVltnBdst()); + + // PK(코드) 필수값 검증 + if (vo.getActTypeCd() == null || vo.getActTypeCd().trim().isEmpty()) { + log.warn("행위 유형 등록 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // 위반 건축물 바이트 길이 검증 (한글 3바이트 기준 최대 100바이트) + if (vo.getVltnBdst() != null && !vo.getVltnBdst().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnBdst()); + if (byteLength > 100) { + log.warn("행위 유형 등록 실패 - 위반 건축물 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 건축물은 최대 100바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 위반 건축물 상세 바이트 길이 검증 (한글 3바이트 기준 최대 1000바이트) + if (vo.getVltnBdstDtl() != null && !vo.getVltnBdstDtl().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnBdstDtl()); + if (byteLength > 1000) { + log.warn("행위 유형 등록 실패 - 위반 건축물 상세 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 건축물은 최대 1000바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 수정 수행 + int result = mapper.update(vo); + log.debug("행위 유형 수정 완료 - 수정 건수: {}", result); + return result; + } + + /** + * 행위 유형 정보를 삭제한다. + * PK(코드) 필수값 검증을 수행한 후 삭제를 진행한다. + * @param vo 삭제할 PK 정보(코드)를 담은 VO 객체 + * @return 삭제된 행의 수 + * @throws MessageException PK 필수값 누락 시 발생 + */ + @Override + public int delete(ActTypeVO vo) { + log.debug("행위 유형 삭제 - 코드: {}", vo.getActTypeCd()); + + // PK(코드) 필수값 검증 + if (vo.getActTypeCd() == null || vo.getActTypeCd().trim().isEmpty()) { + log.warn("행위 유형 삭제 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // 삭제 수행 + int result = mapper.delete(vo); + log.debug("행위 유형 삭제 완료 - 삭제 건수: {}", result); + return result; + } + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(actTypeCd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + @Override + public int selectDuplicateCheck(ActTypeVO vo) { + log.debug("행위 유형 중복 체크 - 코드: {}", vo.getActTypeCd()); + return mapper.selectDuplicateCheck(vo); + } + + +} diff --git a/src/main/java/go/kr/project/baseData/cmpttnRt2/controller/CmpttnRt2Controller.java b/src/main/java/go/kr/project/baseData/cmpttnRt2/controller/CmpttnRt2Controller.java new file mode 100644 index 0000000..ee99920 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/cmpttnRt2/controller/CmpttnRt2Controller.java @@ -0,0 +1,167 @@ +package go.kr.project.baseData.cmpttnRt2.controller; + +import egovframework.constant.MessageConstants; +import egovframework.constant.TilesConstants; +import egovframework.exception.MessageException; +import egovframework.util.ApiResponseUtil; +import egovframework.util.SessionUtil; +import go.kr.project.baseData.cmpttnRt2.model.CmpttnRt2VO; +import go.kr.project.baseData.cmpttnRt2.service.CmpttnRt2Service; +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; + +/** + * packageName : go.kr.project.baseData.cmpttnRt2.controller + * fileName : CmpttnRt2Controller + * author : 김의진 + * date : 2025-09-24 + * description : 기준자료 > 산정률2 웹 컨트롤러 + * 중요 로직 주석: + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-24 김의진 최초 생성 + */ +@Controller +@RequestMapping("/baseData/cmpttnRt2") +@RequiredArgsConstructor +@Slf4j +@Tag(name = "기준자료: 산정률2", description = "산정률2 관리 API") +public class CmpttnRt2Controller { + + /** 산정률2 서비스 */ + private final CmpttnRt2Service service; + + /** + * 산정률2 목록 페이지를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @param model 뷰에 전달할 데이터를 담는 모델 객체 + * @return 목록 페이지 뷰 이름 + */ + @GetMapping("/list.do") + @Operation(summary = "산정률2 목록 페이지", description = "목록 페이지를 조회합니다.") + public String listPage(CmpttnRt2VO vo, Model model){ + log.debug("산정률2 목록 페이지 조회"); + return "baseData/cmpttnRt2/list" + TilesConstants.BASE; + } + + /** + * 산정률2 목록을 AJAX로 조회한다. + * 서버사이드 페이징을 지원하며 검색 조건에 따라 필터링된 결과를 반환한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 목록 데이터와 페이징 정보를 담은 ResponseEntity + */ + @PostMapping("/list.ajax") + @Operation(summary = "목록 조회(AJAX)", description = "페이징 목록을 JSON으로 반환") + @ApiResponse(responseCode = "200", description = "성공") + public ResponseEntity listAjax(@ModelAttribute CmpttnRt2VO vo){ + log.debug("산정률2 목록 AJAX 조회 - 검색조건: {}", vo); + int total = service.selectListTotalCount(vo); // 1. 총 개수 조회 + vo.setTotalCount(total); // 2. setTotalCount + //vo.setPagingYn("Y"); // 3. 페이징 처리 + return ApiResponseUtil.successWithGrid(service.selectList(vo), vo); + } + + /** + * 산정률2 등록/수정/조회 팝업 페이지를 조회한다. + * mode 파라미터에 따라 등록(C), 수정(U), 조회(V) 모드로 동작한다. + * @param vo PK 정보를 담은 VO 객체 + * @param mode 화면 모드 (C: 등록, U: 수정, V: 조회) + * @param model 뷰에 전달할 데이터를 담는 모델 객체 + * @return 팝업 페이지 뷰 이름 + */ + @GetMapping("/popup.do") + @Operation(summary = "등록/수정/조회 팝업", description = "window.open으로 호출되는 팝업, mode 파라미터로 C/U/V 구분") + public ModelAndView popup( + @Parameter(description = "산정률2 코드") @RequestParam(required = false) String cmpttnRt2Cd, + @Parameter(description = "화면 모드 (C:등록, U:수정, V:보기)") @RequestParam String mode, + Model model) { + + try { + log.debug("산정률2 팝업 화면 요청 - 모드: {}, 구조지수코드: {}", mode, cmpttnRt2Cd); + + ModelAndView mav = new ModelAndView("baseData/cmpttnRt2/popup" + TilesConstants.POPUP); + mav.addObject("mode", mode); + + // 수정/조회 모드인 경우 기존 데이터 조회 + if (("U".equals(mode) || "V".equals(mode)) && cmpttnRt2Cd != null) { + CmpttnRt2VO paramVO = new CmpttnRt2VO(); + paramVO.setCmpttnRt2Cd(cmpttnRt2Cd); + + CmpttnRt2VO data = service.selectOne(paramVO); + if (data != null) { + mav.addObject("data", data); + } else { + throw new MessageException("해당 산정률2 정보를 찾을 수 없습니다."); + } + } + + return mav; + + } catch (Exception e) { + log.error("산정률2 팝업 화면 제공 중 오류 발생", e); + throw new MessageException("팝업 화면을 불러오는 중 오류가 발생했습니다."); + } + } + + /** + * 새로운 산정률2 정보를 등록한다. + * @param vo 등록할 산정률2 정보를 담은 VO 객체 + * @return 등록 결과를 담은 ResponseEntity + */ + @Operation(summary = "산정률2 등록", description = "새로운 산정률2 정보를 등록합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "산정률2 등록 성공"), + @ApiResponse(responseCode = "400", description = "산정률2 등록 실패"), + @ApiResponse(description = "오류로 인한 실패") + }) + @PostMapping("/insert.ajax") + public ResponseEntity insert(@ModelAttribute CmpttnRt2VO paramVO) throws Exception { + // 등록자 정보 설정 + paramVO.setRgtr(SessionUtil.getUserId()); + + int result = service.insert(paramVO); + + if (result > 0) { + return ApiResponseUtil.success(MessageConstants.Common.SAVE_SUCCESS); + } else { + return ApiResponseUtil.error(MessageConstants.Common.SAVE_ERROR); + } + } + + /** + * 기존 산정률2 정보를 수정한다. + * @param vo 수정할 산정률2 정보를 담은 VO 객체 + * @return 수정 결과를 담은 ResponseEntity + */ + @Operation(summary = "산정률2 수정", description = "기존 산정률2 정보를 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "산정률2 수정 성공"), + @ApiResponse(responseCode = "400", description = "산정률2 수정 실패"), + @ApiResponse(description = "오류로 인한 실패") + }) + @PostMapping("/update.ajax") + public ResponseEntity update(@ModelAttribute CmpttnRt2VO paramVO) throws Exception { + // 수정자 정보 설정 + paramVO.setMdfr(SessionUtil.getUserId()); + + int result = service.update(paramVO); + + if (result > 0) { + return ApiResponseUtil.success(MessageConstants.Common.UPDATE_SUCCESS); + } else { + return ApiResponseUtil.error(MessageConstants.Common.UPDATE_ERROR); + } + } + +} diff --git a/src/main/java/go/kr/project/baseData/cmpttnRt2/mapper/CmpttnRt2Mapper.java b/src/main/java/go/kr/project/baseData/cmpttnRt2/mapper/CmpttnRt2Mapper.java new file mode 100644 index 0000000..248833a --- /dev/null +++ b/src/main/java/go/kr/project/baseData/cmpttnRt2/mapper/CmpttnRt2Mapper.java @@ -0,0 +1,71 @@ +package go.kr.project.baseData.cmpttnRt2.mapper; + +import go.kr.project.baseData.cmpttnRt2.model.CmpttnRt2VO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * packageName : go.kr.project.baseData.cmpttnRt2.mapper + * fileName : CmpttnRt2Mapper + * author : 김의진 + * date : 2025-09-24 + * description : 산정률2 MyBatis Mapper 인터페이스 + * 중요한 로직 주석: SQL 쿼리와 매핑되는 메서드들을 정의하여 데이터베이스 접근을 담당한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-24 김의진 최초 생성 + */ +@Mapper +public interface CmpttnRt2Mapper { + + /** + * 산정률2 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 산정률2 목록 + */ + List selectList(CmpttnRt2VO vo); + + /** + * 산정률2 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + int selectListTotalCount(CmpttnRt2VO vo); + + /** + * 특정 코드의 산정률2 정보를 조회한다. + * @param vo 조회할 PK 정보를 담은 VO 객체 + * @return 조회된 산정률2 정보 + */ + CmpttnRt2VO selectOne(CmpttnRt2VO vo); + + /** + * 새로운 산정률2 정보를 등록한다. + * @param vo 등록할 산정률2 정보를 담은 VO 객체 + * @return 등록된 행의 수 + */ + int insert(CmpttnRt2VO vo); + + /** + * 기존 산정률2 정보를 수정한다. + * @param vo 수정할 산정률2 정보를 담은 VO 객체 + * @return 수정된 행의 수 + */ + int update(CmpttnRt2VO vo); + + /** + * 산정률2 정보를 삭제한다. + * @param vo 삭제할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 삭제된 행의 수 + */ + int delete(CmpttnRt2VO vo); + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + int selectDuplicateCheck(CmpttnRt2VO vo); +} diff --git a/src/main/java/go/kr/project/baseData/cmpttnRt2/model/CmpttnRt2VO.java b/src/main/java/go/kr/project/baseData/cmpttnRt2/model/CmpttnRt2VO.java new file mode 100644 index 0000000..bdbd23d --- /dev/null +++ b/src/main/java/go/kr/project/baseData/cmpttnRt2/model/CmpttnRt2VO.java @@ -0,0 +1,80 @@ +package go.kr.project.baseData.cmpttnRt2.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.cmpttnRt2.model + * fileName : CmpttnRt2VO + * author : 김의진 + * date : 2025-09-24 + * description : 산정률2 관련 데이터를 담는 Value Object 클래스 + * 중요한 로직 주석: 산정률2 테이블(tb_cmpttn_rt2)과 매핑되는 VO 클래스로 페이징 기능을 포함한다. * + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-24 김의진 최초 생성 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class CmpttnRt2VO extends PagingVO { + + // ==================== 기본 테이블 컬럼 ==================== + + /** 산정률2 코드 (PK) - 1자리 코드 */ + private String cmpttnRt2Cd; + + /** 위반 사항 */ + private String vltnMttr; + + /** 산정률2 - DECIMAL(3,0) */ + private BigDecimal cmpttnRt2; + + /** 사용 여부 */ + private String useYn; + + /** 등록 일시 - 테이블은 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; + + /** 수정 일시 */ + @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; + + /** 수정자 ID */ + private String mdfr; + + // ==================== 조인 컬럼 (코드명) ==================== + + /** 등록자 */ + private String rgtrNm; + + /** 수정자 */ + private String mdfrNm; + + /** 행 번호 (그리드 표시용) */ + private Integer rowNum; + + // ==================== 검색 조건 ==================== + + /** 검색 조건 선택 */ + private String schType; + private String schTypeTxt; + + /** 검색 조건 - 사용 여부 */ + private String schUseYn; +} diff --git a/src/main/java/go/kr/project/baseData/cmpttnRt2/service/CmpttnRt2Service.java b/src/main/java/go/kr/project/baseData/cmpttnRt2/service/CmpttnRt2Service.java new file mode 100644 index 0000000..ecb4517 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/cmpttnRt2/service/CmpttnRt2Service.java @@ -0,0 +1,69 @@ +package go.kr.project.baseData.cmpttnRt2.service; + +import go.kr.project.baseData.cmpttnRt2.model.CmpttnRt2VO; + +import java.util.List; + +/** + * packageName : go.kr.project.baseData.cmpttnRt2.service + * fileName : CmpttnRt2Service + * author : 김의진 + * date : 2025-09-24 + * description : 산정률2 비즈니스 로직 처리를 위한 서비스 인터페이스 + * 중요한 로직 주석: 컨트롤러와 매퍼 사이의 비즈니스 로직을 정의하고 데이터 처리 규칙을 관리한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-24 김의진 최초 생성 + */ +public interface CmpttnRt2Service { + + /** + * 산정률2 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 산정률2 목록 + */ + List selectList(CmpttnRt2VO vo); + + /** + * 산정률2 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + int selectListTotalCount(CmpttnRt2VO vo); + + /** + * 특정 코드의 산정률2 정보를 조회한다. + * @param vo 조회할 PK 정보를 담은 VO 객체 + * @return 조회된 산정률2 정보 + */ + CmpttnRt2VO selectOne(CmpttnRt2VO vo); + + /** + * 새로운 산정률2 정보를 등록한다. + * @param vo 등록할 산정률2 정보를 담은 VO 객체 + * @return 등록된 행의 수 + */ + int insert(CmpttnRt2VO vo); + + /** + * 기존 산정률2 정보를 수정한다. + * @param vo 수정할 산정률2 정보를 담은 VO 객체 + * @return 수정된 행의 수 + */ + int update(CmpttnRt2VO vo); + + /** + * 산정률2 정보를 삭제한다. + * @param vo 삭제할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 삭제된 행의 수 + */ + int delete(CmpttnRt2VO vo); + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + int selectDuplicateCheck(CmpttnRt2VO vo); +} diff --git a/src/main/java/go/kr/project/baseData/cmpttnRt2/service/impl/CmpttnRt2ServiceImpl.java b/src/main/java/go/kr/project/baseData/cmpttnRt2/service/impl/CmpttnRt2ServiceImpl.java new file mode 100644 index 0000000..3c9c1d5 --- /dev/null +++ b/src/main/java/go/kr/project/baseData/cmpttnRt2/service/impl/CmpttnRt2ServiceImpl.java @@ -0,0 +1,176 @@ +package go.kr.project.baseData.cmpttnRt2.service.impl; + +import egovframework.exception.MessageException; +import egovframework.util.SessionUtil; +import egovframework.util.StringUtil; +import go.kr.project.baseData.cmpttnRt2.mapper.CmpttnRt2Mapper; +import go.kr.project.baseData.cmpttnRt2.model.CmpttnRt2VO; +import go.kr.project.baseData.cmpttnRt2.service.CmpttnRt2Service; +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.cmpttnRt2.service.impl + * fileName : CmpttnRt2ServiceImpl + * author : 김의진 + * date : 2025-09-22 + * description : 산정률2 비즈니스 로직 처리를 위한 서비스 구현체 + * 중요한 로직 주석: 서비스 인터페이스를 구현하여 실제 비즈니스 로직을 처리하고 매퍼를 호출한다. + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 2025-09-22 김의진 최초 생성 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class CmpttnRt2ServiceImpl extends EgovAbstractServiceImpl implements CmpttnRt2Service { + + /** 산정률2 매퍼 */ + private final CmpttnRt2Mapper mapper; + + /** + * 산정률2 목록을 조회한다. + * @param vo 검색 조건과 페이징 정보를 담은 VO 객체 + * @return 산정률2 목록 + */ + @Override + public List selectList(CmpttnRt2VO vo) { + log.debug("산정률2 목록 조회 - 검색조건: {}", vo); + return mapper.selectList(vo); + } + + /** + * 산정률2 목록의 총 개수를 조회한다. + * @param vo 검색 조건을 담은 VO 객체 + * @return 조회된 목록의 총 개수 + */ + @Override + public int selectListTotalCount(CmpttnRt2VO vo) { + log.debug("산정률2 총 개수 조회 - 검색조건: {}", vo); + return mapper.selectListTotalCount(vo); + } + + /** + * 특정 코드에 해당하는 산정률2 정보를 조회한다. + * @param vo 조회할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 조회된 산정률2 정보 + */ + @Override + public CmpttnRt2VO selectOne(CmpttnRt2VO vo) { + log.debug("산정률2 단건 조회 - 코드: {}", vo.getCmpttnRt2Cd()); + return mapper.selectOne(vo); + } + + /** + * 새로운 산정률2 정보를 등록한다. + * PK(코드) 필수값 검증과 중복 체크를 수행한 후 등록을 진행한다. + * @param vo 등록할 산정률2 정보를 담은 VO 객체 + * @return 등록된 행의 수 + * @throws MessageException PK 필수값 누락 또는 중복 시 발생 + */ + @Override + public int insert(CmpttnRt2VO vo) { + log.debug("산정률2 등록 - 코드: {}, 위반 건축물: {}", vo.getCmpttnRt2Cd(), vo.getVltnMttr()); + + // PK(코드) 필수값 검증 + if (vo.getCmpttnRt2Cd() == null || vo.getCmpttnRt2Cd().trim().isEmpty()) { + log.warn("산정률2 등록 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // PK 중복 체크 + int duplicateCount = mapper.selectDuplicateCheck(vo); + if (duplicateCount > 0) { + log.warn("산정률2 등록 실패 - 중복된 PK: 코드={}", vo.getCmpttnRt2Cd()); + throw new MessageException("이미 존재하는 산정률2 코드입니다. 다른 값을 입력해주세요."); + } + + // 위반 건축물 바이트 길이 검증 (한글 3바이트 기준 최대 100바이트) + if (vo.getVltnMttr() != null && !vo.getVltnMttr().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnMttr()); + if (byteLength > 100) { + log.warn("산정률2 등록 실패 - 위반 건축물 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 사항은 최대 100바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 등록자 정보 설정 및 등록 수행 + vo.setRgtr(SessionUtil.getUserId()); + int result = mapper.insert(vo); + log.debug("산정률2 등록 완료 - 등록 건수: {}", result); + return result; + } + + /** + * 기존 산정률2 정보를 수정한다. + * PK(코드) 필수값 검증을 수행한 후 수정을 진행한다. + * @param vo 수정할 산정률2 정보를 담은 VO 객체 + * @return 수정된 행의 수 + * @throws MessageException PK 필수값 누락 시 발생 + */ + @Override + public int update(CmpttnRt2VO vo) { + log.debug("산정률2 수정 - 코드: {}, 위반 건축물: {}", vo.getCmpttnRt2Cd(), vo.getVltnMttr()); + + // PK(코드) 필수값 검증 + if (vo.getCmpttnRt2Cd() == null || vo.getCmpttnRt2Cd().trim().isEmpty()) { + log.warn("산정률2 등록 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // 위반 건축물 바이트 길이 검증 (한글 3바이트 기준 최대 100바이트) + if (vo.getVltnMttr() != null && !vo.getVltnMttr().trim().isEmpty()) { + int byteLength = StringUtil.calculateUtf8ByteLength(vo.getVltnMttr()); + if (byteLength > 100) { + log.warn("산정률2 등록 실패 - 위반 건축물 바이트 길이 초과: {}바이트", byteLength); + throw new MessageException("위반 사항은 최대 100바이트까지 입력 가능합니다. (현재: " + byteLength + "바이트)"); + } + } + + // 수정 수행 + int result = mapper.update(vo); + log.debug("산정률2 수정 완료 - 수정 건수: {}", result); + return result; + } + + /** + * 산정률2 정보를 삭제한다. + * PK(코드) 필수값 검증을 수행한 후 삭제를 진행한다. + * @param vo 삭제할 PK 정보(코드)를 담은 VO 객체 + * @return 삭제된 행의 수 + * @throws MessageException PK 필수값 누락 시 발생 + */ + @Override + public int delete(CmpttnRt2VO vo) { + log.debug("산정률2 삭제 - 코드: {}", vo.getCmpttnRt2Cd()); + + // PK(코드) 필수값 검증 + if (vo.getCmpttnRt2Cd() == null || vo.getCmpttnRt2Cd().trim().isEmpty()) { + log.warn("산정률2 삭제 실패 - 코드 미입력"); + throw new MessageException("코드는 필수값입니다."); + } + + // 삭제 수행 + int result = mapper.delete(vo); + log.debug("산정률2 삭제 완료 - 삭제 건수: {}", result); + return result; + } + + /** + * PK(코드) 중복 체크를 수행한다. + * @param vo 중복 체크할 PK 정보(cmpttnRt2Cd)를 담은 VO 객체 + * @return 중복 건수 (0이면 중복 없음, 1이상이면 중복 존재) + */ + @Override + public int selectDuplicateCheck(CmpttnRt2VO vo) { + log.debug("산정률2 중복 체크 - 코드: {}", vo.getCmpttnRt2Cd()); + return mapper.selectDuplicateCheck(vo); + } + + +} diff --git a/src/main/java/go/kr/project/baseData/strctIdx/controller/StrctIdxController.java b/src/main/java/go/kr/project/baseData/strctIdx/controller/StrctIdxController.java index efb41ee..5acfb6e 100644 --- a/src/main/java/go/kr/project/baseData/strctIdx/controller/StrctIdxController.java +++ b/src/main/java/go/kr/project/baseData/strctIdx/controller/StrctIdxController.java @@ -87,7 +87,7 @@ public class StrctIdxController { @Parameter(description = "화면 모드 (C:등록, U:수정, V:보기)") @RequestParam String mode, Model model) { - //try { + try { log.debug("구조 지수 팝업 화면 요청 - 모드: {}, 구조지수코드: {}", mode, strctIdxCd); ModelAndView mav = new ModelAndView("baseData/strctIdx/popup" + TilesConstants.POPUP); @@ -108,10 +108,10 @@ public class StrctIdxController { return mav; - //} catch (Exception e) { - // log.error("구조 지수 팝업 화면 제공 중 오류 발생", e); - // throw new MessageException("팝업 화면을 불러오는 중 오류가 발생했습니다."); - //} + } catch (Exception e) { + log.error("구조 지수 팝업 화면 제공 중 오류 발생", e); + throw new MessageException("팝업 화면을 불러오는 중 오류가 발생했습니다."); + } } /** diff --git a/src/main/java/go/kr/project/noti/controller/NotiController.java b/src/main/java/go/kr/project/noti/controller/NotiController.java index 51ea506..5fe8aea 100644 --- a/src/main/java/go/kr/project/noti/controller/NotiController.java +++ b/src/main/java/go/kr/project/noti/controller/NotiController.java @@ -1,17 +1,13 @@ package go.kr.project.noti.controller; -import egovframework.constant.MessageConstants; import egovframework.constant.TilesConstants; -import egovframework.exception.MessageException; import egovframework.util.ApiResponseUtil; -import egovframework.util.SessionUtil; import go.kr.project.common.model.CmmnCodeSearchVO; import go.kr.project.common.service.CommonCodeService; import go.kr.project.noti.model.NotiImpltInfoVO; import go.kr.project.noti.model.NotiImpltTrprInfoVO; import go.kr.project.noti.service.NotiService; 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; @@ -21,7 +17,6 @@ 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 javax.servlet.http.HttpServletRequest; import java.util.List; diff --git a/src/main/java/go/kr/project/noti/model/NotiImpltTrprInfoVO.java b/src/main/java/go/kr/project/noti/model/NotiImpltTrprInfoVO.java index 14dae91..810dc65 100644 --- a/src/main/java/go/kr/project/noti/model/NotiImpltTrprInfoVO.java +++ b/src/main/java/go/kr/project/noti/model/NotiImpltTrprInfoVO.java @@ -20,7 +20,6 @@ import java.time.LocalDateTime; * ----------------------------------------------------------- * 2025-09-11 김의진 최초 생성 */ -@Data @Builder @AllArgsConstructor @NoArgsConstructor diff --git a/src/main/resources/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml b/src/main/resources/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml new file mode 100644 index 0000000..077b11a --- /dev/null +++ b/src/main/resources/mybatis/mapper/baseData/actType/ActTypeMapper_maria.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + INSERT INTO tb_act_type ( + ACT_TYPE_CD /* 행위 유형 코드 */ + , VLTN_BDST /* 위반 건축물 */ + , LAWLPRVS /* 법조문 */ + , CMPTTN_RT /* 산정률 */ + , VLTN_BDST_DTL /* 위반 건축물 상세 */ + , USE_YN /* 사용 여부 */ + , REG_DT /* 등록 일시 */ + , RGTR /* 등록자 */ + ) VALUES ( + #{actTypeCd} /* 행위 유형 코드 */ + , #{vltnBdst} /* 위반 건축물 */ + , #{lawlprvs} /* 법조문 */ + , #{cmpttnRt} /* 산정률 */ + , #{vltnBdstDtl} /* 위반 건축물 상세 */ + , #{useYn} /* 사용 여부 */ + , NOW() /* 등록 일시 - 현재 날짜 자동 설정 */ + , #{rgtr} /* 등록자 - 세션 사용자 ID */ + ) + + + + + UPDATE tb_act_type + SET VLTN_BDST = #{vltnBdst} /* 위반 건축물 */ + , LAWLPRVS = #{lawlprvs} /* 법조문 */ + , CMPTTN_RT = #{cmpttnRt} /* 산정률 */ + , VLTN_BDST_DTL = #{vltnBdstDtl} /* 위반 건축물 상세 */ + , USE_YN = #{useYn} /* 사용 여부 */ + , MDFCN_DT = NOW() /* 수정 일시 */ + , MDFR = #{mdfr} /* 수정자 */ + WHERE ACT_TYPE_CD = #{actTypeCd} /* 행위 유형 코드 */ + + + + + diff --git a/src/main/resources/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml b/src/main/resources/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml new file mode 100644 index 0000000..a263cc8 --- /dev/null +++ b/src/main/resources/mybatis/mapper/baseData/cmpttnRt2/CmpttnRt2Mapper_maria.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + INSERT INTO tb_cmpttn_rt_2 ( + CMPTTN_RT_2_CD /* 산정률2 코드 */ + , VLTN_MTTR /* 위반 사항 */ + , CMPTTN_RT_2 /* 산정률2 */ + , USE_YN /* 사용 여부 */ + , REG_DT /* 등록 일시 */ + , RGTR /* 등록자 */ + ) VALUES ( + #{cmpttnRt2Cd} /* 산정률2 코드 */ + , #{vltnMttr} /* 위반 사항 */ + , #{cmpttnRt2} /* 산정률2 */ + , #{useYn} /* 사용 여부 */ + , NOW() /* 등록 일시 - 현재 날짜 자동 설정 */ + , #{rgtr} /* 등록자 - 세션 사용자 ID */ + ) + + + + + UPDATE tb_cmpttn_rt_2 + SET VLTN_MTTR = #{vltnMttr} /* 위반 사항 */ + , CMPTTN_RT_2 = #{cmpttnRt2} /* 산정률2 */ + , USE_YN = #{useYn} /* 사용 여부 */ + , MDFCN_DT = NOW() /* 수정 일시 */ + , MDFR = #{mdfr} /* 수정자 */ + WHERE CMPTTN_RT_2_CD = #{cmpttnRt2Cd} /* 산정률2 코드 */ + + + + + diff --git a/src/main/webapp/WEB-INF/views/baseData/actType/list.jsp b/src/main/webapp/WEB-INF/views/baseData/actType/list.jsp new file mode 100644 index 0000000..372b567 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/baseData/actType/list.jsp @@ -0,0 +1,376 @@ +<%@ 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"%> + + +
+
+
+
+
+ + +
+
+
+
+
+
    +
  • 조회 조건
  • +
  • +
  • +
  • +
  • 사용 여부
  • +
  • +
  • +
+
    +
  • +
  • +
+
+
+
+
+
+
    +
  • 행위 유형 목록
  • +
  • 총 0건
  • +
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/baseData/actType/popup.jsp b/src/main/webapp/WEB-INF/views/baseData/actType/popup.jsp new file mode 100644 index 0000000..544561e --- /dev/null +++ b/src/main/webapp/WEB-INF/views/baseData/actType/popup.jsp @@ -0,0 +1,160 @@ +<%@ 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" %> + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/list.jsp b/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/list.jsp new file mode 100644 index 0000000..614e66f --- /dev/null +++ b/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/list.jsp @@ -0,0 +1,366 @@ +<%@ 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"%> + + +
+
+
+
+
+ + +
+
+
+
+
+
    +
  • 조회 조건
  • +
  • +
  • +
  • +
  • 사용 여부
  • +
  • +
  • +
+
    +
  • +
  • +
+
+
+
+
+
+
    +
  • 산정률2 목록
  • +
  • 총 0건
  • +
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/popup.jsp b/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/popup.jsp new file mode 100644 index 0000000..44db43a --- /dev/null +++ b/src/main/webapp/WEB-INF/views/baseData/cmpttnRt2/popup.jsp @@ -0,0 +1,147 @@ +<%@ 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" %> + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/baseData/strctIdx/list.jsp b/src/main/webapp/WEB-INF/views/baseData/strctIdx/list.jsp index 10a4e31..7c30b74 100644 --- a/src/main/webapp/WEB-INF/views/baseData/strctIdx/list.jsp +++ b/src/main/webapp/WEB-INF/views/baseData/strctIdx/list.jsp @@ -142,7 +142,7 @@ header : '구조명', name : 'strctNm', align : 'center', - width : 300, + minwidth : 300, sortable : true }, { header : '구조지수', @@ -319,6 +319,7 @@ // 모든 검색 조건 초기화 $("#schType").val("1"); $("#schTypeTxt").val(""); + $("#schDelYn").val("N"); // 그리드 데이터 새로고침 self.grid.instance.readData(); diff --git a/src/main/webapp/WEB-INF/views/baseData/usgIdx/list.jsp b/src/main/webapp/WEB-INF/views/baseData/usgIdx/list.jsp index ebcca65..01a267b 100644 --- a/src/main/webapp/WEB-INF/views/baseData/usgIdx/list.jsp +++ b/src/main/webapp/WEB-INF/views/baseData/usgIdx/list.jsp @@ -144,7 +144,7 @@ header : '용도명', name : 'usgNm', align : 'center', - width : 400, + minwidth : 400, sortable : true }, { header : '용도지수', diff --git a/src/main/webapp/WEB-INF/views/crdn/exmnr/list.jsp b/src/main/webapp/WEB-INF/views/crdn/exmnr/list.jsp index 8c1416b..e68a23f 100644 --- a/src/main/webapp/WEB-INF/views/crdn/exmnr/list.jsp +++ b/src/main/webapp/WEB-INF/views/crdn/exmnr/list.jsp @@ -171,7 +171,7 @@ header: '조사원', name: 'exmnr', align: 'center', - width: 120 + minwidth: 120 //sortable: true }, { @@ -185,7 +185,19 @@ name: 'rgtrNm', align: 'center', width: 100 - } + }, + { + header : '수정일시', + name : 'mdfcnDt', + align : 'center', + width : 150 + }, + { + header : '수정자', + name : 'mdfrNm', + align : 'center', + width : 100 + } ]; }, diff --git a/src/main/webapp/WEB-INF/views/noti/list.jsp b/src/main/webapp/WEB-INF/views/noti/list.jsp index 78ff81a..2cbe3ca 100644 --- a/src/main/webapp/WEB-INF/views/noti/list.jsp +++ b/src/main/webapp/WEB-INF/views/noti/list.jsp @@ -202,6 +202,12 @@ width: 100, sortable: true }, + { + header: '진행단계', + name: 'impltTaskSeCdNm', + align: 'center', + width: 100 + }, { header: '구분', name: 'rgnSeCdNm', @@ -305,6 +311,10 @@ GRID_PAGINATION_INFO.totalCount = responseObj.data.pagination.totalCount; GRID_PAGINATION_INFO.page = responseObj.data.pagination.page; GRID_PAGINATION_INFO.perPage = responseObj.data.pagination.perPage; + + //하단 그리드 초기화 + NotiList.selectCdGroupId = ''; + NotiList.detailGrid.instance.readData(1); } // 선택된 행 초기화 diff --git a/src/main/webapp/resources/xit/common_util.js b/src/main/webapp/resources/xit/common_util.js index de5f14a..1ebe721 100644 --- a/src/main/webapp/resources/xit/common_util.js +++ b/src/main/webapp/resources/xit/common_util.js @@ -162,7 +162,7 @@ $(document).ready(function () { groupSeparator: ",", // 그룹 구분자 없음 repeat: 1, // 정수부 최대 1자리 (0) digits: 4, // 소수점 최대 4자리 - max: 0.9999, + max: 0.9999 }); }); @@ -194,6 +194,36 @@ $(document).ready(function () { digits: 2 // 소수점 사용 안함 }); }); + + // 중요로직: Act_Type_Cd 전용 마스크 - 숫자 3자리 + $("body").on("focus", ".actTypeCdMask", function () { + $(this).inputmask({ + mask: "999", // 3자리 숫자 패턴 (선행 0 포함) + placeholder: "000", // 입력 안내용 플레이스홀더 + definitions: { + "9": { + validator: "[0-9]", // 숫자만 허용 + cardinality: 1 + } + }, + autoUnmask: true, // 마스크 제거 후 실제 값 반환 + rightAlign: false // 왼쪽 정렬 + }); + }); + + // 중요로직: Cmpttn_Rt 전용 마스크 - 숫자 3자리 + $("body").on("focus", ".cmpttnRtMask", function () { + $(this).inputmask("numeric", { + autoGroup: true, // 그룹화 사용 안함 + allowMinus: false, // 음수 사용 안함 + autoUnmask: true, + rightAlign: false, + groupSeparator: ",", // 그룹 구분자 없음 + repeat: 3, // 정수부 최대 3자리 + digits: 0, // 소수점 사용 안함 + max: 100 + }); + }); });