package com.pms.service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.SqlSession; import org.json.simple.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.pms.common.SqlMapConfig; import com.pms.common.bean.PersonBean; import com.pms.common.utils.CommonUtils; import com.pms.common.utils.Constants; import com.pms.common.utils.MailUtil; import com.pms.salesmgmt.service.SalesMngService; @Service public class ApprovalService { @Autowired CommonService commonService; @Autowired SalesMngService salesMngService; @Autowired PurchaseOrderService purchaseOrderService; /** *
	 * targetObjId를 통해 등록된 approval이 있는지 체크한다.
	 * 있다면 해당 approval object id를 리턴.
	 * 없다면 approval을 생성 후, object id를 리턴.
	 * 
	 * transaction 관리대상.
	 * 
* @param sqlSession * @param paramMap * @return approval의 object id * @throws Exception */ public String checkApprovalObjId(SqlSession sqlSession, Map paramMap)throws Exception{ String result = ""; Map map = sqlSession.selectOne("approval.selectApprovalInfo", paramMap); if(map != null) result = CommonUtils.checkNull(map.get("OBJID")); if("".equals(result)){ result = CommonUtils.createObjId(); paramMap.put("objId", result); paramMap.put("systemType", Constants.SYSTEM_NAME); sqlSession.insert("approval.insertApprovalInfo", paramMap); } paramMap.put("approvalObjId", result); return result; } public Map getLastApprovalInfo(SqlSession sqlSession, Map paramMap)throws Exception{ paramMap.put("search_type", "last"); Map map = sqlSession.selectOne("approval.selectApprovalInfo", paramMap); return map; } /** *
	 * Route 신규 생성
	 * 반려 후, 생성이 될 수 있으니 Approval의 상태값을 inProcess로 변경.
	 * paramMap의 approvalObjId가 필요함.
	 * 
	 * transaction 관리대상.
	 * 
* @param sqlSession * @param paramMap * @return route의 object id * @throws Exception */ public String createRouteInfo(SqlSession sqlSession, Map paramMap)throws Exception{ String result = ""; //1. Approval의 status를 inProcess로 변경. Map approvalParamMap = new HashMap(); approvalParamMap.put("approvalObjId", CommonUtils.checkNull(paramMap.get("approvalObjId"))); approvalParamMap.put("status", "inProcess"); sqlSession.update("approval.changeApprovalStatus", approvalParamMap); //2. route 생성 result = CommonUtils.checkNull(CommonUtils.createObjId()); paramMap.put("routeObjId", result); paramMap.put("systemType", Constants.SYSTEM_NAME); sqlSession.insert("approval.createRouteInfo", paramMap); return result; } public void createApprovalTagetInfo(SqlSession sqlSession, Map paramMap, String targetObjIdsArr [])throws Exception{ if(!CommonUtils.isEmpty(targetObjIdsArr) && targetObjIdsArr.length > 0) { Map dupCheckMap = new HashMap(); for (String targetObjId : targetObjIdsArr) { if(StringUtils.isNotBlank(targetObjId) && !dupCheckMap.containsKey(targetObjId)) { //중복제거 dupCheckMap.put(targetObjId, ""); //1. APPROVAL_TARGET 생성 String objid = CommonUtils.checkNull(CommonUtils.createObjId()); paramMap.put("objId", objid); paramMap.put("targetObjId", targetObjId); //paramMap.put("systemType", Constants.SYSTEM_NAME); sqlSession.insert("approval.createApprovalTagetInfo", paramMap); } } } } /** *
	 * Inboxtask 신규 생성
	 * 
	 * transaction 관리대상.
	 * 
* @param sqlSession * @param paramMap * @param normalArr * @param helpArr * @param refArr * @return * @throws Exception */ public boolean createInboxTask(SqlSession sqlSession, Map paramMap, List normalArr, List helpArr, List refArr)throws Exception{ boolean result = false; int idx = 0; for(String targetUserId : normalArr){ idx++; paramMap.put("inboxTaskObjId", CommonUtils.createObjId()); paramMap.put("seq", idx); paramMap.put("approvalType", "normal"); if(idx == 1){ paramMap.put("status", "ready"); //EO 결재 상신(최초) 시 결재구분 일반 중 첫번째 인원에게 메일을 발송한다. String targetType = CommonUtils.checkNull(paramMap.get("targetType")); System.out.println("createInboxTask(paramMap):"+paramMap); if("EO".equals(targetType)){ System.out.println("createInboxTask(idx):"+idx); System.out.println("createInboxTask(targetUserId):"+targetUserId); approvalEODistribute(sqlSession, paramMap,targetUserId); } }else{ paramMap.put("status", "standby"); } paramMap.put("targetUserId", targetUserId); sqlSession.insert("approval.createInboxTaskInfo", paramMap); } for(String targetUserId : helpArr){ if(!"null".equals(targetUserId)){ paramMap.put("inboxTaskObjId", CommonUtils.createObjId()); paramMap.put("seq", 0); paramMap.put("approvalType", "help"); paramMap.put("status", "ready"); paramMap.put("targetUserId", targetUserId); sqlSession.insert("approval.createInboxTaskInfo", paramMap); } } for(String targetUserId : refArr){ if(!"null".equals(targetUserId)){ paramMap.put("inboxTaskObjId", CommonUtils.createObjId()); paramMap.put("seq", 0); paramMap.put("approvalType", "ref"); paramMap.put("status", "complete"); paramMap.put("targetUserId", targetUserId); sqlSession.insert("approval.createInboxTaskInfo", paramMap); } } result = true; return result; } /** * 결재함 목록 조회 * @param paramMap * @return */ public ArrayList getApprovalList(HttpServletRequest request, Map paramMap){ ArrayList> resultList = new ArrayList(); SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(); try{ String countPerPage = CommonUtils.checkNull(request.getParameter("countPerPage"), Constants.ADMIN_COUNT_PER_PAGE+""); paramMap.put("COUNT_PER_PAGE", Integer.parseInt(countPerPage)); //접속자 정보 등록 HttpSession session = request.getSession(); PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); String connectUserId = CommonUtils.checkNull(person.getUserId()); paramMap.put("connectUserId", connectUserId); paramMap.put("systemType", Constants.SYSTEM_NAME); Map pageMap = (HashMap)sqlSession.selectOne("approval.selectApprovalListCnt", paramMap); pageMap = (HashMap)CommonUtils.setPagingInfo(request, pageMap); System.out.println("pageMap : "+pageMap); paramMap.put("PAGE_END", CommonUtils.checkNull(pageMap.get("PAGE_END"))); paramMap.put("PAGE_START", CommonUtils.checkNull(pageMap.get("PAGE_START"))); resultList = (ArrayList)sqlSession.selectList("approval.selectApprovalList", paramMap); }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } return CommonUtils.toUpperCaseMapKey(resultList); } /** * approvalObjId를 통해 route 목록을 조회한다. * @param paramMap * @return */ public List getRouteList(Map paramMap){ List resultList = new ArrayList(); SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(); try{ resultList = (ArrayList)sqlSession.selectList("approval.getRouteList", paramMap); }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } return resultList; } /** * routeObjId를 통해 route 정보를 조회한다. * @param paramMap * @return */ public Map getRouteInfo(Map paramMap){ Map resultMap = new HashMap(); SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(); try{ resultMap = (HashMap)sqlSession.selectOne("approval.getRouteInfo", paramMap); }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } return resultMap; } /** * route별 inboxtask 목록을 조회한다. * @param paramMap * @return */ public List getInboxtaskList(Map paramMap){ List resultList = new ArrayList(); SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(); try{ resultList = (ArrayList)sqlSession.selectList("approval.selectInboxtaskList", paramMap); }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } return resultList; } /** * 담당자 결재 처리 * @param sqlSession * @param paramMap */ public void setApprovalResult(SqlSession sqlSession, Map paramMap){ String result = CommonUtils.checkNull(paramMap.get("result")); String status = ""; if("Y".equals(result)) status = "complete"; else if("N".equals(result)) status = "reject"; else status = "cancel"; paramMap.put("status", status); System.out.println("setApprovalResult.paramMap : "+paramMap); sqlSession.update("approval.setInboxtaskResult", paramMap); //다음순번의 결재자에게 메일발송 (개발필요) 반려가 되었을경우는 다른 함수에서 처리. } /** * 승인일 경우 다음 결재자가 있는지 확인 후, 다음 결재자의 상태를 ready로 변경한다. * @param sqlSession * @param paramMap */ public void changeNextApprovalStatus(SqlSession sqlSession, Map paramMap){ int nextSeq = Integer.parseInt(CommonUtils.checkNull(paramMap.get("seq"), "0"))+1; paramMap.put("nextSeq", nextSeq); Map map = sqlSession.selectOne("approval.getNextApprovalObjId", paramMap); map = CommonUtils.toUpperCaseMapKey(map); System.out.println("changeNextApprovalStatus(map):"+map); if(map != null && !map.isEmpty()){ String nextInboxtaskObjId = CommonUtils.checkNull(map.get("INBOXTASK_OBJID")); sqlSession.update("approval.setNextInboxtaskStatus", nextInboxtaskObjId); Map targetMap = sqlSession.selectOne("approval.getTargetType", paramMap); String targetType = CommonUtils.checkNull(targetMap.get("TARGET_TYPE")); String nextUserId = CommonUtils.checkNull(map.get("TARGET_USER_ID")); String targetObjId = CommonUtils.checkNull(map.get("TARGET_OBJID")); String sendEmail = CommonUtils.checkNull(map.get("EMAIL")); System.out.println("changeNextApprovalStatus(targetMap):"+targetMap); String mailTitle = ""; if("EO".equals(targetType)){ HashMap eoParamMap = new HashMap(); eoParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); eoParamMap.put("targetObjId", targetObjId); eoParamMap.put("status", "ready"); approvalEODistribute(sqlSession, eoParamMap, nextUserId); }else if("EXPENSE_APPLY".equals(targetType)){ //경비신청 mailTitle = "[경비신청서 결재요청] 1건이 발생했습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", nextUserId, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("ISSUE_RELEASE".equals(targetType)){ //통합문제점 mailTitle = "[문제점개선대책서 결재요청] 1건이 발생했습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", nextUserId, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("MATERIAL_APPLY".equals(targetType)){ //메일발송 mailTitle = "[발주서 결재요청] 1건이 발생했습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", nextUserId, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("MATERIAL_SORTAPPLY".equals(targetType)){ //메일발송 mailTitle = "[발주서 결재요청] 1건이 발생했습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", nextUserId, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); } } } /** * 승인일 경우 다음 결재자가 있는지 확인 후, 다음 결재자에게 메일을 발송한다. * @param sqlSession * @param paramMap */ public void SendMailNextApproval(SqlSession sqlSession, Map paramMap){ int nextSeq = Integer.parseInt(CommonUtils.checkNull(paramMap.get("seq"), "0"))+1; paramMap.put("nextSeq", nextSeq); Map map = sqlSession.selectOne("approval.getNextApprovalObjId", paramMap); System.out.println("changeNextApprovalStatus(map):"+map); if(map != null && !map.isEmpty()){ String nextInboxtaskObjId = CommonUtils.checkNull(map.get("INBOXTASK_OBJID")); sqlSession.update("approval.setNextInboxtaskStatus", nextInboxtaskObjId); Map targetMap = sqlSession.selectOne("approval.getTargetType", paramMap); String targetType = CommonUtils.checkNull(targetMap.get("TARGET_TYPE")); String nextUserId = CommonUtils.checkNull(map.get("TARGET_USER_ID")); String targetObjId = CommonUtils.checkNull(map.get("TARGET_OBJID")); //EO 경우 다음 결재진행자에게 EO 갑지내용으로 메일을 발송한다. System.out.println("changeNextApprovalStatus(targetMap):"+targetMap); if("EO".equals(targetType)){ HashMap eoParamMap = new HashMap(); eoParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); eoParamMap.put("targetObjId", targetObjId); eoParamMap.put("status", "ready"); approvalEODistribute(sqlSession, eoParamMap, nextUserId); } } } /** * Route의 모든 결재자가 결재처리되었는지 확인 후, Route의 상태를 complete로 변경한다. * approval도 종결시킨다. * @param sqlSession * @param paramMap */ public void completeRouteInfo(SqlSession sqlSession, Map paramMap){ Map map = sqlSession.selectOne("approval.getNotCompleteInboxtaskCnt", paramMap); map = CommonUtils.toUpperCaseMapKey(map); int cnt = Integer.parseInt(CommonUtils.checkNull(map.get("CNT"), "0")); //ready나 standby인 상태값이 하나도 없다면 route, approval을 종결시킨다. if(cnt == 0){ Map sqlParamMap = new HashMap(); sqlParamMap.put("completeStatus", "complete"); sqlParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); sqlSession.update("approval.completeRoute", sqlParamMap); //approval 종결 sqlSession.update("approval.completeApproval", paramMap); HashMap routeSqlParamMap = new HashMap(); routeSqlParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); Map routeMap = sqlSession.selectOne("approval.getRouteInfo", routeSqlParamMap); routeMap = CommonUtils.toUpperCaseMapKey(routeMap); //targetType을 가져와서 상태값 처리(PDM은 EO밖에 없음.) Map targetMap = sqlSession.selectOne("approval.getTargetType", paramMap); targetMap = CommonUtils.toUpperCaseMapKey(targetMap); String targetType = CommonUtils.checkNull(targetMap.get("TARGET_TYPE")); String targetObjId = CommonUtils.checkNull(targetMap.get("TARGET_OBJID")); String writer = CommonUtils.checkNull(routeMap.get("WRITER")); String sendEmail = CommonUtils.checkNull(routeMap.get("EMAIL")); String mailTitle = ""; //route와 approval이 종결되었다고 알림메일 발송(개발필요) if("EO".equals(targetType)){ //EO targetMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); targetMap.put("resultMessage", CommonUtils.checkNull(paramMap.get("resultMessage"))); targetMap.put("status", "release"); targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeEOStatus", targetMap); approvalEODistribute(sqlSession, targetMap, writer); }else if("PROBLEM".equals(targetType)){ //통합문제점 targetMap.put("status", "release"); targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeProblemApprovalStatus", targetMap); }else if("EXPENSE_APPLY".equals(targetType)){ //경비신청 mailTitle = "[경비신청서 결재완료]결재가 완료 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("ISSUE_RELEASE".equals(targetType)){ //통합문제점 targetMap.put("status", "WPS01100"); targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeIssueMgmtApprovalStatus", targetMap); mailTitle = "[문제점개선대책서 결재완료]결재가 완료 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("MATERIAL_APPLY".equals(targetType)){ //발주서작성 Map materMap = sqlSession.selectOne("approval.getmaterstatus", targetMap); String STATUS_CD = CommonUtils.checkNull(materMap.get("STATUS_CD")); if("PURSTCD00200".equals(STATUS_CD)){ targetMap.put("status", "PURSTCD00300"); }else if("PURSTCD00500".equals(STATUS_CD)){ targetMap.put("status", "PURSTCD00600"); } targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeMaterApprovalStatus", targetMap); mailTitle = "[발주서 결재완료]결재가 완료 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("MATERIAL_SORTAPPLY".equals(targetType)){ //발주서작성 targetMap.put("status", "PURSTCD00600"); targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeMaterApprovalStatus", targetMap); mailTitle = "[발주서 결재완료]결재가 완료 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("USED_MNG".equals(targetType)){ //중고관리 targetMap.put("targetObjId", targetObjId); targetMap.put("statusName", "결재완료"); targetMap.put("statusCommCD", Constants.USED_MNG_STATUS_CD); sqlSession.update("approval.changeUsedMngApprovalStatus", targetMap); }else if("CUSTOMER_MNG".equals(targetType)){ //중고관리 targetMap.put("targetObjId", targetObjId); targetMap.put("statusName", "결재완료"); targetMap.put("statusCommCD", Constants.CUSTOMER_MNG_STATUS_CD); sqlSession.update("approval.changeCustomerMngApprovalStatus", targetMap); }else if("CHECK_REPORT_MNG".equals(targetType)){ //검수관리 targetMap.put("targetObjId", targetObjId); targetMap.put("status", "approvalComplete"); sqlSession.update("approval.checkReportMngApprovalStatus", targetMap); }else if("EO_MNG".equals(targetType)){ //EO 등록 targetMap.put("targetObjId", targetObjId); targetMap.put("status", "approvalComplete"); targetMap.put("writer", writer); sqlSession.update("approval.eoMngApprovalStatus", targetMap); // 결제완료시 eo mng 의 reg date를 now()로 업데이트 , eo date sqlSession.update("eoMng.changeEOEDITDate", targetMap); // 결제완료시 part mng 의 eo를 현재 편집중인 eo로 업데이트 , eo date sqlSession.update("eoMng.changePartEO", targetMap); }else if("MOLD_DEV_REQUEST".equals(targetType)){ //금형제작의뢰 targetMap.put("targetObjId", targetObjId); targetMap.put("status", "approvalComplete"); sqlSession.update("approval.moldDevRequestApprovalStatus", targetMap); }else if("ECR_MNG".equals(targetType)){ //ECR sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000102"); sqlSession.update("approval.EcrMngApprovalStatus", sqlParamMap); }else if("AS_MNG".equals(targetType)){ //ECR sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000102"); sqlSession.update("approval.ASMngApprovalStatus", sqlParamMap); }else if("CSM".equals(targetType)){ //customer_service_mgmt sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000102"); sqlSession.update("approval.CSMApprovalStatus", sqlParamMap); }else if("SALES_REQUEST".equals(targetType)){ //구매의뢰 sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "approvalComplete"); sqlSession.update("approval.salesRequestApprovalStatus", sqlParamMap); salesMngService.afterApprovalCompleteSalesRequest(sqlSession, sqlParamMap); }else if("PURCHASE_ORDER".equals(targetType)){ //발주 sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "approvalComplete"); sqlSession.update("approval.purchaseOrderApprovalStatus", sqlParamMap); purchaseOrderService.afterApprovalCompleteRouteInfo(sqlSession, routeMap, targetMap, sqlParamMap); //동시발주 관련 메일 N건 발송 처리 추가(240109) // =>메인 1건만 나가는거로 변경되서 주석처리 /* List multiMasterList = new ArrayList(); paramMap.put("MULTI_MASTER_OBJID", targetObjId); multiMasterList = commonService.selectList("purchaseOrder.selectPurchaseOrderMasterList", null, paramMap); if(CommonUtils.isNotEmpty(multiMasterList) && !multiMasterList.isEmpty()) { for (Object object : multiMasterList) { Map mapInfo = (Map)object; sqlParamMap.put("targetObjId", mapInfo.get("OBJID")); //sqlParamMap.put("status", "approvalComplete"); purchaseOrderService.afterApprovalCompleteRouteInfo(sqlSession, routeMap, targetMap, sqlParamMap); } } */ }else if("DEFECT_ACTION".equals(targetType)){ //부적합품 통보서 } } } /** * Route의 상태를 reject로 변경한다. * @param sqlSession * @param paramMap */ public void rejectRouteInfo(SqlSession sqlSession, Map paramMap){ Map sqlParamMap = new HashMap(); sqlParamMap.put("completeStatus", "reject"); sqlParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); //Route를 반려오 상태를 변경한다. sqlSession.update("approval.completeRoute", sqlParamMap); //Route에 해당하는 정보를 가져온다. HashMap routeInfoMap = new HashMap(); routeInfoMap = (HashMap)sqlSession.selectOne("approval.getRouteInfo", sqlParamMap); String sendEmail = CommonUtils.checkNull(routeInfoMap.get("EMAIL")); //Route에 해당하는 상신인원 정보 String writer = CommonUtils.checkNull(routeInfoMap.get("WRITER")); //반려 시 작성된 Comment String rejectComment = CommonUtils.checkNull(paramMap.get("resultMessage")); //targetType, targetObjectId을 가져와서 상태값 처리(PDM은 EO밖에 없음.) Map targetMap = sqlSession.selectOne("approval.getTargetType", paramMap); targetMap = CommonUtils.toUpperCaseMapKey(targetMap); String targetType = CommonUtils.checkNull(targetMap.get("TARGET_TYPE")); String targetObjId = CommonUtils.checkNull(targetMap.get("TARGET_OBJID")); String mailTitle =""; targetMap.put("routeObjId", CommonUtils.checkNull(routeInfoMap.get("ROUTE_OBJID"))); targetMap.put("status", "reject"); targetMap.put("targetObjId", targetObjId); if("EO".equals(targetType)){ //상태값을 reject(반려)로 변경한다. sqlSession.update("approval.changeEOStatus", targetMap); targetMap.put("resultMessage", rejectComment); //상신자에게 반려되었다는 알림메일 발송 approvalEODistribute(sqlSession, targetMap, writer); }else if("PROBLEM".equals(targetType)){ //상태값을 reject(반려)로 변경한다. sqlSession.update("approval.changeProblemApprovalStatus", targetMap); }else if("DESIGN_CHECK_LIST".equals(targetType)){ //상태값을 reject(반려)로 변경한다. sqlSession.update("approval.changeDesignCheckListApprovalStatus", targetMap); }else if("MATERIAL_APPLY".equals(targetType)){ //발주 Map materMap = sqlSession.selectOne("approval.getmaterstatus", targetMap); String STATUS_CD = CommonUtils.checkNull(materMap.get("STATUS_CD")); if("PURSTCD00200".equals(STATUS_CD)){ targetMap.put("status", "PURSTCD00100"); }else if("PURSTCD00500".equals(STATUS_CD)){ targetMap.put("status", "PURSTCD00400"); } targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeMaterApprovalStatus", targetMap); mailTitle = "[발주서 반려알림]결재가 반려 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("EXPENSE_APPLY".equals(targetType)){ //경비 mailTitle = "[경비신청서 반려알림]결재가 반려 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("ISSUE_RELEASE".equals(targetType)){ //통합문제점 mailTitle = "[문제점개선대책서 반려알림]결재가 반려 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("MATERIAL_SORTAPPLY".equals(targetType)){ //발주 targetMap.put("status", "PURSTCD00100"); targetMap.put("targetObjId", targetObjId); sqlSession.update("approval.changeMaterApprovalStatus", targetMap); mailTitle = "[발주서 반려알림]결재가 반려 되었습니다."; MailUtil.sendMail("plm_admin", "master@hongsungeng.co.kr", writer, sendEmail, "", "", "", mailTitle, mailTitle, "ISSUE_RELEASE"); }else if("USED_MNG".equals(targetType)){ //중고관리 targetMap.put("targetObjId", targetObjId); targetMap.put("statusName", "반려"); targetMap.put("statusCommCD", Constants.USED_MNG_STATUS_CD); sqlSession.update("approval.changeUsedMngApprovalStatus", targetMap); }else if("CUSTOMER_MNG".equals(targetType)){ //중고관리 targetMap.put("targetObjId", targetObjId); targetMap.put("statusName", "반려"); targetMap.put("statusCommCD", Constants.CUSTOMER_MNG_STATUS_CD); sqlSession.update("approval.changeCustomerMngApprovalStatus", targetMap); }else if("CHECK_REPORT_MNG".equals(targetType)){ //검수관리 targetMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); targetMap.put("status", "reject"); sqlSession.update("approval.checkReportMngApprovalStatus", targetMap); }else if("EO_MNG".equals(targetType)){ //검수관리 targetMap.put("targetObjId", targetObjId); targetMap.put("status", "reject"); sqlSession.update("approval.eoMngApprovalStatus", targetMap); }else if("MOLD_DEV_REQUEST".equals(targetType)){ //금형제작의뢰 targetMap.put("targetObjId", targetObjId); targetMap.put("status", "reject"); sqlSession.update("approval.moldDevRequestApprovalStatus", targetMap); }else if("ECR_MNG".equals(targetType)){ //ECR sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000107"); sqlSession.update("approval.EcrMngApprovalStatus", sqlParamMap); }else if("AS_MNG".equals(targetType)){ //ECR sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000107"); sqlSession.update("approval.ASMngApprovalStatus", sqlParamMap); }else if("CSM".equals(targetType)){ //customer_service_mgmt sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "0000107"); sqlSession.update("approval.CSMApprovalStatus", sqlParamMap); }else if("SALES_REQUEST".equals(targetType)){ //구매의뢰 sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "reject"); sqlSession.update("approval.salesRequestApprovalStatus", sqlParamMap); }else if("PURCHASE_ORDER".equals(targetType)){ //구매의뢰 sqlParamMap.put("targetObjId", targetObjId); sqlParamMap.put("status", "reject"); sqlSession.update("approval.purchaseOrderApprovalStatus", sqlParamMap); } } /** * 이전 결재자가 반려를 했기때문에, 대기상태의 모든 inboxtask를 cancel로 변경시킨다. * @param sqlSession * @param paramMap */ public void setInboxtaskCancel(SqlSession sqlSession, Map paramMap){ //반려가 되었기때문에 남은 인원에 대하여 반려알림 메일발송 (개발필요) sqlSession.update("approval.cancelInboxtask", paramMap); } /** * 결재상신시 target의 상태값을 변경한다. * @param sqlSession * @param paramMap */ public void setTargetStatus(SqlSession sqlSession, Map paramMap){ String targetType = CommonUtils.checkNull(paramMap.get("targetType")); if("EO".equals(targetType)){ //상태값을 complete로 변경한다. Map sqlParamMap = new HashMap(); sqlParamMap.put("status", "approval"); sqlParamMap.put("TARGET_OBJID", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlSession.update("approval.changeEOStatus", sqlParamMap); }else if("PROBLEM".equals(targetType)){ //결재상태를 create로 입력한다. Map sqlParamMap = new HashMap(); sqlParamMap.put("status", "approval"); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); sqlSession.update("approval.changeProblemApprovalStatus", sqlParamMap); }else if("DESIGN_CHECK_LIST".equals(targetType)){ //결재상태를 create로 입력한다. Map sqlParamMap = new HashMap(); sqlParamMap.put("status", "approval"); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("routeObjId", CommonUtils.checkNull(paramMap.get("routeObjId"))); sqlSession.update("approval.changeDesignCheckListApprovalStatus", sqlParamMap); }else if("ISSUE_RELEASE".equals(targetType)){ //통합문제점 Map sqlParamMap = new HashMap(); sqlParamMap.put("status", "WPS01000"); sqlParamMap.put("targetObjId",CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlSession.update("approval.changeIssueMgmtApprovalStatus", sqlParamMap); }else if("USED_MNG".equals(targetType)){ //중고관리 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("statusName", "결재중"); sqlParamMap.put("statusCommCD", Constants.USED_MNG_STATUS_CD); sqlSession.update("approval.changeUsedMngApprovalStatus", sqlParamMap); }else if("CUSTOMER_MNG".equals(targetType)){ //중고관리 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("statusName", "결재중"); sqlParamMap.put("statusCommCD", Constants.CUSTOMER_MNG_STATUS_CD); sqlSession.update("approval.changeCustomerMngApprovalStatus", sqlParamMap); }else if("CHECK_REPORT_MNG".equals(targetType)){ //검수관리 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "approvalRequest"); sqlSession.update("approval.checkReportMngApprovalStatus", sqlParamMap); }else if("EO_MNG".equals(targetType)){ //검수관리 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "approvalRequest"); sqlSession.update("approval.eoMngApprovalStatus", sqlParamMap); }else if("MOLD_DEV_REQUEST".equals(targetType)){ //금형제작의뢰 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "approvalRequest"); sqlSession.update("approval.moldDevRequestApprovalStatus", sqlParamMap); }else if("ECR_MNG".equals(targetType)){ //금형제작의뢰 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "0000101"); sqlSession.update("approval.EcrMngApprovalStatus", sqlParamMap); }else if("AS_MNG".equals(targetType)){ //금형제작의뢰 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "0000101"); sqlSession.update("approval.ASMngApprovalStatus", sqlParamMap); }else if("CSM".equals(targetType)){ //customer_service_mgmt Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "0000101"); sqlSession.update("approval.CSMApprovalStatus", sqlParamMap); }else if("SALES_REQUEST".equals(targetType)){ //구매의뢰 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "approvalRequest"); sqlSession.update("approval.salesRequestApprovalStatus", sqlParamMap); }else if("PURCHASE_ORDER".equals(targetType)){ //구매의뢰 Map sqlParamMap = new HashMap(); sqlParamMap.put("targetObjId", CommonUtils.checkNull(paramMap.get("targetObjId"))); sqlParamMap.put("status", "approvalRequest"); sqlSession.update("approval.purchaseOrderApprovalStatus", sqlParamMap); } } /** * 결재상신 후 EO 배포처에 해당하는 인원들에게 EO 갑지내용을 배포한다. * type : approval(결재 상신 시 1번째 인원 또는 다음 결재인원에게 메일 발송) * type : release(모든 인원이 결재 완료하여 배포처 및 결재상신 인원에게 메일발송) * @param sqlSession * @param paramMap * @param type */ public void approvalEODistribute(SqlSession sqlSession, Map paramMap,String userId){ ArrayList distributeMemberList = new ArrayList(); ArrayList connectedPartList = new ArrayList(); ArrayList connectedDrawPartList = new ArrayList(); HashMap eoInfoMap = new HashMap(); System.out.println("approvalEODistribute(paramMap):"+paramMap); System.out.println("approvalEODistribute(userId):"+userId); //EO의 ObjectId String targetObjid = CommonUtils.checkNull(paramMap.get("targetObjId")); //Route의 ObjectId String routeObjId = CommonUtils.checkNull(paramMap.get("routeObjId")); String status = CommonUtils.checkNull(paramMap.get("status")); if(!"".equals(targetObjid)){ //EO 정보를 가져온다. HashMap eoSqlMap = new HashMap(); eoSqlMap.put("objId", targetObjid); eoInfoMap = sqlSession.selectOne("eo.getEOInfo",eoSqlMap); //EO에 연결된 정보를 가져온다. connectedPartList = (ArrayList)sqlSession.selectList("eo.getConnectPartList", eoSqlMap); eoSqlMap.put("drawingType", "draw"); connectedDrawPartList = (ArrayList)sqlSession.selectList("eo.getConnectPartList", eoSqlMap); String eoNo = CommonUtils.checkNull(eoInfoMap.get("EO_NO")); String eoDate = CommonUtils.checkNull(eoInfoMap.get("EO_ISSUE_DATE")); String carName = CommonUtils.checkNull(eoInfoMap.get("CAR_NAME")); String carCode = CommonUtils.checkNull(eoInfoMap.get("CAR_CODE")); //결재 상신 후 결재 순으로 인원에게 메일발송 if("ready".equals(status) || "complete".equals(status)){ //제목에 사용할 EO정보 String mailSubject = "[EO 결재요청] "+carCode+"_"+eoNo+"("+eoDate+")_"+connectedDrawPartList.size()+"건"; HashMap userSqlMap = new HashMap(); userSqlMap.put("userId",userId); System.out.println("approvalEODistribute(userSqlMap):"+userSqlMap); HashMap userMap = sqlSession.selectOne("admin.selectUserInfo", userSqlMap); String userEmail = CommonUtils.checkNull(userMap.get("EMAIL")); HashMap routeMap = (HashMap)getRouteInfo(paramMap); String routeTitle = ""; String writer = ""; String comment = ""; if(null == routeMap || routeMap.isEmpty()){ routeTitle = CommonUtils.checkNull(paramMap.get("approvalTitle")); HashMap writerSqlMap = new HashMap(); writerSqlMap.put("userId",CommonUtils.checkNull(paramMap.get("writer"))); HashMap writerMap = sqlSession.selectOne("admin.selectUserInfo", writerSqlMap); writer = CommonUtils.checkNull(writerMap.get("DEPT_NAME"))+" "+CommonUtils.checkNull(writerMap.get("USER_NAME")); comment = CommonUtils.checkNull(paramMap.get("approvalDescription")); }else{ routeTitle = CommonUtils.checkNull(routeMap.get("APPROVAL_TITLE")); writer = CommonUtils.checkNull(routeMap.get("WRITER_DEPT_NAME"))+" "+CommonUtils.checkNull(routeMap.get("WRITER_USER_NAME")); comment = CommonUtils.checkNull(routeMap.get("APPROVAL_DESC")); } //결재 상신 시 문구 HashMap mailMap = new HashMap(); mailMap.put("approvalType", "EO"); mailMap.put("routeTitle", routeTitle); mailMap.put("approvalUser", writer); mailMap.put("comment", comment); mailMap.put("userType", "상신자"); mailMap.put("mailUrl", Constants.SYSTEM_URL); String mailContents = MailUtil.getHTMLContents("eoApprovalMailTemplate", mailMap); System.out.println("approvalEODistribute(status):"+status); System.out.println("approvalEODistribute(userEmail):"+userEmail); System.out.println("approvalEODistribute(mailContents):"+mailContents); System.out.println("approvalEODistribute(mailSubject):"+mailSubject); MailUtil.sendMail(CommonUtils.checkNull(paramMap.get("writer")), "bestcw8388@iljitech.co.kr", userId, userEmail, "", "", "", mailSubject, mailContents, Constants.MAIL_TYPE_RELEASE_EO); MailUtil.sendMail(CommonUtils.checkNull(paramMap.get("writer")), "", userId, "don38317@gmail.com", "", "", "", mailSubject, mailContents, Constants.MAIL_TYPE_RELEASE_EO); //결재 인원 모두 결재 완료된 경우 }else if("release".equals(status)){ HashMap mailMap = new HashMap(); mailMap.put("oem", CommonUtils.checkNull(eoInfoMap.get("OEM_NAME"))); mailMap.put("car", CommonUtils.checkNull(eoInfoMap.get("CAR_CODE"))); mailMap.put("eoType", CommonUtils.checkNull(eoInfoMap.get("EO_TYPE_STR"))); mailMap.put("designTeam", CommonUtils.checkNull(eoInfoMap.get("DESIGN_TEAM"))); mailMap.put("eoNo", CommonUtils.checkNull(eoInfoMap.get("EO_NO"))); mailMap.put("eoDate", CommonUtils.checkNull(eoInfoMap.get("EO_ISSUE_DATE"))); mailMap.put("urgentDegree", CommonUtils.checkNull(eoInfoMap.get("URGENT_DEGREE_STR"))); mailMap.put("hkmcDate", CommonUtils.checkNull(eoInfoMap.get("HKMC_DISTRIBUTE_DATE"))); mailMap.put("approvalDesc", CommonUtils.checkNull(paramMap.get("approvalDescription"))); if(0 < connectedDrawPartList.size()){ String appendHtlm = ""; for(int i=0;i"; appendHtlm += " "+partNo+""; appendHtlm += " "+partName+""; appendHtlm += " "+changeItems+""; appendHtlm += " "+rev+""; appendHtlm += " "+ecdFlag+""; appendHtlm += " "+mngItemFlag+""; appendHtlm += " "+applyPointName+""; appendHtlm += ""; } if("".equals(appendHtlm)){ appendHtlm += ""; appendHtlm += " 연결된 파트 정보가 없습니다."; appendHtlm += ""; } //파트에 해당하는 영역에 Part 정보를 append 한다. mailMap.put("connectedPartList", appendHtlm); } //모든 결재 완료 시 문구 //제목에 사용할 EO정보 String mailSubject = "[EO 결재완료] "+carCode+"_"+eoNo+"("+eoDate+")_"+connectedDrawPartList.size()+"건"; HashMap approvalMap = new HashMap(); approvalMap.put("objId", targetObjid); ArrayList eoApprovalList = (ArrayList)sqlSession.selectList("eo.getEOApprovalList",approvalMap); String approvalMembers = ""; for(int j=0;j"; approvalMembers+=""+deptName+""; approvalMembers+=""+memberName+""; approvalMembers+=""; } mailMap.put("approvalMembers", approvalMembers); HashMap distributeSqlMap = new HashMap(); distributeSqlMap.put("targetObjId", targetObjid); distributeMemberList = (ArrayList)sqlSession.selectList("approval.getEODistributeMemberList", distributeSqlMap); String releaseMembers = ""; for(int k=0;k resultMap = new HashMap(); SqlSession sqlSession = null; try{ sqlSession = SqlMapConfig.getInstance().getSqlSession(); String userId = CommonUtils.checkNull(paramMap.get("userId")); System.out.println("userId : "+userId); if(!"".equals(userId)){ Map sqlParamMap = new HashMap(); sqlParamMap.put("userId", userId); sqlParamMap.put("systemType", "PMS"); resultMap = sqlSession.selectOne("approval.getApprovalCnt", sqlParamMap); } }catch(Exception e){ e.printStackTrace(); }finally{ sqlSession.close(); } return CommonUtils.toUpperCaseMapKey(resultMap); } /** * Amaranth10 전자결재 건수 조회 * 세션에서 empseq를 가져와 서버 인증으로 직접 결재함 조회 * @param request * @param paramMap * @return */ public Map getAmaranthApprovalCnt(HttpServletRequest request, Map paramMap){ Map resultMap = new HashMap(); try{ // 파라미터에서 empseq 가져오기 (header.jsp에서 전달) String empSeq = CommonUtils.checkNull(paramMap.get("empseq")); String userId = CommonUtils.checkNull(paramMap.get("userId")); String compSeq = "1000"; // 회사 시퀀스 System.out.println("=== Amaranth 결재 건수 조회 ==="); System.out.println("userId: " + userId); System.out.println("empSeq: " + empSeq); // empSeq가 비어있으면 에러 처리 if(empSeq == null || empSeq.isEmpty()){ System.err.println("empSeq가 비어있습니다. LoginId 업데이트 배치를 먼저 실행하세요."); resultMap.put("CNT", "0"); return CommonUtils.toUpperCaseMapKey(resultMap); } // Amaranth10 결재함 조회 (서버 인증 - 인증 토큰 불필요) com.pms.api.AmaranthApprovalApiClient apiClient = new com.pms.api.AmaranthApprovalApiClient(); String baseUrl = "https://erp.rps-korea.com"; String boxListJson = apiClient.getApprovalBoxListDirect(baseUrl, empSeq, compSeq); // 미결 건수 추출 (boxCode = "20") int pendingCnt = extractPendingCount(boxListJson); resultMap.put("CNT", String.valueOf(pendingCnt)); resultMap.put("AMARANTH_CNT", String.valueOf(pendingCnt)); System.out.println("Amaranth 미결 건수: " + pendingCnt); }catch(Exception e){ System.err.println("Amaranth 결재 건수 조회 오류: " + e.getMessage()); e.printStackTrace(); resultMap.put("CNT", "0"); resultMap.put("ERROR", e.getMessage()); } return CommonUtils.toUpperCaseMapKey(resultMap); } /** * JSON에서 미결 건수 추출 (boxCode = "20" 미결문서) * 응답 구조: resultData.result.boxList[].boxCode, docCnt */ private int extractPendingCount(String jsonResponse){ int count = 0; try { System.out.println("=== 미결 건수 파싱 시작 ==="); System.out.println("응답 내용: " + jsonResponse); // boxCode "20" 찾기 (미결문서) // "boxCode":"20" 또는 "boxCode": "20" 형태 int searchFrom = 0; while(true) { int boxCodeIndex = jsonResponse.indexOf("\"boxCode\"", searchFrom); if(boxCodeIndex == -1) break; // "boxCode" 뒤의 값 추출 int colonIndex = jsonResponse.indexOf(":", boxCodeIndex + 9); if(colonIndex == -1) break; int valueStart = jsonResponse.indexOf("\"", colonIndex); if(valueStart == -1) break; int valueEnd = jsonResponse.indexOf("\"", valueStart + 1); if(valueEnd == -1) break; String boxCodeValue = jsonResponse.substring(valueStart + 1, valueEnd); if("20".equals(boxCodeValue)) { // boxCode "20" 객체의 시작 위치 찾기 (이전 { 찾기) int objStart = jsonResponse.lastIndexOf("{", boxCodeIndex); if(objStart >= 0) { String objStr = jsonResponse.substring(objStart, boxCodeIndex); // docCnt 추출 int docCntIndex = objStr.indexOf("\"docCnt\""); if(docCntIndex >= 0) { int dcColonIndex = objStr.indexOf(":", docCntIndex + 8); int dcValueStart = objStr.indexOf("\"", dcColonIndex); int dcValueEnd = objStr.indexOf("\"", dcValueStart + 1); if(dcValueStart >= 0 && dcValueEnd > dcValueStart) { String docCntStr = objStr.substring(dcValueStart + 1, dcValueEnd); count = Integer.parseInt(docCntStr.trim()); System.out.println("미결문서(boxCode=20) docCnt: " + count); } } } break; } searchFrom = valueEnd + 1; } } catch (Exception e) { System.err.println("미결 건수 추출 오류: " + e.getMessage()); e.printStackTrace(); } return count; } /** * Amaranth10 전자결재 문서 목록 조회 - JSON 문자열 반환 (AJAX 전용) * approvalList.jsp 전용 엔드포인트에서 호출 * @param request HttpServletRequest * @param paramMap 검색 파라미터 * @return JSON 문자열 */ public String getAmaranthApprovalDocListJson(HttpServletRequest request, Map paramMap){ Map resultMap = getAmaranthApprovalDocList(request, paramMap); return buildApprovalDocListJson(resultMap); } /** * Amaranth10 결재 문서 상세 조회 * @param request HttpServletRequest * @param paramMap docId, deptSeq 필수 * @return API 응답 JSON 원본 (contents HTML 포함) */ public String getAmaranthApprovalDocDetail(HttpServletRequest request, Map paramMap){ try { // 세션에서 사원 정보 가져오기 HttpSession session = request.getSession(); PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); String empSeq = CommonUtils.checkNull(person.getEmpseq()); String compSeq = "1000"; String docId = CommonUtils.checkNull(paramMap.get("docId")); String deptSeq = CommonUtils.checkNull(paramMap.get("deptSeq")); System.out.println("=== Amaranth 결재 문서 상세 조회 ==="); System.out.println("empSeq: " + empSeq + ", docId: " + docId + ", deptSeq: " + deptSeq); if(empSeq == null || empSeq.isEmpty()){ System.err.println("empSeq가 비어있습니다."); return "{\"resultCode\":-1,\"resultMsg\":\"empSeq가 비어있습니다.\"}"; } if(docId == null || docId.isEmpty()){ System.err.println("docId가 비어있습니다."); return "{\"resultCode\":-1,\"resultMsg\":\"docId가 비어있습니다.\"}"; } // API 호출 com.pms.api.AmaranthApprovalApiClient apiClient = new com.pms.api.AmaranthApprovalApiClient(); String baseUrl = "https://erp.rps-korea.com"; String apiResponse = apiClient.getApprovalDocDetail(baseUrl, empSeq, compSeq, deptSeq, docId); System.out.println("상세 조회 API 응답 길이: " + (apiResponse != null ? apiResponse.length() : 0) + " bytes"); return apiResponse; } catch(Exception e){ System.err.println("Amaranth 결재 문서 상세 조회 오류: " + e.getMessage()); e.printStackTrace(); return "{\"resultCode\":-1,\"resultMsg\":\"" + escapeJsonValue(e.getMessage()) + "\"}"; } } /** * 결재 문서 목록 결과를 JSON 문자열로 변환 */ private String buildApprovalDocListJson(Map resultMap){ StringBuilder json = new StringBuilder(); json.append("{"); // 페이징 정보 json.append("\"totalCount\":").append(resultMap.get("TOTAL_COUNT")).append(","); json.append("\"maxPage\":").append(resultMap.get("MAX_PAGE_SIZE")).append(","); json.append("\"nextPage\":").append(resultMap.get("NEXT_PAGE")).append(","); json.append("\"prevPage\":").append(resultMap.get("PREV_PAGE")).append(","); // 문서 리스트 json.append("\"list\":["); ArrayList> list = (ArrayList>) resultMap.get("LIST"); if(list != null){ for(int i = 0; i < list.size(); i++){ if(i > 0) json.append(","); HashMap doc = list.get(i); json.append("{"); json.append("\"RNUM\":\"").append(escapeJsonValue(String.valueOf(doc.get("RNUM")))).append("\","); json.append("\"DOC_ID\":\"").append(escapeJsonValue(String.valueOf(doc.get("DOC_ID")))).append("\","); json.append("\"DOC_TITLE\":\"").append(escapeJsonValue(String.valueOf(doc.get("DOC_TITLE")))).append("\","); json.append("\"FORM_NAME\":\"").append(escapeJsonValue(String.valueOf(doc.get("FORM_NAME")))).append("\","); json.append("\"EMP_NAME\":\"").append(escapeJsonValue(String.valueOf(doc.get("EMP_NAME")))).append("\","); json.append("\"DEPT_NAME\":\"").append(escapeJsonValue(String.valueOf(doc.get("DEPT_NAME")))).append("\","); json.append("\"DOC_STS_NAME\":\"").append(escapeJsonValue(String.valueOf(doc.get("DOC_STS_NAME")))).append("\","); json.append("\"REP_DT\":\"").append(escapeJsonValue(String.valueOf(doc.get("REP_DT")))).append("\","); json.append("\"DOC_STS\":\"").append(escapeJsonValue(String.valueOf(doc.get("DOC_STS")))).append("\","); json.append("\"DEPT_SEQ\":\"").append(escapeJsonValue(String.valueOf(doc.get("DEPT_SEQ")))).append("\""); json.append("}"); } } json.append("]"); json.append("}"); return json.toString(); } /** * JSON 값 이스케이프 (서비스 내부용) */ private String escapeJsonValue(String value){ if(value == null || "null".equals(value)) return ""; return value.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t"); } /** * Amaranth10 전자결재 문서 목록 조회 (서버 인증 방식) * @param request HttpServletRequest * @param paramMap 검색 파라미터 (search_approvalTitle, search_fromDate, search_toDate, page 등) * @return 결재 문서 목록 및 페이징 정보 */ public Map getAmaranthApprovalDocList(HttpServletRequest request, Map paramMap){ Map resultMap = new HashMap(); ArrayList> resultList = new ArrayList(); try{ // 세션에서 사원 정보 가져오기 HttpSession session = request.getSession(); PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); String empSeq = CommonUtils.checkNull(person.getEmpseq()); String compSeq = "1000"; // 회사 시퀀스 System.out.println("=== Amaranth 결재 문서 목록 조회 ==="); System.out.println("empSeq: " + empSeq); if(empSeq == null || empSeq.isEmpty()){ System.err.println("empSeq가 비어있습니다. LoginId 업데이트 배치를 먼저 실행하세요."); resultMap.put("LIST", resultList); resultMap.put("TOTAL_COUNT", 0); return resultMap; } // 검색 조건 매핑 String keyWord = CommonUtils.checkNull(paramMap.get("search_approvalTitle")); String fromDt = CommonUtils.checkNull(paramMap.get("search_fromDate")); String toDt = CommonUtils.checkNull(paramMap.get("search_toDate")); String page = CommonUtils.checkNull(paramMap.get("page"), "1"); String pageSize = "20"; // menuId: 기안함(1000400) - 결재 전체 목록 조회용 String menuId = CommonUtils.checkNull(paramMap.get("menuId"), "1000400"); // API 호출 com.pms.api.AmaranthApprovalApiClient apiClient = new com.pms.api.AmaranthApprovalApiClient(); String baseUrl = "https://erp.rps-korea.com"; String apiResponse = apiClient.getApprovalDocList( baseUrl, empSeq, compSeq, menuId, fromDt, toDt, keyWord, page, pageSize); System.out.println("API 응답 길이: " + (apiResponse != null ? apiResponse.length() : 0) + " bytes"); // JSON 파싱 resultList = parseApprovalDocList(apiResponse); int totalCnt = extractTotalCnt(apiResponse); // 번호 매기기 (RNUM) int startNum = (Integer.parseInt(page) - 1) * Integer.parseInt(pageSize); for(int i = 0; i < resultList.size(); i++){ resultList.get(i).put("RNUM", String.valueOf(startNum + i + 1)); } // 페이징 정보 설정 int currentPage = Integer.parseInt(page); int pageSizeInt = Integer.parseInt(pageSize); int maxPage = (int) Math.ceil((double) totalCnt / pageSizeInt); if(maxPage < 1) maxPage = 1; resultMap.put("LIST", resultList); resultMap.put("TOTAL_COUNT", totalCnt); resultMap.put("MAX_PAGE_SIZE", maxPage); resultMap.put("NEXT_PAGE", Math.min(currentPage + 1, maxPage)); resultMap.put("PREV_PAGE", Math.max(currentPage - 1, 1)); System.out.println("결재 문서 수: " + resultList.size() + ", 전체: " + totalCnt); }catch(Exception e){ System.err.println("Amaranth 결재 문서 목록 조회 오류: " + e.getMessage()); e.printStackTrace(); resultMap.put("LIST", resultList); resultMap.put("TOTAL_COUNT", 0); resultMap.put("MAX_PAGE_SIZE", 1); resultMap.put("NEXT_PAGE", 1); resultMap.put("PREV_PAGE", 1); } return resultMap; } /** * API 응답에서 eaDocList 배열 파싱 * 응답 구조: {"resultData":{"eaDocList":[{...},{...}],"totalCnt":94}} */ private ArrayList> parseApprovalDocList(String jsonResponse){ ArrayList> list = new ArrayList(); try { // eaDocList 배열 찾기 int eaDocListIndex = jsonResponse.indexOf("\"eaDocList\""); if(eaDocListIndex == -1){ System.err.println("eaDocList를 찾을 수 없습니다."); return list; } // eaDocList 다음의 [ 찾기 int arrayStart = jsonResponse.indexOf("[", eaDocListIndex); if(arrayStart == -1){ System.err.println("eaDocList 배열 시작을 찾을 수 없습니다."); return list; } // 대응하는 ] 찾기 int bracketCount = 0; int arrayEnd = -1; for(int i = arrayStart; i < jsonResponse.length(); i++){ char c = jsonResponse.charAt(i); if(c == '[') bracketCount++; else if(c == ']') bracketCount--; if(bracketCount == 0){ arrayEnd = i; break; } } if(arrayEnd == -1){ System.err.println("eaDocList 배열 끝을 찾을 수 없습니다."); return list; } String arrayStr = jsonResponse.substring(arrayStart + 1, arrayEnd); // 각 문서 객체 파싱 int searchFrom = 0; while(searchFrom < arrayStr.length()){ int objStart = arrayStr.indexOf("{", searchFrom); if(objStart == -1) break; // 중첩 { } 처리 int braceCount = 0; int objEnd = -1; for(int i = objStart; i < arrayStr.length(); i++){ char c = arrayStr.charAt(i); if(c == '{') braceCount++; else if(c == '}') braceCount--; if(braceCount == 0){ objEnd = i; break; } } if(objEnd == -1) break; String objStr = arrayStr.substring(objStart, objEnd + 1); HashMap doc = parseDocObject(objStr); if(!doc.isEmpty()){ list.add(doc); } searchFrom = objEnd + 1; } System.out.println("파싱된 문서 수: " + list.size()); } catch (Exception e) { System.err.println("eaDocList 파싱 오류: " + e.getMessage()); e.printStackTrace(); } return list; } /** * 개별 문서 JSON 객체 파싱 */ private HashMap parseDocObject(String objStr){ HashMap doc = new HashMap(); try { doc.put("DOC_ID", extractJsonStringValue(objStr, "docId")); doc.put("DOC_TITLE", extractJsonStringValue(objStr, "docTitle")); doc.put("FORM_NAME", extractJsonStringValue(objStr, "formName")); doc.put("EMP_NAME", extractJsonStringValue(objStr, "empName")); doc.put("DEPT_NAME", extractJsonStringValue(objStr, "deptName")); doc.put("DOC_STS", extractJsonStringValue(objStr, "docSts")); doc.put("DOC_STS_NAME", extractJsonStringValue(objStr, "docStsName")); doc.put("POSITION_NAME", extractJsonStringValue(objStr, "positionName")); doc.put("DUTY_NAME", extractJsonStringValue(objStr, "dutyName")); doc.put("LINE_NAME", extractJsonStringValue(objStr, "lineName")); doc.put("ATTACH_CNT", extractJsonStringValue(objStr, "attachCnt")); doc.put("COMMENT_CNT", extractJsonStringValue(objStr, "commentCnt")); doc.put("EMERGENCY_FLAG", extractJsonStringValue(objStr, "emergencyFlag")); doc.put("DELAY_FLAG", extractJsonStringValue(objStr, "delayFlag")); doc.put("READ_YN", extractJsonStringValue(objStr, "readYN")); doc.put("APP_YN", extractJsonStringValue(objStr, "appYN")); doc.put("COMP_SEQ", extractJsonStringValue(objStr, "compSeq")); doc.put("EMP_SEQ", extractJsonStringValue(objStr, "empSeq")); doc.put("DEPT_SEQ", extractJsonStringValue(objStr, "deptSeq")); // 상신일(repDt) 포맷팅: YYYYMMDDHHMISS → YYYY-MM-DD String repDt = extractJsonStringValue(objStr, "repDt"); if(repDt != null && repDt.length() >= 8){ doc.put("REP_DT", repDt.substring(0, 4) + "-" + repDt.substring(4, 6) + "-" + repDt.substring(6, 8)); } else { doc.put("REP_DT", repDt); } // 생성일(createdDt) 포맷팅 String createdDt = extractJsonStringValue(objStr, "createdDt"); if(createdDt != null && createdDt.length() >= 8){ doc.put("CREATED_DT", createdDt.substring(0, 4) + "-" + createdDt.substring(4, 6) + "-" + createdDt.substring(6, 8)); } else { doc.put("CREATED_DT", createdDt); } } catch (Exception e) { System.err.println("문서 객체 파싱 오류: " + e.getMessage()); } return doc; } /** * JSON 문자열에서 특정 키의 문자열 값 추출 */ private String extractJsonStringValue(String json, String key){ String searchKey = "\"" + key + "\""; int keyIndex = json.indexOf(searchKey); if(keyIndex == -1) return ""; int colonIndex = json.indexOf(":", keyIndex + searchKey.length()); if(colonIndex == -1) return ""; // 콜론 뒤의 공백 건너뛰기 int valueStart = colonIndex + 1; while(valueStart < json.length() && json.charAt(valueStart) == ' '){ valueStart++; } if(valueStart >= json.length()) return ""; // null 값 체크 if(json.substring(valueStart).startsWith("null")){ return ""; } // 숫자 값 체크 (따옴표 없는 경우) char firstChar = json.charAt(valueStart); if(firstChar != '"'){ // 숫자나 boolean 값 int valueEnd = valueStart; while(valueEnd < json.length()){ char c = json.charAt(valueEnd); if(c == ',' || c == '}' || c == ']') break; valueEnd++; } return json.substring(valueStart, valueEnd).trim(); } // 문자열 값 (따옴표 있는 경우) int quoteStart = valueStart; // 이미 '"' 위치 int quoteEnd = json.indexOf("\"", quoteStart + 1); if(quoteEnd == -1) return ""; return json.substring(quoteStart + 1, quoteEnd); } /** * API 응답에서 totalCnt 추출 */ private int extractTotalCnt(String jsonResponse){ try { String searchKey = "\"totalCnt\""; int keyIndex = jsonResponse.indexOf(searchKey); if(keyIndex == -1) return 0; int colonIndex = jsonResponse.indexOf(":", keyIndex + searchKey.length()); if(colonIndex == -1) return 0; int valueStart = colonIndex + 1; while(valueStart < jsonResponse.length() && jsonResponse.charAt(valueStart) == ' '){ valueStart++; } int valueEnd = valueStart; while(valueEnd < jsonResponse.length()){ char c = jsonResponse.charAt(valueEnd); if(c == ',' || c == '}' || c == ']') break; valueEnd++; } String cntStr = jsonResponse.substring(valueStart, valueEnd).trim(); return Integer.parseInt(cntStr); } catch (Exception e) { System.err.println("totalCnt 추출 오류: " + e.getMessage()); return 0; } } public ArrayList getApprovalLine(HttpServletRequest request, Map paramMap){ ArrayList> resultList = new ArrayList(); SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(); try{ resultList = (ArrayList)sqlSession.selectList("approval.getApprovalLine",paramMap); }catch(Exception e){ throw e; }finally{ sqlSession.close(); } return CommonUtils.toUpperCaseMapKey(resultList); } /** * 결재완료 여부 확인 (견적서 메일 발송용) * @param paramMap * @return */ /** * Amaranth10 전자결재 문서 상신 (사용자 인증 방식) * 1단계: getAuthToken(서버인증)으로 사용자 토큰 발급 * 2단계: 발급받은 토큰으로 상신 API 호출 * @param request HttpServletRequest * @param paramMap 상신 데이터 (title, appLineListJson 등) * @return 결과 JSON 문자열 */ public String submitAmaranthApprovalDoc(HttpServletRequest request, Map paramMap){ try { HttpSession session = request.getSession(); PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); if(person == null){ return "{\"resultCode\":-1,\"resultMsg\":\"세션이 만료되었습니다. 다시 로그인하세요.\"}"; } String empSeq = CommonUtils.checkNull(person.getEmpseq()); String compSeq = "1000"; if(empSeq == null || empSeq.isEmpty()){ return "{\"resultCode\":-1,\"resultMsg\":\"empSeq가 비어있습니다. 관리자에게 문의하세요.\"}"; } // 파라미터 추출 String title = CommonUtils.checkNull(paramMap.get("title")); String appLineListJson = CommonUtils.checkNull(paramMap.get("appLineListJson")); String deptSeq = CommonUtils.checkNull(paramMap.get("deptSeq")); // 양식코드, 연동코드, 기록물철 (Amaranth10 설정값) String tiKeyCode = CommonUtils.checkNull(paramMap.get("tiKeyCode"), "1576"); String approKey = CommonUtils.checkNull(paramMap.get("approKey"), ""); String aiKeyCode = CommonUtils.checkNull(paramMap.get("aiKeyCode"), "102433"); System.out.println("=== Amaranth 결재 문서 상신 (사용자 인증 - empSeqEnc) ==="); System.out.println("empSeq: " + empSeq); System.out.println("title: " + title); System.out.println("deptSeq: " + deptSeq); System.out.println("appLineList: " + appLineListJson); // 요청 Body 구성 StringBuilder body = new StringBuilder(); body.append("{"); body.append("\"header\":{"); body.append("\"groupSeq\":\"").append(escapeJsonValue(GROUP_SEQ)).append("\","); body.append("\"empSeq\":\"").append(escapeJsonValue(empSeq)).append("\""); body.append("},"); body.append("\"body\":{"); body.append("\"empSeq\":\"").append(escapeJsonValue(empSeq)).append("\","); body.append("\"groupSeq\":\"").append(escapeJsonValue(GROUP_SEQ)).append("\","); body.append("\"langCode\":\"kr\","); body.append("\"saveType\":\"002\","); body.append("\"tiKeyCode\":\"").append(escapeJsonValue(tiKeyCode)).append("\","); body.append("\"approKey\":\"").append(escapeJsonValue(approKey)).append("\","); // 결재라인 (JSON 문자열로 전달 - API 스펙: jsonstring 타입) body.append("\"appLineList\":\"").append(appLineListJson.replace("\"", "\\\"")).append("\","); // 회사정보 body.append("\"companyInfo\":{"); body.append("\"groupSeq\":\"").append(escapeJsonValue(GROUP_SEQ)).append("\","); body.append("\"compSeq\":\"").append(escapeJsonValue(compSeq)).append("\","); body.append("\"deptSeq\":\"").append(escapeJsonValue(deptSeq)).append("\","); body.append("\"empSeq\":\"").append(escapeJsonValue(empSeq)).append("\""); body.append("},"); // 문서기본정보 body.append("\"docParamList\":[{"); body.append("\"diTitle\":\"").append(escapeJsonValue(title)).append("\","); body.append("\"aiKeyCode\":\"").append(escapeJsonValue(aiKeyCode)).append("\","); body.append("\"diDocGrade\":\"000\","); body.append("\"diDocType\":\"000\","); body.append("\"diPublic\":\"001\","); body.append("\"diGrade\":\"000\","); body.append("\"diSecretGrade\":\"\","); body.append("\"diTreatMent\":\"001\","); body.append("\"fileAttachInfo\":[]"); body.append("}]"); body.append("}"); body.append("}"); String requestBody = body.toString(); System.out.println("Request Body: " + requestBody); // API 호출 (사용자 인증 - empSeq로 토큰 발급 후 상신) com.pms.api.AmaranthApprovalApiClient apiClient = new com.pms.api.AmaranthApprovalApiClient(); String baseUrl = "https://erp.rps-korea.com"; String apiResponse = apiClient.submitApprovalDoc(baseUrl, empSeq, requestBody); System.out.println("상신 API 응답: " + apiResponse); return apiResponse; } catch(Exception e){ System.err.println("Amaranth 결재 문서 상신 오류: " + e.getMessage()); e.printStackTrace(); return "{\"resultCode\":-1,\"resultMsg\":\"" + escapeJsonValue(e.getMessage()) + "\"}"; } } /** * Amaranth10 사원 목록 조회 (결재라인 사용자 검색용) * @param request HttpServletRequest * @return 사원 목록 JSON 문자열 */ public String searchAmaranthEmployees(HttpServletRequest request, Map paramMap){ try { com.pms.api.AmaranthUserApiClient apiClient = new com.pms.api.AmaranthUserApiClient(); String baseUrl = "https://erp.rps-korea.com"; String apiResponse = apiClient.getAllUserInfo(baseUrl); return apiResponse; } catch(Exception e){ System.err.println("Amaranth 사원 검색 오류: " + e.getMessage()); e.printStackTrace(); return "{\"resultCode\":-1,\"resultMsg\":\"" + escapeJsonValue(e.getMessage()) + "\"}"; } } // Amaranth10 그룹 시퀀스 (상신 Body 구성용) private static final String GROUP_SEQ = "gcmsAmaranth40578"; private static final String AMARANTH_BASE_URL = "https://erp.rps-korea.com"; /** * Amaranth10 전자결재 SSO URL 생성 (B방식 - 팝업 직접 오픈) * 1단계: 인증 토큰 발급 (api99u01A01) * 2단계: SSO 호출 (api99u01A02) → fullUrl 획득 * * @param request HttpServletRequest (세션에서 사용자 정보 추출) * @param paramMap targetType, targetObjId, approvalTitle, outProcessCode, formId 등 * @return fullUrl이 포함된 JSON 문자열 */ public String getAmaranthSsoUrl(HttpServletRequest request, Map paramMap){ SqlSession sqlSession = null; try { HttpSession session = request.getSession(); PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); if(person == null){ return "{\"resultCode\":-1,\"resultMsg\":\"세션이 만료되었습니다. 다시 로그인하세요.\"}"; } String empSeq = CommonUtils.checkNull(person.getEmpseq()); String loginId = CommonUtils.checkNull(person.getUserId()); System.out.println("=== Amaranth SSO - 사용자 정보 ==="); System.out.println("userId(loginId): " + loginId); System.out.println("userName: " + person.getUserName()); System.out.println("empSeq: [" + empSeq + "]"); if(empSeq.isEmpty()){ return "{\"resultCode\":-1,\"resultMsg\":\"empSeq 정보가 없습니다. (userId: " + loginId + ") 관리자에게 문의하세요.\"}"; } // 파라미터 추출 String targetType = CommonUtils.checkNull(paramMap.get("targetType")); String targetObjId = CommonUtils.checkNull(paramMap.get("targetObjId")); String approvalTitle = CommonUtils.checkNull(paramMap.get("approvalTitle")); String outProcessCode = CommonUtils.checkNull(paramMap.get("outProcessCode")); String formId = CommonUtils.checkNull(paramMap.get("formId")); String compSeq = CommonUtils.checkNull(paramMap.get("compSeq"), "1000"); String deptSeq = CommonUtils.checkNull(paramMap.get("deptSeq")); // DB에서 기존 매핑 조회 → 있으면 approKey 재사용, 없으면 신규 생성 sqlSession = SqlMapConfig.getInstance().getSqlSession(false); Map mappingParam = new HashMap(); mappingParam.put("targetType", targetType); mappingParam.put("targetObjId", targetObjId); Map existing = sqlSession.selectOne("approval.selectAmaranthApprovalByTarget", mappingParam); existing = existing != null ? CommonUtils.toUpperCaseMapKey(existing) : null; String approKey; boolean isNewRecord; if(existing != null){ approKey = CommonUtils.checkNull(existing.get("APPRO_KEY")); isNewRecord = false; System.out.println("=== 기존 approKey 재사용: " + approKey + " ==="); } else { approKey = "UB_" + java.util.UUID.randomUUID().toString(); isNewRecord = true; System.out.println("=== 신규 approKey 생성: " + approKey + " ==="); } System.out.println("empSeq: " + empSeq + ", loginId: " + loginId); System.out.println("targetType: " + targetType + ", targetObjId: " + targetObjId); System.out.println("outProcessCode: " + outProcessCode + ", formId: " + formId); // API 클라이언트 생성 com.pms.api.AmaranthApprovalApiClient apiClient = new com.pms.api.AmaranthApprovalApiClient(); // 첨부파일 처리: targetType별 분기하여 원챔버 업로드 String fileListEncoded = null; try { if("CONTRACT_ESTIMATE".equals(targetType)) { fileListEncoded = uploadEstimateFilesToOneChamber(apiClient, empSeq, targetObjId); } else { fileListEncoded = uploadProposalFilesToOneChamber(apiClient, empSeq, targetObjId); } } catch(Exception fileEx) { System.err.println("[첨부파일] 원챔버 업로드 중 오류 (결재는 계속 진행): " + fileEx.getMessage()); fileEx.printStackTrace(); } // SSO URL 생성 API 호출 (기존/신규 동일한 approKey 사용) String apiResponse = apiClient.getSsoUrl( AMARANTH_BASE_URL, empSeq, outProcessCode, formId, approKey, approvalTitle, "W", compSeq, deptSeq, loginId, fileListEncoded ); System.out.println("SSO API 응답: " + apiResponse); // 응답에서 fullUrl 추출 String fullUrl = extractJsonStringValue(apiResponse, "fullUrl"); String resultCode = extractJsonStringValue(apiResponse, "resultCode"); if("0".equals(resultCode) && !fullUrl.isEmpty()){ // 신규면 INSERT, 기존이면 UPDATE (제목/작성자만 갱신) mappingParam.put("approKey", approKey); mappingParam.put("approvalTitle", approvalTitle); mappingParam.put("writer", loginId); if(isNewRecord){ sqlSession.insert("approval.insertAmaranthApproval", mappingParam); System.out.println("Amaranth 결재 매핑 INSERT - approKey: " + approKey); } else { sqlSession.update("approval.updateAmaranthApprovalResubmit", mappingParam); System.out.println("Amaranth 결재 매핑 UPDATE - approKey: " + approKey); } sqlSession.commit(); StringBuilder result = new StringBuilder(); result.append("{\"resultCode\":0,\"resultMsg\":\"SUCCESS\",\"resultData\":{"); result.append("\"fullUrl\":\"").append(escapeJsonValue(fullUrl)).append("\","); result.append("\"approKey\":\"").append(escapeJsonValue(approKey)).append("\","); result.append("\"targetType\":\"").append(escapeJsonValue(targetType)).append("\","); result.append("\"targetObjId\":\"").append(escapeJsonValue(targetObjId)).append("\""); result.append("}}"); return result.toString(); } else { String resultMsg = extractJsonStringValue(apiResponse, "resultMsg"); return "{\"resultCode\":-1,\"resultMsg\":\"SSO URL 생성 실패: " + escapeJsonValue(resultMsg) + "\"}"; } } catch(Exception e){ if(sqlSession != null) sqlSession.rollback(); System.err.println("Amaranth SSO URL 생성 오류: " + e.getMessage()); e.printStackTrace(); return "{\"resultCode\":-1,\"resultMsg\":\"" + escapeJsonValue(e.getMessage()) + "\"}"; } finally { if(sqlSession != null) sqlSession.close(); } } /** * 품의서 첨부파일을 원챔버에 업로드하고 fileList (URL 인코딩) 반환 * @return URL 인코딩된 fileList JSON 문자열 (파일 없으면 null) */ private String uploadProposalFilesToOneChamber( com.pms.api.AmaranthApprovalApiClient apiClient, String empSeq, String targetObjId) throws Exception { if(targetObjId == null || targetObjId.isEmpty()) return null; SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(true); try { // 1. 인증 토큰 발급 (파일 업로드는 사용자 인증 필요) Map authResult = apiClient.getAuthToken(AMARANTH_BASE_URL, empSeq); if(!"true".equals(authResult.get("success"))){ throw new Exception("파일 업로드용 인증 토큰 발급 실패: " + authResult.get("resultMsg")); } String authToken = authResult.get("authToken"); String userHashKey = authResult.get("hashKey"); StringBuilder listItems = new StringBuilder(); int uploadCount = 0; // 2. 품의서 본문을 JSP와 동일한 레이아웃의 HTML 파일로 생성하여 업로드 try { Map proposalParam = new HashMap(); proposalParam.put("PROPOSAL_OBJID", targetObjId); Map proposalInfo = sqlSession.selectOne("salesMng.getProposalInfo", proposalParam); if(proposalInfo != null){ proposalInfo = CommonUtils.toUpperCaseMapKey(proposalInfo); String proposalNo = CommonUtils.checkNull(proposalInfo.get("PROPOSAL_NO")); // 품목 리스트 조회 Map partParam = new HashMap(); partParam.put("PROPOSAL_OBJID", targetObjId); List partList = sqlSession.selectList("salesMng.getProposalPartList", partParam); String fullHtml = buildProposalFormFileHtml(proposalInfo, partList); String tempFileName = "구매품의서_" + proposalNo + ".html"; java.io.File tempFile = java.io.File.createTempFile("proposal_", ".html"); java.io.OutputStreamWriter writer = new java.io.OutputStreamWriter( new java.io.FileOutputStream(tempFile), "UTF-8"); writer.write(fullHtml); writer.close(); System.out.println("[첨부파일] 품의서 HTML 생성: " + tempFileName + " (" + tempFile.length() + " bytes)"); String uploadResponse = apiClient.uploadFileToOneChamber( AMARANTH_BASE_URL, authToken, userHashKey, empSeq, tempFile, tempFileName ); String listItem = apiClient.extractListItemFromUploadResponse(uploadResponse); if(listItem != null){ listItems.append(listItem); uploadCount++; System.out.println("[첨부파일] 품의서 HTML 업로드 성공"); } tempFile.delete(); } } catch(Exception htmlEx){ System.err.println("[첨부파일] 품의서 HTML 생성/업로드 오류: " + htmlEx.getMessage()); } // 3. ATTACH_FILE_INFO에서 기존 첨부파일도 업로드 Map fileParam = new HashMap(); fileParam.put("targetObjId", targetObjId); List> fileList = sqlSession.selectList("common.getFileList", fileParam); if(fileList != null && !fileList.isEmpty()){ System.out.println("[첨부파일] 품의서(" + targetObjId + ") 기존 첨부파일 " + fileList.size() + "건 발견"); for(Map fileInfo : fileList){ String savedFileName = CommonUtils.checkNull(fileInfo.get("saved_file_name")); String realFileName = CommonUtils.checkNull(fileInfo.get("real_file_name")); String filePath = CommonUtils.checkNull(fileInfo.get("file_path")); String fileExt = CommonUtils.checkNull(fileInfo.get("file_ext")); if(savedFileName.isEmpty()) continue; java.io.File physicalFile = new java.io.File(filePath, savedFileName); if(!physicalFile.exists()){ System.err.println("[첨부파일] 물리 파일 없음: " + physicalFile.getAbsolutePath()); continue; } String originalName = realFileName; if(!originalName.contains(".") && !fileExt.isEmpty()){ originalName = realFileName + "." + fileExt; } System.out.println("[첨부파일] 업로드 시작: " + originalName + " (" + physicalFile.length() + " bytes)"); String uploadResponse = apiClient.uploadFileToOneChamber( AMARANTH_BASE_URL, authToken, userHashKey, empSeq, physicalFile, originalName ); String listItem = apiClient.extractListItemFromUploadResponse(uploadResponse); if(listItem != null){ if(uploadCount > 0) listItems.append(","); listItems.append(listItem); uploadCount++; System.out.println("[첨부파일] 업로드 성공: " + originalName); } else { System.err.println("[첨부파일] 업로드 응답에서 list 항목 추출 실패: " + originalName); } } } if(uploadCount == 0) return null; // 4. JSON 배열 구성 → URL 인코딩 String fileListJson = "[" + listItems.toString() + "]"; String fileListEncoded = java.net.URLEncoder.encode(fileListJson, "UTF-8"); System.out.println("[첨부파일] 총 " + uploadCount + "건 업로드 완료"); return fileListEncoded; } finally { if(sqlSession != null) sqlSession.close(); } } /** * 견적서 첨부파일을 원챔버에 업로드하고 fileList (URL 인코딩) 반환 * @return URL 인코딩된 fileList JSON 문자열 (파일 없으면 null) */ private String uploadEstimateFilesToOneChamber( com.pms.api.AmaranthApprovalApiClient apiClient, String empSeq, String targetObjId) throws Exception { if(targetObjId == null || targetObjId.isEmpty()) return null; SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(true); try { Map authResult = apiClient.getAuthToken(AMARANTH_BASE_URL, empSeq); if(!"true".equals(authResult.get("success"))){ throw new Exception("파일 업로드용 인증 토큰 발급 실패: " + authResult.get("resultMsg")); } String authToken = authResult.get("authToken"); String userHashKey = authResult.get("hashKey"); StringBuilder listItems = new StringBuilder(); int uploadCount = 0; // 1. 견적서 본문을 HTML 파일로 생성하여 업로드 try { Map estParam = new HashMap(); estParam.put("targetObjId", targetObjId); Map estimateInfo = sqlSession.selectOne("approval.getEstimateInfoForApproval", estParam); if(estimateInfo != null){ estimateInfo = CommonUtils.toUpperCaseMapKey(estimateInfo); String estimateNo = CommonUtils.checkNull(estimateInfo.get("ESTIMATE_NO")); Map itemParam = new HashMap(); itemParam.put("targetObjId", targetObjId); List itemList = sqlSession.selectList("approval.getEstimateItemsForApproval", itemParam); String fullHtml = buildEstimateFormFileHtml(estimateInfo, itemList); String tempFileName = "견적서_" + estimateNo + ".html"; java.io.File tempFile = java.io.File.createTempFile("estimate_", ".html"); java.io.OutputStreamWriter writer = new java.io.OutputStreamWriter( new java.io.FileOutputStream(tempFile), "UTF-8"); writer.write(fullHtml); writer.close(); System.out.println("[첨부파일] 견적서 HTML 생성: " + tempFileName + " (" + tempFile.length() + " bytes)"); String uploadResponse = apiClient.uploadFileToOneChamber( AMARANTH_BASE_URL, authToken, userHashKey, empSeq, tempFile, tempFileName ); String listItem = apiClient.extractListItemFromUploadResponse(uploadResponse); if(listItem != null){ listItems.append(listItem); uploadCount++; System.out.println("[첨부파일] 견적서 HTML 업로드 성공"); } tempFile.delete(); } } catch(Exception htmlEx){ System.err.println("[첨부파일] 견적서 HTML 생성/업로드 오류: " + htmlEx.getMessage()); } // 2. ATTACH_FILE_INFO에서 기존 첨부파일도 업로드 Map fileParam = new HashMap(); fileParam.put("targetObjId", targetObjId); List> fileList = sqlSession.selectList("common.getFileList", fileParam); if(fileList != null && !fileList.isEmpty()){ System.out.println("[첨부파일] 견적서(" + targetObjId + ") 기존 첨부파일 " + fileList.size() + "건 발견"); for(Map fileInfo : fileList){ String savedFileName = CommonUtils.checkNull(fileInfo.get("saved_file_name")); String realFileName = CommonUtils.checkNull(fileInfo.get("real_file_name")); String filePath = CommonUtils.checkNull(fileInfo.get("file_path")); if(savedFileName.isEmpty()) continue; String fullPath = filePath + "/" + savedFileName; java.io.File physicalFile = new java.io.File(fullPath); if(!physicalFile.exists()){ System.err.println("[첨부파일] 파일 미존재: " + fullPath); continue; } String originalName = realFileName.isEmpty() ? savedFileName : realFileName; String uploadResponse = apiClient.uploadFileToOneChamber( AMARANTH_BASE_URL, authToken, userHashKey, empSeq, physicalFile, originalName ); String listItem = apiClient.extractListItemFromUploadResponse(uploadResponse); if(listItem != null){ if(uploadCount > 0) listItems.append(","); listItems.append(listItem); uploadCount++; System.out.println("[첨부파일] 업로드 성공: " + originalName); } } } if(uploadCount == 0) return null; String fileListJson = "[" + listItems.toString() + "]"; String fileListEncoded = java.net.URLEncoder.encode(fileListJson, "UTF-8"); System.out.println("[첨부파일] 견적서 총 " + uploadCount + "건 업로드 완료"); return fileListEncoded; } finally { if(sqlSession != null) sqlSession.close(); } } /** * 견적서 데이터를 HTML 파일로 구성 (결재 첨부파일용) */ private String buildEstimateFormFileHtml(Map estimateInfo, List itemList){ String estimateNo = CommonUtils.checkNull(estimateInfo.get("ESTIMATE_NO")); String contractNo = CommonUtils.checkNull(estimateInfo.get("CONTRACT_NO")); String customerName = CommonUtils.checkNull(estimateInfo.get("CUSTOMER_NAME")); String writerName = CommonUtils.checkNull(estimateInfo.get("WRITER_NAME")); String regdate = CommonUtils.checkNull(estimateInfo.get("REGDATE")); String totalAmount = CommonUtils.checkNull(estimateInfo.get("TOTAL_AMOUNT")); String totalAmountKrw = CommonUtils.checkNull(estimateInfo.get("TOTAL_AMOUNT_KRW")); String currencyName = CommonUtils.checkNull(estimateInfo.get("CURRENCY_NAME")); String exchangeRate = CommonUtils.checkNull(estimateInfo.get("EXCHANGE_RATE")); String recipient = CommonUtils.checkNull(estimateInfo.get("RECIPIENT")); String contactPerson = CommonUtils.checkNull(estimateInfo.get("CONTACT_PERSON")); String modelName = CommonUtils.checkNull(estimateInfo.get("MODEL_NAME")); String validityPeriod = CommonUtils.checkNull(estimateInfo.get("VALIDITY_PERIOD")); String noteRemarks = CommonUtils.checkNull(estimateInfo.get("NOTE_REMARKS")); StringBuilder html = new StringBuilder(); html.append(""); html.append("견적서 - " + estimateNo + ""); html.append(""); html.append("
견 적 서
"); // 기본 정보 테이블 html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); if(!currencyName.isEmpty()){ html.append(""); html.append(""); } html.append(""); if(!validityPeriod.isEmpty()){ html.append(""); } html.append("
견적번호" + estimateNo + "영업번호" + contractNo + "
고객사" + customerName + "작성일" + regdate + "
수신" + recipient + "담당자" + contactPerson + "
작성자" + writerName + "모델명" + modelName + "
통화" + currencyName + "환율" + exchangeRate + "
합계금액"); if(!totalAmountKrw.isEmpty() && !"0".equals(totalAmountKrw)){ html.append(totalAmountKrw + " (KRW)"); if(!totalAmount.isEmpty()) html.append(" / " + totalAmount + " (" + currencyName + ")"); } else { html.append(totalAmount); } html.append("
유효기간" + validityPeriod + "
"); // 품목 리스트 if(itemList != null && !itemList.isEmpty()){ html.append(""); html.append(""); html.append(""); html.append(""); int no = 1; for(Map item : itemList){ item = CommonUtils.toUpperCaseMapKey(item); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); } html.append("
No품명규격수량단위단가금액비고
" + no++ + "" + CommonUtils.checkNull(item.get("DESCRIPTION")) + "" + CommonUtils.checkNull(item.get("SPECIFICATION")) + "" + CommonUtils.checkNull(item.get("QUANTITY")) + "" + CommonUtils.checkNull(item.get("UNIT")) + "" + CommonUtils.checkNull(item.get("UNIT_PRICE")) + "" + CommonUtils.checkNull(item.get("AMOUNT")) + "" + CommonUtils.checkNull(item.get("REMARK")) + "
"); } // 비고 if(!noteRemarks.isEmpty()){ html.append("
비고:
" + noteRemarks.replace("\n", "
") + "
"); } html.append(""); return html.toString(); } /** * 견적서 데이터를 HTML 본문으로 구성 (아마란스 결재 화면 표시용) */ private String buildEstimateContentsHtml(Map estimateInfo, List itemList){ StringBuilder html = new StringBuilder(); String estimateNo = CommonUtils.checkNull(estimateInfo.get("ESTIMATE_NO")); String contractNo = CommonUtils.checkNull(estimateInfo.get("CONTRACT_NO")); String customerName = CommonUtils.checkNull(estimateInfo.get("CUSTOMER_NAME")); String writerName = CommonUtils.checkNull(estimateInfo.get("WRITER_NAME")); String regdate = CommonUtils.checkNull(estimateInfo.get("REGDATE")); String totalAmount = CommonUtils.checkNull(estimateInfo.get("TOTAL_AMOUNT")); String totalAmountKrw = CommonUtils.checkNull(estimateInfo.get("TOTAL_AMOUNT_KRW")); String currencyName = CommonUtils.checkNull(estimateInfo.get("CURRENCY_NAME")); String exchangeRate = CommonUtils.checkNull(estimateInfo.get("EXCHANGE_RATE")); String recipient = CommonUtils.checkNull(estimateInfo.get("RECIPIENT")); String contactPerson = CommonUtils.checkNull(estimateInfo.get("CONTACT_PERSON")); String modelName = CommonUtils.checkNull(estimateInfo.get("MODEL_NAME")); String validityPeriod = CommonUtils.checkNull(estimateInfo.get("VALIDITY_PERIOD")); String noteRemarks = CommonUtils.checkNull(estimateInfo.get("NOTE_REMARKS")); html.append("
"); html.append("

견 적 서

"); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); if(!currencyName.isEmpty()){ html.append(""); html.append(""); html.append(""); html.append(""); } html.append(""); html.append(""); if(!validityPeriod.isEmpty()){ html.append(""); html.append(""); } html.append("
견적번호" + estimateNo + "영업번호" + contractNo + "
고객사" + customerName + "작성일" + regdate + "
수신" + recipient + "담당자" + contactPerson + "
작성자" + writerName + "모델명" + modelName + "
통화" + currencyName + "환율" + exchangeRate + "
합계금액"); if(!totalAmountKrw.isEmpty() && !"0".equals(totalAmountKrw)){ html.append(totalAmountKrw + " (KRW)"); if(!totalAmount.isEmpty()) html.append(" / " + totalAmount + " (" + currencyName + ")"); } else { html.append(totalAmount); } html.append("
유효기간" + validityPeriod + "
"); // 품목 리스트 if(itemList != null && !itemList.isEmpty()){ html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); int no = 1; for(Map item : itemList){ item = CommonUtils.toUpperCaseMapKey(item); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); } html.append("
No품명규격수량단위단가금액비고
" + no++ + "" + CommonUtils.checkNull(item.get("DESCRIPTION")) + "" + CommonUtils.checkNull(item.get("SPECIFICATION")) + "" + CommonUtils.checkNull(item.get("QUANTITY")) + "" + CommonUtils.checkNull(item.get("UNIT")) + "" + CommonUtils.checkNull(item.get("UNIT_PRICE")) + "" + CommonUtils.checkNull(item.get("AMOUNT")) + "" + CommonUtils.checkNull(item.get("REMARK")) + "
"); } if(!noteRemarks.isEmpty()){ html.append("
비고:
" + noteRemarks.replace("\n", "
") + "
"); } html.append("
"); return html.toString(); } /** * Amaranth10 전자결재 콜백 처리 * 결재 이벤트(상신/진행/종결/반려/삭제 등) 발생 시 Amaranth10에서 호출 * * @param paramMap 콜백 파라미터 (processId, approkey, docId, docSts, userId, formId 등) * @return 처리 결과 JSON */ public String handleAmaranthApprovalCallback(Map paramMap){ String approkey = CommonUtils.checkNull(paramMap.get("approkey")); String docId = CommonUtils.checkNull(paramMap.get("docId")); String docSts = CommonUtils.checkNull(paramMap.get("docSts")); String docTitle = CommonUtils.checkNull(paramMap.get("docTitle")); String userId = CommonUtils.checkNull(paramMap.get("userId")); String processId = CommonUtils.checkNull(paramMap.get("processId")); String appCancelYn = CommonUtils.checkNull(paramMap.get("appCancelYn"), "0"); System.out.println("=== Amaranth 결재 콜백 수신 ==="); System.out.println("approkey: " + approkey); System.out.println("docId: " + docId); System.out.println("docSts: " + docSts + " (" + getDocStsName(docSts) + ")"); System.out.println("docTitle: " + docTitle); System.out.println("userId: " + userId); System.out.println("processId: " + processId); System.out.println("appCancelYn: " + appCancelYn); System.out.println("전체 파라미터: " + paramMap); SqlSession sqlSession = null; try { sqlSession = SqlMapConfig.getInstance().getSqlSession(false); // approkey로 매핑 정보 조회 Map searchParam = new HashMap(); searchParam.put("approKey", approkey); Map mappingInfo = sqlSession.selectOne("approval.selectAmaranthApprovalByApproKey", searchParam); if(mappingInfo == null){ System.err.println("콜백 처리 실패: approkey에 해당하는 매핑 정보 없음 - " + approkey); return "{\"resultCode\":\"SUCCESS\",\"resultMessage\":\"성공하였습니다.\"}"; } mappingInfo = CommonUtils.toUpperCaseMapKey(mappingInfo); String targetType = CommonUtils.checkNull(mappingInfo.get("TARGET_TYPE")); String targetObjId = CommonUtils.checkNull(mappingInfo.get("TARGET_OBJID")); System.out.println("매핑 정보 - targetType: " + targetType + ", targetObjId: " + targetObjId); // Amaranth 결재 매핑 테이블 상태 업데이트 String internalStatus = convertDocStsToInternalStatus(docSts, appCancelYn); Map updateParam = new HashMap(); updateParam.put("approKey", approkey); updateParam.put("amaranthDocId", docId); updateParam.put("docSts", docSts); updateParam.put("status", internalStatus); sqlSession.update("approval.updateAmaranthApprovalByCallback", updateParam); // 대상 문서(품의서 등)의 상태 업데이트 if(!targetObjId.isEmpty()){ String proposalStatus = convertDocStsToProposalStatus(docSts, appCancelYn); if(!proposalStatus.isEmpty()){ Map statusParam = new HashMap(); statusParam.put("targetObjId", targetObjId); statusParam.put("status", proposalStatus); if("PROPOSAL".equals(targetType)){ sqlSession.update("approval.changeProposalApprovalStatus", statusParam); System.out.println("품의서 상태 변경 - targetObjId: " + targetObjId + " → " + proposalStatus); } else if("SALES_REQUEST".equals(targetType)){ sqlSession.update("approval.salesRequestApprovalStatus", statusParam); System.out.println("구매요청 상태 변경 - targetObjId: " + targetObjId + " → " + proposalStatus); } else if("CONTRACT_ESTIMATE".equals(targetType)){ // 견적서: AMARANTH_APPROVAL 테이블만으로 상태 관리 (품의서와 동일 패턴) System.out.println("견적서 결재 상태 변경 - targetObjId: " + targetObjId + " → " + internalStatus); } } } sqlSession.commit(); System.out.println("콜백 처리 완료 - docSts: " + docSts + " → internalStatus: " + internalStatus); } catch(Exception e){ if(sqlSession != null) sqlSession.rollback(); System.err.println("콜백 처리 중 오류: " + e.getMessage()); e.printStackTrace(); } finally { if(sqlSession != null) sqlSession.close(); } return "{\"resultCode\":\"SUCCESS\",\"resultMessage\":\"성공하였습니다.\"}"; } /** * Amaranth docSts → 내부 상태 변환 * 10:임시보관, 20:상신, 30:진행, 90:종결, 100:반려, 110:보류 */ private String convertDocStsToInternalStatus(String docSts, String appCancelYn){ if("1".equals(appCancelYn)) return "create"; if("10".equals(docSts)) return "create"; if("20".equals(docSts)) return "inProcess"; if("30".equals(docSts)) return "inProcess"; if("90".equals(docSts)) return "complete"; if("100".equals(docSts)) return "reject"; if("110".equals(docSts)) return "hold"; return "inProcess"; } /** * Amaranth docSts → 품의서(SALES_REQUEST_MASTER) STATUS 변환 */ private String convertDocStsToProposalStatus(String docSts, String appCancelYn){ if("1".equals(appCancelYn)) return "create"; if("20".equals(docSts)) return "approvalRequest"; if("30".equals(docSts)) return "approvalRequest"; if("90".equals(docSts)) return "approvalComplete"; if("100".equals(docSts)) return "reject"; if("110".equals(docSts)) return "approvalRequest"; return ""; } /** * Amaranth10 결재작성 시 본문 내용 조회 (Binding WebAPI / WebAPI) * 결재 작성 화면이 열릴 때 Amaranth10에서 호출 * * @param paramMap approkey, formId, docId, userId, empSeq 등 * @return 제목/본문 JSON */ @SuppressWarnings("unchecked") public String getAmaranthApprovalContents(Map paramMap){ // Amaranth에서 approkey 또는 approKey 두 가지 형태로 전달될 수 있음 String approkey = CommonUtils.checkNull(paramMap.get("approkey")); if(approkey.isEmpty()){ approkey = CommonUtils.checkNull(paramMap.get("approKey")); } String docId = CommonUtils.checkNull(paramMap.get("docId")); System.out.println("=== Amaranth 결재 본문 조회 ==="); System.out.println("approkey: " + approkey); System.out.println("docId: " + docId); System.out.println("전체 파라미터: " + paramMap); SqlSession sqlSession = null; try { sqlSession = SqlMapConfig.getInstance().getSqlSession(); // approkey로 매핑 정보 조회 Map searchParam = new HashMap(); searchParam.put("approKey", approkey); Map mappingInfo = sqlSession.selectOne("approval.selectAmaranthApprovalByApproKey", searchParam); System.out.println("매핑 조회 결과: " + (mappingInfo != null ? mappingInfo : "null (매핑 없음)")); String title = "결재 문서"; String contentsHtml = "

연동 데이터를 찾을 수 없습니다.

"; if(mappingInfo != null){ // DB 조회 결과의 키 대소문자에 관계없이 처리 mappingInfo = CommonUtils.toUpperCaseMapKey(mappingInfo); String targetType = CommonUtils.checkNull(mappingInfo.get("TARGET_TYPE")); String targetObjId = CommonUtils.checkNull(mappingInfo.get("TARGET_OBJID")); title = CommonUtils.checkNull(mappingInfo.get("APPROVAL_TITLE"), "결재 문서"); System.out.println("매핑 정보 - targetType: " + targetType + ", targetObjId: " + targetObjId); if("PROPOSAL".equals(targetType) && !targetObjId.isEmpty()){ Map proposalParam = new HashMap(); proposalParam.put("PROPOSAL_OBJID", targetObjId); Map proposalInfo = sqlSession.selectOne("salesMng.getProposalInfo", proposalParam); if(proposalInfo != null){ proposalInfo = CommonUtils.toUpperCaseMapKey(proposalInfo); contentsHtml = buildProposalContentsHtml(proposalInfo, sqlSession, targetObjId); String proposalNo = CommonUtils.checkNull(proposalInfo.get("PROPOSAL_NO")); if(!proposalNo.isEmpty()){ title = "품의서 결재 - " + proposalNo; } } } else if("CONTRACT_ESTIMATE".equals(targetType) && !targetObjId.isEmpty()){ Map estParam = new HashMap(); estParam.put("targetObjId", targetObjId); Map estimateInfo = sqlSession.selectOne("approval.getEstimateInfoForApproval", estParam); if(estimateInfo != null){ estimateInfo = CommonUtils.toUpperCaseMapKey(estimateInfo); List itemList = sqlSession.selectList("approval.getEstimateItemsForApproval", estParam); contentsHtml = buildEstimateContentsHtml(estimateInfo, itemList); String estimateNo = CommonUtils.checkNull(estimateInfo.get("ESTIMATE_NO")); if(!estimateNo.isEmpty()){ title = "견적서 결재 - " + estimateNo; } } } } // JSONObject로 안전한 JSON 응답 생성 (이스케이프 자동 처리) JSONObject resultData = new JSONObject(); resultData.put("title", title); resultData.put("contents", contentsHtml); JSONObject response = new JSONObject(); response.put("resultCode", 0); response.put("resultMessage", "SUCCESS"); response.put("resultData", resultData); String responseStr = response.toJSONString(); System.out.println("Contents API 응답 길이: " + responseStr.length()); return responseStr; } catch(Exception e){ System.err.println("결재 본문 조회 오류: " + e.getMessage()); e.printStackTrace(); JSONObject resultData = new JSONObject(); resultData.put("title", "결재 문서"); resultData.put("contents", "

본문 조회 중 오류가 발생했습니다: " + (e.getMessage() != null ? e.getMessage() : "") + "

"); JSONObject response = new JSONObject(); response.put("resultCode", 0); response.put("resultMessage", "SUCCESS"); response.put("resultData", resultData); return response.toJSONString(); } finally { if(sqlSession != null) sqlSession.close(); } } /** * 품의서 데이터를 HTML 본문으로 구성 */ private String buildProposalContentsHtml(Map proposalInfo, SqlSession sqlSession, String targetObjId){ StringBuilder html = new StringBuilder(); String proposalNo = CommonUtils.checkNull(proposalInfo.get("PROPOSAL_NO")); String projectNumber = CommonUtils.checkNull(proposalInfo.get("PROJECT_NUMBER")); String projectName = CommonUtils.checkNull(proposalInfo.get("PROJECT_NAME")); String purchaseTypeName = CommonUtils.checkNull(proposalInfo.get("PURCHASE_TYPE_NAME")); String orderTypeName = CommonUtils.checkNull(proposalInfo.get("ORDER_TYPE_NAME")); String productName = CommonUtils.checkNull(proposalInfo.get("PRODUCT_NAME_TITLE")); String customerName = CommonUtils.checkNull(proposalInfo.get("PROJECT_CUSTOMER_NAME")); String writerName = CommonUtils.checkNull(proposalInfo.get("WRITER_NAME")); String regdate = CommonUtils.checkNull(proposalInfo.get("REGDATE_TITLE")); String remark = CommonUtils.checkNull(proposalInfo.get("REMARK")); String totalAmount = CommonUtils.checkNull(proposalInfo.get("TOTAL_AMOUNT")); html.append("
"); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); if(!totalAmount.isEmpty()){ html.append(""); html.append(""); } else { html.append(""); } html.append(""); html.append("
품의서 No").append(escapeHtml(proposalNo)).append("작성일").append(escapeHtml(regdate)).append("
프로젝트번호").append(escapeHtml(projectNumber)).append("프로젝트명").append(escapeHtml(projectName)).append("
구매유형").append(escapeHtml(purchaseTypeName)).append("주문유형").append(escapeHtml(orderTypeName)).append("
제품구분").append(escapeHtml(productName)).append("고객사").append(escapeHtml(customerName)).append("
작성자").append(escapeHtml(writerName)).append("합계금액").append(escapeHtml(totalAmount)).append("
"); // 품의서 품목 리스트 조회 try { Map partParam = new HashMap(); partParam.put("PROPOSAL_OBJID", targetObjId); List partList = sqlSession.selectList("salesMng.getProposalPartList", partParam); if(partList != null && !partList.isEmpty()){ html.append("
"); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); int idx = 1; for(Map partInfo : partList){ html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); html.append(""); } html.append("
No품번품명규격수량단가금액거래처
").append(idx++).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("PART_NO")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("PART_NAME")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("SPEC")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("QTY")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("UNIT_PRICE")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("TOTAL_PRICE")))).append("").append(escapeHtml(CommonUtils.checkNull(partInfo.get("VENDOR_NAME")))).append("
"); } } catch(Exception e){ System.err.println("품의서 품목 리스트 조회 오류: " + e.getMessage()); } // 비고 if(!remark.isEmpty()){ html.append("

비고: ").append(escapeHtml(remark)).append("

"); } html.append("
"); return html.toString(); } /** * 품의서 JSP(proposalFormPopUp.jsp)와 동일한 레이아웃의 HTML 파일 생성 * 결재 첨부파일용 (입력 필드 없이 값만 표시) */ private String buildProposalFormFileHtml(Map proposalInfo, List partList){ String proposalNo = CommonUtils.checkNull(proposalInfo.get("PROPOSAL_NO")); String regdate = CommonUtils.checkNull(proposalInfo.get("REGDATE_TITLE")); String writerName = CommonUtils.checkNull(proposalInfo.get("WRITER_NAME")); String recipientRef = CommonUtils.checkNull(proposalInfo.get("RECIPIENT_REF")); String executor = CommonUtils.checkNull(proposalInfo.get("EXECUTOR")); String executionDate = CommonUtils.checkNull(proposalInfo.get("EXECUTION_DATE_TITLE")); String title = CommonUtils.checkNull(proposalInfo.get("TITLE")); String remark = CommonUtils.checkNull(proposalInfo.get("REMARK")); // 부서명/기안자명 분리 (WRITER_NAME = "경영지원팀 관리자" 형식) String deptName = "-"; String writerOnly = "-"; if(!writerName.isEmpty()){ if(writerName.contains(" ")){ deptName = writerName.substring(0, writerName.indexOf(" ")); writerOnly = writerName.substring(writerName.lastIndexOf(" ") + 1); } else { deptName = writerName; writerOnly = writerName; } } // 합계 계산 long totalAmount = 0; if(partList != null){ for(Map part : partList){ try { Object tp = part.get("TOTAL_PRICE"); if(tp != null) totalAmount += Long.parseLong(tp.toString()); } catch(Exception ignore){} } } StringBuilder h = new StringBuilder(); h.append(""); h.append("구매품의서 - ").append(escapeHtml(proposalNo)).append(""); h.append(""); h.append("
"); // 제목 h.append("
구 매 품 의 서
"); // 상단 기본정보 h.append("
"); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append("
품 의 번 호").append(escapeHtml(proposalNo)).append("
작 성 일 자").append(escapeHtml(regdate)).append("
기 안 부 서").append(escapeHtml(deptName)).append("
기 안 자").append(escapeHtml(writerOnly)).append("
"); // 하단 기본정보 (수신및참조, 시행자, 시행일자, 제목) h.append("
"); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append("
수신및참조").append(escapeHtml(recipientRef)).append("
시 행 자").append(escapeHtml(executor)).append("
시행일자").append(escapeHtml(executionDate)).append("
제    목").append(escapeHtml(title)).append("
"); // 개정 정보 h.append("
[구매품의서 개정 : 22.05.17]
"); // 중간 정보 섹션 h.append("
"); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append("

부 서소속팀날 짜").append(escapeHtml(regdate)).append("총 합 계
").append(escapeHtml(deptName)).append("").append(escapeHtml(deptName)).append("기 안 자").append(escapeHtml(writerOnly)).append("").append(formatNumber(totalAmount)).append("
"); // 품목 테이블 h.append("
"); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); if(partList != null && !partList.isEmpty()){ int idx = 1; for(Map part : partList){ String partName = CommonUtils.checkNull(part.get("PART_NAME")); String spec = CommonUtils.checkNull(part.get("SPEC")); String partRemark = CommonUtils.checkNull(part.get("REMARK")); String deliveryDate = CommonUtils.checkNull(part.get("DELIVERY_REQUEST_DATE_TITLE")); String vendorName = CommonUtils.checkNull(part.get("VENDOR_NAME")); String qty = CommonUtils.checkNull(part.get("QTY")); String unit = CommonUtils.checkNull(part.get("UNIT_NAME")); String unitPrice = CommonUtils.checkNull(part.get("UNIT_PRICE")); String totalPrice = CommonUtils.checkNull(part.get("TOTAL_PRICE")); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); h.append(""); } } else { h.append(""); } h.append("
No.목 적품명 / 규격납 기 일업 체 명수량단위단가합 계
").append(idx++).append("").append(escapeHtml(partRemark)).append("").append(escapeHtml(partName)); if(!spec.isEmpty()) h.append("
(").append(escapeHtml(spec)).append(")"); h.append("
").append(escapeHtml(deliveryDate)).append("").append(escapeHtml(vendorName)).append("").append(formatNumber(qty)).append("").append(escapeHtml(unit)).append("").append(formatNumber(unitPrice)).append("").append(formatNumber(totalPrice)).append("
등록된 품목이 없습니다.
"); // 참조문서 h.append(""); h.append(""); h.append("
참 조 문 서선택된 문서가 없습니다.
"); h.append("
"); return h.toString(); } /** * 숫자 천단위 콤마 포맷 */ private String formatNumber(Object value){ if(value == null) return "0"; try { long num = Long.parseLong(value.toString().replaceAll("[^0-9\\-]", "")); return String.format("%,d", num); } catch(Exception e){ return value.toString(); } } /** * HTML 이스케이프 (XSS 방지) */ private String escapeHtml(String value){ if(value == null || value.isEmpty()) return ""; return value.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """); } /** * 결재 상태코드 → 한글명 변환 */ private String getDocStsName(String docSts){ if("10".equals(docSts)) return "임시보관"; if("20".equals(docSts)) return "상신"; if("30".equals(docSts)) return "진행"; if("40".equals(docSts)) return "발신종결"; if("90".equals(docSts)) return "종결"; if("100".equals(docSts)) return "반려"; if("110".equals(docSts)) return "보류"; return "기타(" + docSts + ")"; } public Map checkApprovalComplete(Map paramMap){ Map resultMap = new HashMap(); SqlSession sqlSession = null; try{ sqlSession = SqlMapConfig.getInstance().getSqlSession(); String approvalObjId = CommonUtils.checkNull(paramMap.get("approvalObjId")); if(!"".equals(approvalObjId)){ Map sqlParamMap = new HashMap(); sqlParamMap.put("approvalObjId", approvalObjId); // 결재 정보 조회 Map approvalInfo = sqlSession.selectOne("approval.getApprovalInfo", sqlParamMap); if(approvalInfo != null) { approvalInfo = CommonUtils.toUpperCaseMapKey(approvalInfo); String status = CommonUtils.checkNull(approvalInfo.get("STATUS")); String targetType = CommonUtils.checkNull(approvalInfo.get("TARGET_TYPE")); String targetObjId = CommonUtils.checkNull(approvalInfo.get("TARGET_OBJID")); // 결재완료 상태인지 확인 if("complete".equals(status)) { resultMap.put("isComplete", "Y"); // CONTRACT_ESTIMATE인 경우 CONTRACT_OBJID 조회 if("CONTRACT_ESTIMATE".equals(targetType)) { Map estParam = new HashMap(); estParam.put("estObjId", targetObjId); Map estInfo = sqlSession.selectOne("approval.getEstimateContractObjId", estParam); if(estInfo != null) { estInfo = CommonUtils.toUpperCaseMapKey(estInfo); resultMap.put("contractObjId", CommonUtils.checkNull(estInfo.get("CONTRACT_OBJID"))); } } } else { resultMap.put("isComplete", "N"); } } else { resultMap.put("isComplete", "N"); } } else { resultMap.put("isComplete", "N"); } }catch(Exception e){ e.printStackTrace(); resultMap.put("isComplete", "N"); }finally{ if(sqlSession != null) sqlSession.close(); } return resultMap; } }