package cokr.xit.fims.crdn.web; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.poi.ss.usermodel.CellStyle; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import cokr.xit.base.code.CommonCode; import cokr.xit.base.docs.xls.CellDef; import cokr.xit.base.docs.xls.Comment; import cokr.xit.base.docs.xls.Format; import cokr.xit.base.docs.xls.Style; import cokr.xit.base.docs.xls.XLSWriter; import cokr.xit.base.file.FileInfo; import cokr.xit.base.file.FileInfo.Relation; import cokr.xit.base.file.service.FileQuery; import cokr.xit.base.file.service.FileService; import cokr.xit.base.file.service.bean.FileBean; import cokr.xit.base.file.web.FileInfoFactory; import cokr.xit.base.user.dao.UserMapper; import cokr.xit.base.web.ApplicationController; import cokr.xit.fims.base.FimsUser; import cokr.xit.fims.cmmn.service.bean.StngBean; import cokr.xit.fims.cmmn.xls.FormatMaker; import cokr.xit.fims.cmmn.xls.StyleMaker; import cokr.xit.fims.crdn.Crdn; import cokr.xit.fims.crdn.CrdnQuery; import cokr.xit.fims.crdn.dao.CrdnInfoMapper; import cokr.xit.fims.crdn.dao.CrdnStngMapper; import cokr.xit.fims.crdn.service.CrdnService; import cokr.xit.fims.crdn.service.CrdnStngService; import cokr.xit.fims.mngt.service.bean.TaskBean; import cokr.xit.fims.sprt.Sprt; import cokr.xit.fims.sprt.service.bean.MediaBean; import cokr.xit.fims.task.Task; import cokr.xit.foundation.data.DataObject; /**단속 관리 서비스 웹 컨트롤러.
* {웹 컨텍스트}/crdn/crdn06 로 접근할 수 있다. * @author leebj */ @Controller @RequestMapping(name="단속 관리", value=Crdn06Controller.CLASS_URL) public class Crdn06Controller extends ApplicationController { public static final String CLASS_URL = "/crdn/crdn06"; public class METHOD_URL { public static final String crackdownManagementMain = "/010/main.do" , getCrackdownList = "/010/list.do" , removeCrackdown = "/010/remove.do" , removeCrackdownPayer = "/010/removeCrdnPayer.do" , countCrdn = "/010/nocs.do" , getCrackdownInfo = "/020/info.do" , updateCrackdown = "/020/update.do" , getCrackdownStatusInfo = "/030/info.do" , updateCrackdownStatus = "/030/update.do" ; } @Resource(name="crdnService") private CrdnService crdnService; @Resource(name="crdnStngService") private CrdnStngService crdnStngService; @Resource(name="userMapper") protected UserMapper userMapper; @Resource(name="crdnStngMapper") protected CrdnStngMapper crdnStngMapper; @Resource(name = "fileBean") private FileBean fileBean; @Resource(name = "stngBean") private StngBean stngBean; @Resource(name = "crdnInfoMapper") private CrdnInfoMapper crdnInfoMapper; @Resource(name = "mediaBean") private MediaBean mediaBean; @Resource(name = "fileService") private FileService fileService; @Resource(name = "taskBean") private TaskBean taskBean; /** 단속 관리 메인화면을 연다. * @return fims/crdn/crdn06010-main */ @RequestMapping(name="단속 관리 메인", value=METHOD_URL.crackdownManagementMain) public ModelAndView crackdownManagementMain(String openType, String taskSeCd) { Map> commonCodes = getCodesOf("FIM002", "FIM003", "FIM005", "FIM010", "FIM022", "FIM026", "FIM034", "FIM054"); ModelAndView mav = new ModelAndView("fims/crdn/crdn06010-main") .addObject("pageName", "crdn06010" + ifEmpty(openType, ()-> "")); if(!isEmpty(taskSeCd)) mav.addObject("taskSeCd", taskSeCd); mav.addObject("FIM003List", commonCodes.get("FIM003")) .addObject("FIM005List", commonCodes.get("FIM005")) .addObject("FIM010List", commonCodes.get("FIM010")) .addObject("FIM054List", commonCodes.get("FIM054")) .addObject("TaskListForSgg", stngBean.filterTaskSectionCodeForSgg(commonCodes.get("FIM054"))); return addCodes(commonCodes, mav, "FIM002", "FIM003", "FIM010", "FIM022", "FIM026", "FIM034"); } /**단속자료 목록을 조회한다.
* {@link CrdnService#getCrackdownList(CrdnQuery)} 참고 * @param query 단속자료 목록 조회 조건 * @return jsonView */ @Task @RequestMapping(name="단속자료 목록", value=METHOD_URL.getCrackdownList) public ModelAndView getCrackdownList(CrdnQuery query) { setFetchSize(query); FimsUser currentUser = (FimsUser) currentUser().getUser(); query.setSggCd(currentUser.getOrgID()); if("xls".equals(query.getDownload())) { List cellDefs = fromJson(query.getCellDefs(), CellDef.listType()); if("Y".equals(query.getIncludePhoto())) { cellDefs.add((new CellDef()).setLabel("사진1").setWidth(18).setField("CRDN_PHOTO_PATH1")); cellDefs.add((new CellDef()).setLabel("사진2").setWidth(18).setField("CRDN_PHOTO_PATH2")); } XLSWriter xlsx = new XLSWriter().worksheet(0); Format format = new Format(xlsx); Comment comment = new Comment(xlsx); CellStyle center = format.cellStyle(Style.CENTER); CellStyle left = format.cellStyle(Style.LEFT); CellStyle dateYMD = format.yyyy_mm_dd(); CellStyle dateDT = format.yyyy_mm_dd_hh_mm_ss(); Map valueMap = new HashMap(); for(CellDef def : cellDefs) { switch(def.getLabel()) { case "자료출처"->{ valueMap.put("자료출처", format.of("CRDN_INPT_SE_NM").style(center)); } case "차량번호"->{ valueMap.put("차량번호", left); } case "위반일시"->{ valueMap.put("위반일시", FormatMaker.yyyy_mm_dd_hh_mm_ss(format,"CRDN_YMD_TM").style(dateDT)); } case "단속장소"->{ valueMap.put("단속장소", left); } case "사진건수"->{ valueMap.put("사진건수", center); } case "스티커번호"->{ valueMap.put("스티커번호", left); } case "장애차량확인"->{ valueMap.put("장애차량확인", format.of("PRK_PSBLTY_RSLT_NM").style(center)); } case "처리상태"->{ valueMap.put("처리상태", format.of("CRDN_STTS_NM").style(center)); } case "제외사유"->{ valueMap.put("제외사유", format.of("LEVY_EXCL_RSN_NM").style(center)); } case "제외처리일자"->{ valueMap.put("제외처리일자", FormatMaker.yyyy_mm_dd(format,"LEVY_EXCL_YMD").style(dateYMD)); } case "제외내역"->{ valueMap.put("제외내역", left); } case "사진1"->{ valueMap.put("사진1", FormatMaker.photoCellForApproval(format, comment, "CRDN_PHOTO_PATH1")); } case "사진2"->{ valueMap.put("사진2", FormatMaker.photoCellForApproval(format, comment, "CRDN_PHOTO_PATH2")); } } } CellDef.setValues(cellDefs, valueMap); List list = crdnService.getCrackdownList(query.setFetchSize(0)); if(ifEmpty(query.getIncludePhoto(), () -> "").equals("Y")) { for(DataObject crdn : list) { String crdnId = crdn.string("CRDN_ID"); FileQuery fileQuery = new FileQuery(); fileQuery.setInfoType(Crdn.INF_TYPE); fileQuery.setInfoKeys(crdnId); List fileInfoList = fileBean.getFileList(fileQuery); if(fileInfoList != null && fileInfoList.size() > 0) { for(int j=0; (j < fileInfoList.size()) && (j < 2); j++) { crdn.set("CRDN_PHOTO_PATH"+(j+1), fileInfoList.get(j).string("FILE_PATH")); } } } } xlsx.cell(0, 0).value("단속자료 목록").value(center).merge(0, cellDefs.size()-1); xlsx.cell(3, 0).rowValues(CellDef.header(cellDefs, () -> StyleMaker.headerStyle(xlsx))); xlsx.cell(4, 0).values(list, CellDef.values(cellDefs.stream().map(i -> {if(i.getValue() instanceof Format) {i.setField(null);}; return i;}).toList())); ModelAndView mav = new ModelAndView("downloadView"); mav.addObject("download", xlsx.getDownloadable().setFilename("단속자료 목록.xlsx")); mav.addObject("downloadData", list); mav.addObject("dataNames", cellDefs.stream().map(CellDef::getLabel).toList()); return mav; } return setPagingInfo(new ModelAndView("jsonView"), crdnService.getCrackdownList(query),""); } /**지정한 단속 ID에 해당하는 단속 대장를 제거한다. * @param crdnID 단속 ID * @return jsonView *
 {
	 *     "affected": 저장된 정보수
	 *     "saved": 저장되었으면 true, 그렇지 않으면 false
	 * }
*/ @Task @RequestMapping(name="단속자료 삭제", value=METHOD_URL.removeCrackdown) public ModelAndView removeCrackdown(Crdn crdn) { boolean saved = false; String rtnMsg = crdnService.removeCrackdown(crdn); if (rtnMsg.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("rtnMsg", rtnMsg); } /**지정한 단속 ID에 해당하는 납부자 ID를 제거한다. * @param crdnID 단속 ID * @return jsonView *
 {
	 *     "affected": 저장된 정보수
	 *     "saved": 저장되었으면 true, 그렇지 않으면 false
	 * }
*/ @Task @RequestMapping(name="단속자료 납부자 삭제", value=METHOD_URL.removeCrackdownPayer) public ModelAndView removeCrackdownPayer(Crdn crdn) { boolean saved = false; String rtnMsg = crdnService.removeCrackdownPayer(crdn); if (rtnMsg.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("rtnMsg", rtnMsg); } /**지정한 조회조건으로 단속 건수를 반환한다. * @param CrdnQuery 조회조건 * @return jsonView */ @Task @RequestMapping(name="단속 건수 조회", value=METHOD_URL.countCrdn) public ModelAndView countCrdn(CrdnQuery crdnQuery) { ModelAndView mav = new ModelAndView("jsonView"); int crdnCount = crdnService.countCrdn(crdnQuery); mav.addObject("crdnCount", crdnCount); return mav; } /**지정한 ID의 단속 정보(info)를 반환한다. * @param query 단속 대장 조회 조건 * @return fims/crdn/crdn06020-info 또는 jsonView *
{
	 *     "crdnInfo": 단속 정보
	 * }
*/ @Task @RequestMapping(name="단속자료 상세 조회", value=METHOD_URL.getCrackdownInfo) public ModelAndView getCrackdownInfo(HttpServletRequest hReq, CrdnQuery query) { boolean json = jsonResponse(); ModelAndView mav = new ModelAndView(json ? "jsonView" : "fims/crdn/crdn06020-info"); // 법정동 FimsUser currentUser = (FimsUser) currentUser().getUser(); String sggCd = currentUser.getOrgID(); List stdgNmList = crdnStngMapper.selectStdgNmList(sggCd); mav.addObject("stdgNmList", stdgNmList); // 공통코드 - 위반 내역 코드 String taskSeCd = query.getTaskSeCd(); String vltnByTask = taskBean.getVltnCdGrp(sggCd, taskSeCd); Map> commonCodes = getCodesOf("CMN006", "FIM011","FIM053","LVS005",vltnByTask); mav.addObject("CMN006List", commonCodes.get("CMN006")) .addObject("FIM011List", commonCodes.get("FIM011")) .addObject("FIM053List", commonCodes.get("FIM053")) .addObject("LVS005List", commonCodes.get("LVS005")) .addObject("VLTNList", commonCodes.get(vltnByTask)); // 단속조 List teamList = crdnStngService.getTeamList(query); // 단속부가정보(TB_CRDN_ADI) 공통코드 String[] extraCodeGroups = taskBean.getExtraCdGrps(sggCd, taskSeCd); if (!isEmpty(extraCodeGroups)) { commonCodes = getCodesOf(extraCodeGroups); commonCodes.forEach((codeGroup, codes) -> { mav.addObject(codeGroup + "List", codes); }); } mav.addObject("TeamList", teamList); DataObject crdnInfo = crdnService.getCrackdownInfo(query); return mav .addObject("pageName", "crdn06020") // jsp pageName .addObject("prefixUrl", CLASS_URL) // prefixUrl .addObject("Info", json ? crdnInfo : toJson(crdnInfo)) ; } /**지정한 단속 ID에 해당하는 단속 대장를 수정한다. * @param crdnID 단속 ID * @return jsonView *
 {
	 *     "affected": 저장된 정보수
	 *     "saved": 저장되었으면 true, 그렇지 않으면 false
	 * }
*/ @Task @RequestMapping(name="단속자료 수정", value=METHOD_URL.updateCrackdown) public ModelAndView updateCrackdown(Crdn crdn) { boolean saved = false; String rtnMsg = crdnService.updateCrackdown(crdn); if (rtnMsg.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("rtnMsg", rtnMsg); } /**지정한 ID의 단속 처리 상태 정보(info)를 반환한다. * @param query 단속 대장 조회 조건 * @return fims/crdn/crdn06030-info 또는 jsonView *
{
	 *     "crdnInfo": 단속 정보
	 * }
*/ @Task @RequestMapping(name="단속자료 상태 조회", value=METHOD_URL.getCrackdownStatusInfo) public ModelAndView getCrackdownStatusInfo(HttpServletRequest hReq, CrdnQuery query) { DataObject crdnInfo = crdnService.getCrackdownInfo(query); Map> commonCodes = getCodesOf("FIM010"); boolean json = jsonResponse(); return new ModelAndView(json ? "jsonView" : "fims/crdn/crdn06030-info") .addObject("pageName", "crdn06030") // jsp pageName .addObject("prefixUrl", CLASS_URL) // prefixUrl .addObject("FIM010List", commonCodes.get("FIM010")) // 단속 처리 상태 코드(CRDN_STTS_CD) .addObject("Info", json ? crdnInfo : toJson(crdnInfo)) ; } /**지정한 단속 ID에 해당하는 단속 처리 상태를 수정한다. * @param crdnID 단속 ID * @return jsonView *
 {
	 *     "affected": 저장된 정보수
	 *     "saved": 저장되었으면 true, 그렇지 않으면 false
	 * }
*/ @Task @RequestMapping(name="단속처리상태 수정", value=METHOD_URL.updateCrackdownStatus) public ModelAndView updateCrackdownStatus(Crdn crdn) { boolean saved = false; String rtnMsg = crdnService.updateCrackdownStatus(crdn); if (rtnMsg.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("rtnMsg", rtnMsg); } @PostMapping(name= "단속 사진 추가", value = "/insertCrdnImageFile.do") public ModelAndView insertCrdnImageFile(String crdnId, int atchFileCnt, MultipartFile[] newFileList) { boolean saved = false; String retMessage = "[F] "; if(newFileList == null || newFileList.length == 0 || newFileList[0] == null || newFileList[0].isEmpty()) { throw new RuntimeException("파일 업로드 오류"); } Relation relation = new Relation().setInfoType(Crdn.INF_TYPE).setInfoKey(crdnId); List newFileInfoList = new FileInfoFactory().makeFileInfos(relation, newFileList); List> processList = new ArrayList<>(); int newFileSort = 999; for(FileInfo newFileInfo : newFileInfoList) { newFileInfo.setSortOrder(newFileSort++); processList.add(Map.of("process", "insert", "obj", newFileInfo)); } Crdn crdn = new Crdn(); crdn.setCrdnId(crdnId); crdn.setAtchFileCnt(atchFileCnt); retMessage = crdnService.changeCrdnImageFile(crdn, processList); if (retMessage.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("retMessage", retMessage); } @PostMapping(name= "단속 사진 수정", value = "/updateCrdnImageFile.do") public ModelAndView updateCrdnImageFile(String crdnId, int atchFileCnt, String beforeKey, int beforeOrder, MultipartFile modifyFile) { boolean saved = false; String retMessage = "[F] "; if(modifyFile == null || modifyFile.isEmpty()) { throw new RuntimeException("파일 업로드 오류"); } Relation relation = new Relation().setInfoType(Crdn.INF_TYPE).setInfoKey(crdnId); FileInfo modifyFileInfo = new FileInfoFactory().make(relation, modifyFile); modifyFileInfo.setSortOrder(beforeOrder); List> processList = new ArrayList<>(); processList.add(Map.of("process", "delete", "key", beforeKey)); processList.add(Map.of("process", "insert", "obj", modifyFileInfo)); Crdn crdn = new Crdn(); crdn.setCrdnId(crdnId); crdn.setAtchFileCnt(atchFileCnt); retMessage = crdnService.changeCrdnImageFile(crdn, processList); if (retMessage.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("retMessage", retMessage); } @PostMapping(name= "단속 사진 삭제", value = "/deleteCrdnImageFile.do") public ModelAndView deleteCrdnImageFile(String crdnId, int atchFileCnt, String[] deleteKeys) { boolean saved = false; String retMessage = "[F] "; if(deleteKeys == null || deleteKeys.length == 0 || deleteKeys[0] == null || deleteKeys[0].isEmpty()) { throw new RuntimeException("파일 삭제 오류"); } List> processList = new ArrayList<>(); for(String deleteKey : deleteKeys) { processList.add(Map.of("process", "delete", "key", deleteKey)); } Crdn crdn = new Crdn(); crdn.setCrdnId(crdnId); crdn.setAtchFileCnt(atchFileCnt); retMessage = crdnService.changeCrdnImageFile(crdn, processList); if (retMessage.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("retMessage", retMessage); } @PostMapping(name= "단속 사진 순서 변경", value = "/changeOrderCrdnImageFile.do") public ModelAndView changeOrderCrdnImageFile(String crdnId, int atchFileCnt, String[] orderedKeys) { boolean saved = false; String retMessage = "[F] "; if(orderedKeys == null || orderedKeys.length == 0 || orderedKeys[0] == null || orderedKeys[0].isEmpty()) { throw new RuntimeException("파일 순서 변경 오류"); } List> processList = new ArrayList<>(); for(String orderedKey : orderedKeys) { processList.add(Map.of("process", "order", "key", orderedKey)); } Crdn crdn = new Crdn(); crdn.setCrdnId(crdnId); crdn.setAtchFileCnt(atchFileCnt); retMessage = crdnService.changeCrdnImageFile(crdn, processList); if (retMessage.contains("[S]")) { saved = true; } else { saved = false; } return new ModelAndView("jsonView") .addObject("saved", saved) .addObject("retMessage", retMessage); } @RequestMapping(name= "단속 사진 목록", value = "/fileList.do") public ModelAndView getFileList(FileQuery req) { ModelAndView mav = new ModelAndView("jsonView"); String infoType = ifEmpty(req.getInfoType(), () -> ""); boolean singleKey = (req.getInfoKeys() != null && req.getInfoKeys().length == 1); //파일 목록 List fileInfoList = fileService.getFileList(req); for(DataObject fileInfo : fileInfoList) { List mosaicInfos = mediaBean.getMosaicList(fileInfo.string("FILE_ID")); if(mosaicInfos != null) { String mosaic = ""; for(int i=0; i < mosaicInfos.size(); i++) { DataObject mosaicInfo = mosaicInfos.get(i); if(i != 0) { mosaic += "|"; } mosaic += mosaicInfo.string("X_AXS") + "," + mosaicInfo.string("Y_AXS") + "," + mosaicInfo.string("MOSC_LEN") + "," + mosaicInfo.string("MOSC_HGT"); } fileInfo.set("MOSAIC", mosaic); } else { fileInfo.set("MOSAIC", ""); } } mav = setPagingInfo(mav, fileInfoList, "file"); //민원 동영상파일 첨부 여부 String cvlcptVideoExistYn = "N"; if(infoType.equals(Crdn.INF_TYPE) && singleKey) { DataObject dataObject = crdnInfoMapper.selectCrdnInfo(req.getInfoKeys()[0]); String linkTblNm = dataObject.string("LINK_TBL_NM"); if(!linkTblNm.equals("")) { //민원연계자료 FileQuery cvlcptFileQuery = new FileQuery(); if(linkTblNm.equals("TB_ESB_INTERFACE")) { cvlcptFileQuery.setInfoType("010"); } else if(linkTblNm.equals("TB_SAEOL_CVLCPT_DTL")) { cvlcptFileQuery.setInfoType("020"); } else { throw new RuntimeException("파일 조회 중 오류가 발생하였습니다."); } cvlcptFileQuery.setInfoKeys(dataObject.string("LINK_ID")); List linkFileList = fileBean.getFileList(cvlcptFileQuery); if(linkFileList != null && !linkFileList.isEmpty()) { for(int i=0; i < linkFileList.size(); i++) { String mimeType = linkFileList.get(i).string("MIME_TYPE"); if(Arrays.asList(Sprt.VIDEO_MIME_TYPE).contains(mimeType)) { cvlcptVideoExistYn = "Y"; } } } } } mav.addObject("cvlcptVideoExistYn", cvlcptVideoExistYn); return mav; } }