From a1c2a7307a408a64cdb5c0cc35eeb0442e4c3572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=EC=98=81?= Date: Fri, 26 Sep 2025 17:07:40 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8B=A8=EC=86=8D=20=ED=96=89=EC=9C=84?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20-=20=EC=B5=9C=EC=A2=85=20=EC=A1=B0?= =?UTF-8?q?=EC=B9=98=EC=9D=BC=EC=9E=90,=20=EC=B4=9D=EB=A9=B4=EC=A0=81,=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EA=B0=92=EB=93=B1=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EC=A7=84=ED=96=89=EC=A4=91...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crdnActInfo/mapper/CrdnActInfoMapper.java | 7 + .../crdnActInfo/model/CrdnActInfoVO.java | 6 +- .../service/impl/CrdnActInfoServiceImpl.java | 144 +++++++++++++++++- .../crdnActInfo/CrdnActInfoMapper_maria.xml | 13 ++ .../crdnActInfo/crdnActnInfoRegistPopup.jsp | 3 - 5 files changed, 166 insertions(+), 7 deletions(-) diff --git a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/mapper/CrdnActInfoMapper.java b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/mapper/CrdnActInfoMapper.java index 78b3217..2c6a4b5 100644 --- a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/mapper/CrdnActInfoMapper.java +++ b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/mapper/CrdnActInfoMapper.java @@ -47,6 +47,13 @@ public interface CrdnActInfoMapper { */ int updateActInfo(CrdnActInfoVO vo); + /** + * 행위정보의 조치 관련 데이터 업데이트 + * @param vo 업데이트할 조치 관련 정보 (actInfoId, actnLastYmd, actnWholArea, actnPrcsSttsCd, mdfr) + * @return 업데이트 결과 + */ + int updateActInfoActnData(CrdnActInfoVO vo); + /** * 불법위반행위정보 삭제 (논리삭제) * @param vo 삭제할 불법위반행위정보 (delYn, delDt, dltr 포함) diff --git a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/model/CrdnActInfoVO.java b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/model/CrdnActInfoVO.java index 37df4bc..56fbccf 100644 --- a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/model/CrdnActInfoVO.java +++ b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/model/CrdnActInfoVO.java @@ -37,9 +37,9 @@ public class CrdnActInfoVO extends PagingVO { private BigDecimal vrtc; // 세로 private BigDecimal area; // 면적 private String rmrk; // 비고 - private String actnYmd; // 조치 일자 - private BigDecimal actnArea; // 조치 면적 - private String actnRmrk; // 조치 비고 + private String actnLastYmd; // 조치 최종 일자 + private BigDecimal actnWholArea; // 조치 총 면적 + private String actnPrcsSttsCd; // 조치 처리 상태 코드 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") diff --git a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/service/impl/CrdnActInfoServiceImpl.java b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/service/impl/CrdnActInfoServiceImpl.java index a5a3a65..56f0cc8 100644 --- a/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/service/impl/CrdnActInfoServiceImpl.java +++ b/src/main/java/go/kr/project/crdn/crndRegistAndView/crdnActInfo/service/impl/CrdnActInfoServiceImpl.java @@ -14,7 +14,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.math.BigDecimal; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * 불법위반행위정보 서비스 구현체 @@ -317,6 +320,9 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C vo, actnPhotoFiles != null ? actnPhotoFiles.size() : 0); try { + // 중요한 로직 주석: 등록 전 면적 검증 수행 + updateActInfoWithActnData(vo.getActInfoId(), vo.getActnArea(), true); + // 중요한 로직 주석: 먼저 조치정보를 등록한다 (insertActnInfo 메서드에서 actnInfoId가 자동 설정됨) int result = mapper.insertActnInfo(vo); @@ -330,6 +336,9 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C int actnPhotoResult = photoService.insertActnPhotosWithFiles(actnPhotoFiles, vo); log.debug("조치사진 파일 처리 완료: actnInfoId={}, 등록된 조치사진 수={}", vo.getActnInfoId(), actnPhotoResult); } + + // 중요한 로직 주석: 조치정보 등록 후 행위정보의 조치 관련 데이터 업데이트 + updateActInfoWithActnData(vo.getActInfoId(), null, false); } else { log.error("조치정보 등록 실패: {}", vo); throw new MessageException("조치정보 등록에 실패했습니다."); @@ -350,6 +359,26 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C vo, actnPhotoFiles != null ? actnPhotoFiles.size() : 0); try { + // 중요한 로직 주석: 수정 전 기존 조치정보 조회 및 면적 검증 수행 + CrdnActnInfoVO existingActnInfo = mapper.selectActnInfoByPk(vo.getActnInfoId()); + if (existingActnInfo == null) { + throw new MessageException("수정할 조치정보를 찾을 수 없습니다."); + } + + // 중요한 로직 주석: 면적 변경이 있는 경우 검증 수행 (기존 면적 제외하고 새 면적으로 검증) + BigDecimal areaDifference = BigDecimal.ZERO; + if (vo.getActnArea() != null && existingActnInfo.getActnArea() != null) { + areaDifference = vo.getActnArea().subtract(existingActnInfo.getActnArea()); + } else if (vo.getActnArea() != null) { + areaDifference = vo.getActnArea(); + } else if (existingActnInfo.getActnArea() != null) { + areaDifference = existingActnInfo.getActnArea().negate(); + } + + if (areaDifference.compareTo(BigDecimal.ZERO) != 0) { + updateActInfoWithActnData(vo.getActInfoId(), areaDifference, true); + } + // 중요한 로직 주석: 먼저 조치정보를 수정한다 int result = mapper.updateActnInfo(vo); @@ -361,6 +390,9 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C int actnPhotoResult = photoService.insertActnPhotosWithFiles(actnPhotoFiles, vo); log.debug("조치사진 파일 처리 완료: actnInfoId={}, 등록된 조치사진 수={}", vo.getActnInfoId(), actnPhotoResult); } + + // 중요한 로직 주석: 조치정보 수정 후 행위정보의 조치 관련 데이터 업데이트 + updateActInfoWithActnData(vo.getActInfoId(), null, false); } else { log.error("조치정보 수정 실패: {}", vo); throw new MessageException("조치정보 수정에 실패했습니다."); @@ -379,6 +411,13 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C public int deleteActnInfo(CrdnActnInfoVO vo) { log.debug("조치정보 삭제: {}", vo); + // 중요한 로직 주석: 삭제할 조치정보 조회 (행위정보 업데이트를 위해) + CrdnActnInfoVO existingActnInfo = mapper.selectActnInfoByPk(vo.getActnInfoId()); + String actInfoId = null; + if (existingActnInfo != null) { + actInfoId = existingActnInfo.getActInfoId(); + } + // 중요한 로직 주석: 조치정보 삭제 시 관련된 모든 조치사진도 함께 삭제한다. if (vo.getActnInfoId() != null) { try { @@ -391,7 +430,93 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C } } - return mapper.deleteActnInfo(vo); + int result = mapper.deleteActnInfo(vo); + + // 중요한 로직 주석: 조치정보 삭제 후 행위정보의 조치 관련 데이터 업데이트 + if (result > 0 && actInfoId != null) { + updateActInfoWithActnData(actInfoId, null, false); + } + + return result; + } + + /** + * 행위정보의 조치 관련 필드를 업데이트한다 + * 중요한 로직 주석: 조치정보 변경 시마다 행위정보의 조치 관련 정보를 재계산하여 업데이트한다 + * @param actInfoId 행위정보 ID + * @param currentActnArea 현재 작업 중인 조치 면적 (등록/수정 시 검증용) + * @param isValidationCheck 면적 검증 여부 (등록/수정 시 true, 삭제 시 false) + */ + private void updateActInfoWithActnData(String actInfoId, BigDecimal currentActnArea, boolean isValidationCheck) { + // 중요한 로직 주석: 행위정보 조회 + CrdnActInfoVO actInfo = mapper.selectActInfoByPk(actInfoId); + if (actInfo == null) { + log.warn("행위정보를 찾을 수 없습니다. actInfoId: {}", actInfoId); + return; + } + + // 중요한 로직 주석: 해당 행위정보의 모든 조치정보 조회하여 총 면적 계산 + CrdnActnInfoVO actnSearchVO = CrdnActnInfoVO.builder() + .actInfoId(actInfoId) + .build(); + List actnInfoList = mapper.selectActnInfoList(actnSearchVO); + + BigDecimal totalActnArea = BigDecimal.ZERO; + String lastActnYmd = null; + + for (CrdnActnInfoVO actnInfo : actnInfoList) { + if (actnInfo.getActnArea() != null) { + totalActnArea = totalActnArea.add(actnInfo.getActnArea()); + } + // 최신 조치일자 찾기 + if (actnInfo.getActnYmd() != null && + (lastActnYmd == null || actnInfo.getActnYmd().compareTo(lastActnYmd) > 0)) { + lastActnYmd = actnInfo.getActnYmd(); + } + } + + // 중요한 로직 주석: 등록/수정 시 현재 작업 중인 면적을 추가하여 검증 + if (isValidationCheck && currentActnArea != null) { + BigDecimal totalWithCurrent = totalActnArea.add(currentActnArea); + + // 중요한 로직 주석: 조치 총 면적이 행위정보 면적을 초과하는 경우 예외 처리 + if (actInfo.getArea() != null && totalWithCurrent.compareTo(actInfo.getArea()) > 0) { + BigDecimal remainingArea = actInfo.getArea().subtract(totalActnArea); + String errorMessage = String.format( + "조치 총 면적(%.2f㎡)이 행위정보 면적(%.2f㎡)을 초과할 수 없습니다.\n남은 면적: %.2f㎡", + totalWithCurrent.doubleValue(), actInfo.getArea().doubleValue(), remainingArea.doubleValue() + ); + throw new MessageException(errorMessage); + } + } + + // 중요한 로직 주석: 조치 처리 상태 코드 결정 + String actnPrcsSttsCd = "1"; // 기본값: 미조치 + if (totalActnArea.compareTo(BigDecimal.ZERO) > 0 && actInfo.getArea() != null) { + int comparison = totalActnArea.compareTo(actInfo.getArea()); + if (comparison == 0) { + actnPrcsSttsCd = "3"; // 조치완료 + } else if (comparison < 0) { + actnPrcsSttsCd = "2"; // 부분조치 + } + } + + // 중요한 로직 주석: 행위정보 업데이트 + CrdnActInfoVO updateVO = CrdnActInfoVO.builder() + .actInfoId(actInfoId) + .actnLastYmd(lastActnYmd) + .actnWholArea(totalActnArea) + .actnPrcsSttsCd(actnPrcsSttsCd) + .mdfr(SessionUtil.getUserId()) + .build(); + + int updateResult = mapper.updateActInfoActnData(updateVO); + if (updateResult > 0) { + log.debug("행위정보 조치 데이터 업데이트 완료: actInfoId={}, totalArea={}, status={}", + actInfoId, totalActnArea, actnPrcsSttsCd); + } else { + log.warn("행위정보 조치 데이터 업데이트 실패: actInfoId={}", actInfoId); + } } /** @@ -421,6 +546,8 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C // 중요한 로직 주석: 각 조치정보 ID에 대해 유효성 검증 후 논리 삭제 수행 int deletedCount = 0; + Set affectedActInfoIds = new HashSet<>(); // 업데이트가 필요한 행위정보 ID 목록 + for (String actnInfoId : actnInfoIds) { if (actnInfoId != null && !actnInfoId.trim().isEmpty()) { // 중요한 로직 주석: 삭제할 데이터 존재 여부 확인 @@ -430,6 +557,11 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C continue; } + // 중요한 로직 주석: 행위정보 ID 수집 (나중에 업데이트용) + if (existingData.getActInfoId() != null) { + affectedActInfoIds.add(existingData.getActInfoId()); + } + // 중요한 로직 주석: 해당 조치정보의 관련 사진들을 먼저 삭제한다. try { photoService.deleteActnPhotosByActnInfoId(actnInfoId, userId); @@ -455,6 +587,16 @@ public class CrdnActInfoServiceImpl extends EgovAbstractServiceImpl implements C } } + // 중요한 로직 주석: 영향 받은 모든 행위정보의 조치 관련 데이터 업데이트 + for (String actInfoId : affectedActInfoIds) { + try { + updateActInfoWithActnData(actInfoId, null, false); + log.debug("행위정보 조치 데이터 업데이트 완료: actInfoId={}", actInfoId); + } catch (Exception e) { + log.warn("행위정보 조치 데이터 업데이트 중 오류 발생: actInfoId={}", actInfoId, e); + } + } + log.info("조치정보 일괄 삭제 완료. 요청: {}건, 삭제: {}건", actnInfoIds.size(), deletedCount); return deletedCount; } diff --git a/src/main/resources/mybatis/mapper/crdn/crndRegistAndView/crdnActInfo/CrdnActInfoMapper_maria.xml b/src/main/resources/mybatis/mapper/crdn/crndRegistAndView/crdnActInfo/CrdnActInfoMapper_maria.xml index 1604b4b..9d35584 100644 --- a/src/main/resources/mybatis/mapper/crdn/crndRegistAndView/crdnActInfo/CrdnActInfoMapper_maria.xml +++ b/src/main/resources/mybatis/mapper/crdn/crndRegistAndView/crdnActInfo/CrdnActInfoMapper_maria.xml @@ -490,4 +490,17 @@ AND DEL_YN = 'N' + + + /* ActInfoMapper.updateActInfoActnData : 행위정보의 조치 관련 데이터 업데이트 */ + UPDATE tb_act_info SET + ACTN_LAST_YMD = replace(#{actnLastYmd},'-',''), + ACTN_WHOL_AREA = #{actnWholArea}, + ACTN_PRCS_STTS_CD = #{actnPrcsSttsCd}, + MDFCN_DT = NOW(), + MDFR = #{mdfr} + WHERE ACT_INFO_ID = #{actInfoId} + AND DEL_YN = 'N' + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnActInfo/crdnActnInfoRegistPopup.jsp b/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnActInfo/crdnActnInfoRegistPopup.jsp index 1f36985..ea71076 100644 --- a/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnActInfo/crdnActnInfoRegistPopup.jsp +++ b/src/main/webapp/WEB-INF/views/crdn/crndRegistAndView/crdnActInfo/crdnActnInfoRegistPopup.jsp @@ -498,9 +498,6 @@ } else { alert(response.message || '조치정보 저장에 실패했습니다.'); } - }, - error: function() { - alert('조치정보 저장 중 오류가 발생했습니다.'); } }); },