처리상태, 비고 수정로직 추가

main
박성영 3 weeks ago
parent 2745927092
commit 58bff37e5e

@ -4,6 +4,7 @@ import egovframework.constant.MessageConstants;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import egovframework.util.SessionUtil;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtModifiedDataVO;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO;
import go.kr.project.carInspectionPenalty.registration.service.CarFfnlgTrgtService;
import go.kr.project.common.model.CmmnCodeSearchVO;
@ -404,6 +405,35 @@ public class CarFfnlgTrgtController {
}
}
/**
* AJAX
* , , .
*
* @param modifyData // VO
* @return / ResponseEntity
*/
@PostMapping("/saveAll.ajax")
@ResponseBody
@Operation(summary = "과태료 대상 정보 일괄 저장", description = "생성, 수정, 삭제된 과태료 대상 데이터를 일괄 처리합니다.")
public ResponseEntity<?> saveAllAjax(@RequestBody CarFfnlgTrgtModifiedDataVO modifyData) {
log.info("과태료 대상 일괄 저장 요청 - 수정: {}건, 생성: {}건, 삭제: {}건",
modifyData.getUpdatedRows() != null ? modifyData.getUpdatedRows().size() : 0,
modifyData.getCreatedRows() != null ? modifyData.getCreatedRows().size() : 0,
modifyData.getDeletedRows() != null ? modifyData.getDeletedRows().size() : 0);
try {
int result = service.saveCarFfnlgTrgts(modifyData);
if (result > 0) {
return ApiResponseUtil.success("과태료 대상 정보가 저장되었습니다.");
} else {
return ApiResponseUtil.error("저장할 데이터가 없습니다.");
}
} catch (Exception e) {
log.error("과태료 대상 일괄 저장 중 오류 발생", e);
return ApiResponseUtil.error("저장 중 오류가 발생했습니다: " + e.getMessage());
}
}
/**
* UTF-8 MultipartFile EUC-KR
*

@ -45,7 +45,14 @@ public interface CarFfnlgTrgtMapper {
* @return
*/
int update(CarFfnlgTrgtVO vo);
/**
*
* @param vo (carFfnlgTrgtId, taskPrcsSttsCd, rmrk)
* @return
*/
int updateTaskPrcsSttsCdAndRmrk(CarFfnlgTrgtVO vo);
/**
* ()
* @param vo (carFfnlgTrgtId, dltr)

@ -0,0 +1,31 @@
package go.kr.project.carInspectionPenalty.registration.model;
import go.kr.project.common.model.PagingVO;
import lombok.*;
import java.util.List;
/**
* packageName : go.kr.project.carInspectionPenalty.registration.model
* fileName : CarFfnlgTrgtModifiedDataVO
* author :
* date : 2025-11-28
* description : VO
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-11-28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CarFfnlgTrgtModifiedDataVO extends PagingVO {
private List<CarFfnlgTrgtVO> createdRows;
private List<CarFfnlgTrgtVO> updatedRows;
private List<CarFfnlgTrgtVO> deletedRows;
}

@ -1,5 +1,6 @@
package go.kr.project.carInspectionPenalty.registration.service;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtModifiedDataVO;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO;
import org.springframework.web.multipart.MultipartFile;
@ -77,4 +78,13 @@ public interface CarFfnlgTrgtService {
* @return (compareResults, totalCount, successCount, failCount)
*/
Map<String, Object> compareWithApi(List<Map<String, String>> targetList);
/**
*
* , , .
*
* @param modifyData // VO
* @return
*/
int saveCarFfnlgTrgts(CarFfnlgTrgtModifiedDataVO modifyData);
}

@ -2,9 +2,11 @@ package go.kr.project.carInspectionPenalty.registration.service.impl;
import egovframework.constant.TaskPrcsSttsConstants;
import egovframework.exception.MessageException;
import egovframework.util.SessionUtil;
import go.kr.project.api.service.ExternalVehicleApiService;
import go.kr.project.carInspectionPenalty.registration.config.CarFfnlgTxtParseConfig;
import go.kr.project.carInspectionPenalty.registration.mapper.CarFfnlgTrgtMapper;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtModifiedDataVO;
import go.kr.project.carInspectionPenalty.registration.model.CarFfnlgTrgtVO;
import go.kr.project.carInspectionPenalty.registration.service.CarFfnlgTrgtService;
import go.kr.project.carInspectionPenalty.registration.service.ComparisonService;
@ -1008,4 +1010,64 @@ public class CarFfnlgTrgtServiceImpl extends EgovAbstractServiceImpl implements
return resultData;
}
/**
*
* , , .
*
* @param modifyData // VO
* @return
*/
@Override
@Transactional
public int saveCarFfnlgTrgts(CarFfnlgTrgtModifiedDataVO modifyData) {
int result = 0;
// 1. 삭제된 행 처리 (논리 삭제)
List<CarFfnlgTrgtVO> deletedRows = modifyData.getDeletedRows();
if (deletedRows != null && !deletedRows.isEmpty()) {
for (CarFfnlgTrgtVO vo : deletedRows) {
// 삭제자 정보 설정
String dltr = SessionUtil.getUserId();
if (dltr == null || dltr.isEmpty()) {
throw new MessageException("로그인 정보가 없습니다.");
}
vo.setDltr(dltr);
// 논리 삭제 처리
result += mapper.delete(vo);
}
}
// 2. 추가된 행 처리
List<CarFfnlgTrgtVO> createdRows = modifyData.getCreatedRows();
if (createdRows != null && !createdRows.isEmpty()) {
for (CarFfnlgTrgtVO vo : createdRows) {
// 등록자 정보 설정
String rgtr = SessionUtil.getUserId();
if (rgtr == null || rgtr.isEmpty()) {
throw new MessageException("로그인 정보가 없습니다.");
}
vo.setRgtr(rgtr);
// 기본값 설정
if (vo.getTaskPrcsSttsCd() == null || vo.getTaskPrcsSttsCd().isEmpty()) {
vo.setTaskPrcsSttsCd(TaskPrcsSttsConstants.TASK_PRCS_STTS_CD_01_RCPT);
}
result += mapper.insert(vo);
}
}
// 3. 수정된 행 처리 (처리상태, 비고만 수정)
List<CarFfnlgTrgtVO> updatedRows = modifyData.getUpdatedRows();
if (updatedRows != null && !updatedRows.isEmpty()) {
for (CarFfnlgTrgtVO vo : updatedRows) {
result += mapper.updateTaskPrcsSttsCdAndRmrk(vo);
}
}
log.info("과태료 대상 일괄 저장 완료 - 처리 건수: {}", result);
return result;
}
}

@ -243,7 +243,16 @@
WHERE CAR_FFNLG_TRGT_ID = #{carFfnlgTrgtId}
AND DEL_DT IS NULL
</update>
<!-- 과태료 대상의 처리상태와 비고만 수정 -->
<update id="updateTaskPrcsSttsCdAndRmrk" parameterType="CarFfnlgTrgtVO">
UPDATE tb_car_ffnlg_trgt
SET TASK_PRCS_STTS_CD = #{taskPrcsSttsCd},
RMRK = #{rmrk}
WHERE CAR_FFNLG_TRGT_ID = #{carFfnlgTrgtId}
AND DEL_DT IS NULL
</update>
<!-- 과태료 대상 삭제 (논리삭제) -->
<update id="delete" parameterType="CarFfnlgTrgtVO">
UPDATE tb_car_ffnlg_trgt

@ -10,8 +10,7 @@
<div class="bgs-main">
<section id="section5">
<div class="sub_title">과태료 대상 목록</div>
<button type="button" id="registerBtn" class="newbtn bg1">등록</button>
<button type="button" id="deleteBtn" class="newbtn bg6">삭제</button>
<button type="button" id="registerBtn" class="newbtn bg1">TXT 등록</button>
<button type="button" id="downloadBtn" class="newbtn bg3">TXT 목록 다운로드</button>
</section>
</div>
@ -59,8 +58,11 @@
<ul class="box_title" style="display: flex; justify-content: space-between; align-items: center;">
<li class="tit">과태료 대상 목록</li>
<li class="rig">
<button type="button" id="callApiBtn" class="newbtn bg2-1">그리드 선택 API 호출</button>
<button type="button" id="callApiAllBtn" class="newbtn bg2-1">검색조건 전체 API 호출</button>
<button type="button" id="callApiBtn" class="newbtn bg2-1">선택 API 호출</button>
<button type="button" id="deleteBtn" class="newbtn bg6">선택 삭제</button>
<button type="button" id="btn_cancel" class="newbtn bg6">수정 취소</button>
<button type="button" id="btn_save" class="newbtn bg4">저장</button>
<span id="totalCount" class="total-count" style="padding-left: 25px;padding-right: 25px;">총 0건</span>
<select id="perPageSelect" class="input" style="width: 112px; ">
@ -333,14 +335,44 @@
}
},
{ header: '매매상품', name: 'trdGds', align: 'center', width: 100 },
{ header: '처리상태코드', name: 'taskPrcsSttsCd', align: 'center', width: 100, hidden: true },
{ header: '처리상태', name: 'taskPrcsSttsCdNm', align: 'center', width: 100 },
{
header: '처리상태',
name: 'taskPrcsSttsCd',
align: 'center',
width: 100,
editor: {
type: 'select',
options: {
listItems: [
<c:forEach var="code" items="${taskPrcsSttsCdList}" varStatus="status">
{text: '${code.cdNm}', value: '${code.cdId}'}<c:if test="${!status.last}">,</c:if>
</c:forEach>
]
}
},
formatter: function(props) {
var value = props.value;
var codeList = [
<c:forEach var="code" items="${taskPrcsSttsCdList}" varStatus="status">
{id: '${code.cdId}', nm: '${code.cdNm}'}<c:if test="${!status.last}">,</c:if>
</c:forEach>
];
var code = codeList.find(function(c) { return c.id === value; });
return code ? code.nm : value;
}
},
{ header: '처리일자', name: 'taskPrcsYmd', align: 'center', width: 100,
formatter: function(e) {
return e.value ? moment(e.value, 'YYYYMMDD').format('YYYY-MM-DD') : '';
}
},
{ header: '비고', name: 'rmrk', align: 'left', width: 200 },
{
header: '비고',
name: 'rmrk',
align: 'left',
width: 200,
editor: 'text'
},
{ header: '기본사항조회성명', name: 'carBscMttrInqFlnm', align: 'center', width: 100 },
{ header: '기본사항조회시군구코드', name: 'carBscMttrInqSggCd', align: 'center', width: 100, hidden: true },
{ header: '기본사항조회시군구명', name: 'carBscMttrInqSggNm', align: 'center', width: 120 },
@ -464,6 +496,79 @@
setSearchCond();
LAST_GRID_SEARCH_COND = Object.assign({}, SEARCH_COND);
this.instance.readData(1);
},
/**
* 그리드 변경사항 취소
*/
cancelChanges: function() {
var self = this;
// 변경된 데이터 확인
var modifiedRows = this.instance.getModifiedRows();
// 변경된 데이터가 없으면 알림
if (modifiedRows.createdRows.length === 0 &&
modifiedRows.updatedRows.length === 0 &&
modifiedRows.deletedRows.length === 0) {
alert('취소할 변경사항이 없습니다.');
return;
}
// 취소 확인
if (confirm('모든 변경사항을 취소하시겠습니까?')) {
// 현재 페이지 저장
var currentPage = this.instance.getPagination().getCurrentPage();
// 그리드 데이터를 다시 로드하여 모든 변경사항 취소
this.instance.readData(currentPage);
}
},
/**
* 그리드 변경사항 저장
*/
saveData: function() {
var self = this;
// 변경된 데이터 확인
var modifiedRows = this.instance.getModifiedRows();
// 변경된 데이터가 없으면 저장하지 않음
if (modifiedRows.createdRows.length === 0 &&
modifiedRows.updatedRows.length === 0 &&
modifiedRows.deletedRows.length === 0) {
alert('저장할 데이터가 없습니다.');
return;
}
console.log(modifiedRows);
var confirmMsg = "변경된 내용을 저장하시겠습니까?";
if (modifiedRows.deletedRows.length > 0) {
confirmMsg += "\n삭제 포함되어 있습니다."
}
// 저장 확인
if (confirm(confirmMsg)) {
$.ajax({
url: '<c:url value="/carInspectionPenalty/registration/saveAll.ajax"/>',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(modifiedRows),
success: function(response) {
if (response.result) {
alert(response.message);
self.instance.readData(1);
} else {
alert(response.message);
}
},
error: function(xhr, status, error) {
console.error("저장 실패:", error);
alert("저장 중 오류가 발생했습니다.");
}
});
}
}
},
@ -546,6 +651,16 @@
self.grid.reload();
}
});
// 취소 버튼 클릭 이벤트
$('#btn_cancel').on('click', function() {
self.grid.cancelChanges();
});
// 저장 버튼 클릭 이벤트
$('#btn_save').on('click', function() {
self.grid.saveData();
});
},
/**

Loading…
Cancel
Save