diff --git a/pom.xml b/pom.xml index 5878c03c..7a7f5633 100644 --- a/pom.xml +++ b/pom.xml @@ -144,11 +144,12 @@ 1.1.2 - - cglib - cglib - 3.1 - + + + cglib + cglib + 3.3.0 + org.antlr diff --git a/src/main/java/itn/com/cmm/util/MsgSendUtils.java b/src/main/java/itn/com/cmm/util/MsgSendUtils.java index 1801fd45..339137e9 100644 --- a/src/main/java/itn/com/cmm/util/MsgSendUtils.java +++ b/src/main/java/itn/com/cmm/util/MsgSendUtils.java @@ -23,6 +23,7 @@ import itn.com.cmm.MjonMsgSendVO; import itn.com.cmm.OptimalMsgResultDTO; import itn.let.mail.service.StatusResponse; import itn.let.mjo.event.service.MjonEventVO; +import itn.let.mjo.mjocommon.MjonCommon; import itn.let.mjo.msg.service.MjonMsgVO; import itn.let.mjo.msgagent.service.MjonMsgAgentStsVO; import itn.let.mjo.spammsg.web.ComGetSpamStringParser; @@ -55,26 +56,6 @@ public final class MsgSendUtils { // 이벤트 최저 잔액 public static final double MIN_EVENT_REMAIN_CASH = 7.5; // 이벤트 최소 잔액 - /** - * @methodName : getSmsTxtBytes - * @author : 이호영 - * @date : 2024.09.23 - * @description : sms 텍스트 바이트 계산 후 return; - * @param smsTxt - * @return - * @throws UnsupportedEncodingException - */ - public static int getSmsTxtBytes(String smsTxt) throws UnsupportedEncodingException { //문자열 길이 체크 해주기 - int smsBytes = 0; - //문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산 - String charset = "euc-kr"; - if(StringUtils.isNotEmpty(smsTxt)) { - String smsCont = smsTxt.replace("\r\n", "\n"); - smsBytes = smsCont.getBytes(charset).length; - } -// log.info(" + smsBytes :: [{}]", smsBytes); - return smsBytes; - } /** * @methodName : getMsgType @@ -96,7 +77,7 @@ public final class MsgSendUtils { // msgType = "4"; // } - int smsTxtByte = getSmsTxtBytes(p_smsTxt); + int smsTxtByte = MjonCommon.getSmsTxtBytes(p_smsTxt); String msgType = SHORT_MSG_TYPE; // 1. 2000 Byte 초과는 에러 처리 @@ -648,7 +629,7 @@ public final class MsgSendUtils { // 각 가격을 합산 totalPrice += Float.parseFloat(eachPrice); } - + mjonMsgVO.setTotalPrice(totalPrice); } diff --git a/src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java b/src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java new file mode 100644 index 00000000..457326c0 --- /dev/null +++ b/src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java @@ -0,0 +1,144 @@ +package itn.com.cmm.util; + +import org.apache.commons.lang3.StringUtils; + +import itn.let.kakao.kakaoComm.KakaoVO; +import itn.let.mjo.msg.service.MjonMsgVO; + +public class SlackMessageFormatUtil { + + private static final String PREFIX_SMISHING = "[스미싱의심]"; + private static final String PREFIX_RESERVE = "[예약]"; + private static final String PREFIX_IMAGE = "그림문자 "; + + /** + * 일반 SMS 메시지 텍스트 포맷팅 + */ + public static String formatSmsText(MjonMsgVO mjonMsgVO) { + String smsTxt = mjonMsgVO.getSmsTxt(); + String reserveYn = safeGetString(mjonMsgVO.getReserveYn()); + String delayYn = safeGetString(mjonMsgVO.getDelayYn()); + String smishingYn = safeGetString(mjonMsgVO.getSmishingYn()); + + // 공통 텍스트 포맷팅 로직 적용 + smsTxt = formatMessagePrefix(smsTxt, reserveYn, + "Y".equals(smishingYn) || "Y".equals(delayYn)); + + // 그림 문자 처리 (SMS 전용 로직) + int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0); + if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isEmpty(smsTxt)) { + smsTxt = "그림문자 " + smsTxt; + } + + return smsTxt; + } + + /** + * 카카오톡 메시지 텍스트 포맷팅 + */ + public static String formatKakaoText(KakaoVO kakaoVO) { + String smsTxt = kakaoVO.getTemplateContent(); + String reserveYn = safeGetString(kakaoVO.getReserveYn()); + String atDelayYn = safeGetString(kakaoVO.getAtDelayYn()); + + // 공통 텍스트 포맷팅 로직 적용 + return formatMessagePrefix(smsTxt, reserveYn, "Y".equals(atDelayYn)); + } + + + public static String formatSandName(MjonMsgVO mjonMsgVO) { + String userId = mjonMsgVO.getUserId(); + String callFrom = mjonMsgVO.getCallFrom(); + String msgType = getMessageTypeLabel(mjonMsgVO.getMsgType(), mjonMsgVO.getFileCnt()); + return String.format("[%s][%s]%s", userId, callFrom, msgType); + } + + /** + * 메시지 접두사 포맷팅 공통 로직 (예약 및 스미싱 의심 접두사 처리) + * + * @param messageText 원본 메시지 텍스트 + * @param reserveYn 예약 여부 + * @param isSmishing 스미싱 의심 여부 + * @return 포맷팅된 메시지 텍스트 + */ + public static String formatMessagePrefix(String messageText, String reserveYn, boolean isSmishing) { + if ("Y".equals(reserveYn)) { + return isSmishing ? PREFIX_SMISHING + PREFIX_RESERVE + messageText : PREFIX_RESERVE + messageText; + } else if (isSmishing) { + return PREFIX_SMISHING + messageText; + } + return messageText; + } + + /** + * @카카오톡용 sandName 포맷팅 메서드 + */ + public static String formatKakaoSandName(KakaoVO kakaoVO) { + String userId = kakaoVO.getUserId(); + String callFrom = kakaoVO.getCallFrom(); + String msgType = getKakaoMessageTypeLabel(kakaoVO.getMsgType()); + return String.format("[%s][%s]%s", userId, callFrom, msgType); + } + + /** + * 메시지 타입 레이블 반환 (SMS 전용) + * + * @param msgType 메시지 타입 + * @param fileCnt 파일 개수 + * @return 메시지 타입 레이블 + */ + public static String getMessageTypeLabel(String msgType, String fileCnt) { + int fileCount = parseIntOrDefault(fileCnt, 0); + + switch (msgType) { + case "4": + return "[단문]"; + case "6": + return fileCount == 0 ? "[장문]" : "[그림]"; + default: + return ""; + } + } + + /** + * 카카오톡 메시지 타입 레이블 반환 + * + * @param msgType 메시지 타입 + * @return 메시지 타입 레이블 + */ + public static String getKakaoMessageTypeLabel(String msgType) { + switch (msgType) { + case "8": + return "[알림톡]"; + case "9": + return "[친구톡]"; + default: + return ""; + } + } + + /** + * 정수로 변환, 변환 실패 시 기본값 반환 + * + * @param value 변환할 문자열 + * @param defaultValue 기본값 + * @return 변환된 정수 또는 기본값 + */ + public static int parseIntOrDefault(String value, int defaultValue) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + /** + * 안전하게 문자열 가져오기 (null 체크) + * + * @param value 원본 문자열 + * @return 원본 문자열 또는 빈 문자열 + */ + public static String safeGetString(String value) { + return value == null ? "" : value; + } +} diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java index 516043b6..759f341c 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoButtonVO.java @@ -1,5 +1,9 @@ package itn.let.kakao.kakaoComm; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + /** * @FileName : KakaoButtonVO.java * @Project : mjon @@ -8,6 +12,9 @@ package itn.let.kakao.kakaoComm; * @프로그램 설명 : button, quickReplies 변수 */ +@ToString +@Getter +@Setter public class KakaoButtonVO { private String name = ""; // 버튼명 - linkType “AC” 선택 시 버튼명은 “채널추가” 로 고정 @@ -18,48 +25,4 @@ public class KakaoButtonVO { private String linkPc = ""; // PC 웹 링크 주소 (WL 사용시 선택) private String pluginId = ""; // 플러그인 ID (P1, P2, P3 사용시 필수) - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public String getLinkType() { - return linkType; - } - public void setLinkType(String linkType) { - this.linkType = linkType; - } - public String getLinkAnd() { - return linkAnd; - } - public void setLinkAnd(String linkAnd) { - this.linkAnd = linkAnd; - } - public String getLinkIos() { - return linkIos; - } - public void setLinkIos(String linkIos) { - this.linkIos = linkIos; - } - public String getLinkMo() { - return linkMo; - } - public void setLinkMo(String linkMo) { - this.linkMo = linkMo; - } - public String getLinkPc() { - return linkPc; - } - public void setLinkPc(String linkPc) { - this.linkPc = linkPc; - } - public String getPluginId() { - return pluginId; - } - public void setPluginId(String pluginId) { - this.pluginId = pluginId; - } - - } diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java index 94598ed0..2b95d94b 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoCommentVO.java @@ -3,6 +3,10 @@ package itn.let.kakao.kakaoComm; import java.util.ArrayList; import java.util.List; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + /** * @FileName : KakaoCommentVO.java * @Project : mjon @@ -11,6 +15,9 @@ import java.util.List; * @프로그램 설명 : comment 변수 */ +@ToString +@Getter +@Setter public class KakaoCommentVO { private String content = ""; // 댓글 본분 @@ -26,60 +33,4 @@ public class KakaoCommentVO { private String originalFileName = ""; private String filePath = ""; - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getOriginalFileName() { - return originalFileName; - } - - public void setOriginalFileName(String originalFileName) { - this.originalFileName = originalFileName; - } - - public String getFilePath() { - return filePath; - } - - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - public List getAttachFileList() { - return attachFileList; - } - - public void setAttachFileList(List attachFileList) { - this.attachFileList = attachFileList; - } } diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java index bb259b28..05cba634 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoReturnVO.java @@ -4,6 +4,9 @@ import java.util.ArrayList; import java.util.List; import itn.com.cmm.ComDefaultVO; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; /** * @FileName : KakaoReturnVO.java @@ -13,6 +16,9 @@ import itn.com.cmm.ComDefaultVO; * @프로그램 설명 : 카카오톡 리턴 변수 목록 */ +@Getter +@Setter +@ToString public class KakaoReturnVO extends ComDefaultVO{ private static final long serialVersionUID = 1L; @@ -130,415 +136,4 @@ public class KakaoReturnVO extends ComDefaultVO{ private String businessType = ""; //카카오톡 채널 비즈니스 인증 타입 - public static long getSerialversionuid() { - return serialVersionUID; - } - - public String getBizReturnMsg() { - return bizReturnMsg; - } - - public void setBizReturnMsg(String bizReturnMsg) { - this.bizReturnMsg = bizReturnMsg; - } - - public String getBizReturnCode() { - return bizReturnCode; - } - - public void setBizReturnCode(String bizReturnCode) { - this.bizReturnCode = bizReturnCode; - } - - public String getProfileId() { - return profileId; - } - - public void setProfileId(String profileId) { - this.profileId = profileId; - } - - public String getTotalCount() { - return totalCount; - } - - public void setTotalCount(String totalCount) { - this.totalCount = totalCount; - } - - public String getTotalPage() { - return totalPage; - } - - public void setTotalPage(String totalPage) { - this.totalPage = totalPage; - } - - public String getCurrentPage() { - return currentPage; - } - - public void setCurrentPage(String currentPage) { - this.currentPage = currentPage; - } - - public String getSenderKey() { - return senderKey; - } - - public void setSenderKey(String senderKey) { - this.senderKey = senderKey; - } - - public String getSenderKeyType() { - return senderKeyType; - } - - public void setSenderKeyType(String senderKeyType) { - this.senderKeyType = senderKeyType; - } - - public String getTemplateCode() { - return templateCode; - } - - public void setTemplateCode(String templateCode) { - this.templateCode = templateCode; - } - - public String getTemplateName() { - return templateName; - } - - public void setTemplateName(String templateName) { - this.templateName = templateName; - } - - public String getCategoryCode() { - return categoryCode; - } - - public void setCategoryCode(String categoryCode) { - this.categoryCode = categoryCode; - } - - public String getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - public String getModifiedAt() { - return modifiedAt; - } - - public void setModifiedAt(String modifiedAt) { - this.modifiedAt = modifiedAt; - } - - public String getServiceStatus() { - return serviceStatus; - } - - public void setServiceStatus(String serviceStatus) { - this.serviceStatus = serviceStatus; - } - - public List getTemplatList() { - return templatList; - } - - public void setTemplatList(List templatList) { - this.templatList = templatList; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public boolean isBlock() { - return block; - } - - public void setBlock(boolean block) { - this.block = block; - } - - public boolean isDormant() { - return dormant; - } - - public void setDormant(boolean dormant) { - this.dormant = dormant; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getImageUrl() { - return imageUrl; - } - - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } - - public String getListTitle() { - return listTitle; - } - - public void setListTitle(String listTitle) { - this.listTitle = listTitle; - } - - public String getListDescription() { - return listDescription; - } - - public void setListDescription(String listDescription) { - this.listDescription = listDescription; - } - - public String getSumTitle() { - return sumTitle; - } - - public void setSumTitle(String sumTitle) { - this.sumTitle = sumTitle; - } - - public String getSumDescription() { - return sumDescription; - } - - public void setSumDescription(String sumDescription) { - this.sumDescription = sumDescription; - } - - public String getProfileStatus() { - return profileStatus; - } - - public void setProfileStatus(String profileStatus) { - this.profileStatus = profileStatus; - } - - public boolean isAlimtalk() { - return alimtalk; - } - - public void setAlimtalk(boolean alimtalk) { - this.alimtalk = alimtalk; - } - - public boolean isBizchat() { - return bizchat; - } - - public void setBizchat(boolean bizchat) { - this.bizchat = bizchat; - } - - public boolean isBrandtalk() { - return brandtalk; - } - - public void setBrandtalk(boolean brandtalk) { - this.brandtalk = brandtalk; - } - - public String getCommittalCompanyName() { - return committalCompanyName; - } - - public void setCommittalCompanyName(String committalCompanyName) { - this.committalCompanyName = committalCompanyName; - } - - public String getChannelKey() { - return channelKey; - } - - public void setChannelKey(String channelKey) { - this.channelKey = channelKey; - } - - public boolean isBusinessProfile() { - return businessProfile; - } - - public void setBusinessProfile(boolean businessProfile) { - this.businessProfile = businessProfile; - } - - public String getBusinessType() { - return businessType; - } - - public void setBusinessType(String businessType) { - this.businessType = businessType; - } - - public String getTemplateMessageType() { - return templateMessageType; - } - - public void setTemplateMessageType(String templateMessageType) { - this.templateMessageType = templateMessageType; - } - - public String getTemplateEmphasizeType() { - return templateEmphasizeType; - } - - public void setTemplateEmphasizeType(String templateEmphasizeType) { - this.templateEmphasizeType = templateEmphasizeType; - } - - public String getTemplateContent() { - return templateContent; - } - - public void setTemplateContent(String templateContent) { - this.templateContent = templateContent; - } - - public String getTemplateExtra() { - return templateExtra; - } - - public void setTemplateExtra(String templateExtra) { - this.templateExtra = templateExtra; - } - - public String getTemplateAd() { - return templateAd; - } - - public void setTemplateAd(String templateAd) { - this.templateAd = templateAd; - } - - public String getTemplateImageName() { - return templateImageName; - } - - public void setTemplateImageName(String templateImageName) { - this.templateImageName = templateImageName; - } - - public String getTemplateImageUrl() { - return templateImageUrl; - } - - public void setTemplateImageUrl(String templateImageUrl) { - this.templateImageUrl = templateImageUrl; - } - - public String getTemplateTitle() { - return templateTitle; - } - - public void setTemplateTitle(String templateTitle) { - this.templateTitle = templateTitle; - } - - public String getTemplateSubtitle() { - return templateSubtitle; - } - - public void setTemplateSubtitle(String templateSubtitle) { - this.templateSubtitle = templateSubtitle; - } - - public String getTemplateHeader() { - return templateHeader; - } - - public void setTemplateHeader(String templateHeader) { - this.templateHeader = templateHeader; - } - - public Boolean getSecurityFlag() { - return securityFlag; - } - - public void setSecurityFlag(Boolean securityFlag) { - this.securityFlag = securityFlag; - } - - public String getInspectionStatus() { - return inspectionStatus; - } - - public void setInspectionStatus(String inspectionStatus) { - this.inspectionStatus = inspectionStatus; - } - - public List getButtonList() { - return buttonList; - } - - public void setButtonList(List buttonList) { - this.buttonList = buttonList; - } - - public List getQuickReplyList() { - return quickReplyList; - } - - public void setQuickReplyList(List quickReplyList) { - this.quickReplyList = quickReplyList; - } - - public List getCommentList() { - return commentList; - } - - public void setCommentList(List commentList) { - this.commentList = commentList; - } - - public List getItemList() { - return itemList; - } - - public void setItemList(List itemList) { - this.itemList = itemList; - } } diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java new file mode 100644 index 00000000..480cf85a --- /dev/null +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoSendAdvcVO.java @@ -0,0 +1,116 @@ +package itn.let.kakao.kakaoComm; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import lombok.Getter; +import lombok.Setter; + +/** +* @FileName : KakaoSendVO.java +* @Project : mjon +* @Date : 2025. 3. 25. +* @작성자 : 이호영 + +* @프로그램 설명 : 문자온 발송부분만 ADVC +*/ +@Getter +@Setter +public class KakaoSendAdvcVO implements Serializable { + + + /** + * + */ + private static final long serialVersionUID = 343099046833205405L; + + // ===== + // Insert 데이터 + private String msgId; // 문자ID + private String msgGroupId; // 전송그룹ID + private String msgGroupCnt; // 전송그룹ID + private String userId; // 사용자ID + private String agentCode; // 전송사코드 + private String senderKey; // 발신프로필 키 + private String templateCode; // 템플릿 코드 + private String callTo; // 수신번호 + private String callFrom; // 발신번호 + private String msgType; // 메시지 타입 + private String templateContent; // 템플릿 내용 + private String templateTitle; // 템플릿 제목 + List buttonList; // 템플릿 버튼 리스트 + private String subMsgSendYn; // 대체문자 전송 여부 + private String subMsgTxt; // 대체문자 내용 + private String subMsgType; // 대체문자 타입 + private String reqDate; // 예약일시 + + private String jsonStr; // jsonStr + + // ===== + // ===== + + private String eachPrice; // sms 단가 + private String smsPrice; // sms 단가 + private String mmsPrice; // mms 단가 + private String totPrice; // mms 단가 + private String befCash; // mms 단가 + private String befPoint; // mms 단가 + private String kakaoAtPrice; // 카카오 알림톡 단가 + private String bizJsonName; // 카카오 알림톡 단가 + private String reserveYn; // 카카오 알림톡 단가 + private String atDelayYn; // 카카오 알림톡 단가 + private String bizKakaoResendOrgnlTxt; // 카카오 알림톡 단가 + private String bizKakaoResendType; // 카카오 알림톡 단가 + + + + + + + @Override + public String toString() { + return "MsgSendVO[" + + "\n msgId=[" + msgId + "]" + + "\n , msgGroupId=[" + msgGroupId + "]" + + "\n , msgGroupCnt=[" + msgGroupCnt + "]" + + "\n , userId=[" + userId + "]" + + "\n , agentCode=[" + agentCode + "]" + + "\n , senderKey=[" + senderKey + "]" + + "\n , templateCode=[" + templateCode + "]" + + "\n , callTo=[" + callTo + "]" + + "\n , callFrom=[" + callFrom + "]" + + "\n , msgType=[" + msgType + "]" + + "\n , templateContent=[" + templateContent + "]" + + "\n , templateTitle=[" + templateTitle + "]" + + "\n , buttonList=[" + buttonList.toString() + "]" + + "\n , subMsgSendYn=[" + subMsgSendYn + "]" + + "\n , subMsgTxt=[" + subMsgTxt + "]" + + "\n , subMsgType=[" + subMsgType + "]" + + "\n , reqDate=[" + reqDate + "]" + + "\n , jsonStr=[" + jsonStr + "]" + + "\n , ==== MJ_MSG_DATA INSERT DATA END =======" + + "\n " + + "\n , eachPrice=[" + eachPrice + "]" + + "\n , smsPrice=[" + smsPrice + "]" + + "\n , mmsPrice=[" + mmsPrice + "]" + + "\n , totPrice=[" + totPrice + "]" + + "\n , befCash=[" + befCash + "]" + + "\n , befPoint=[" + befPoint + "]" + + "\n , kakaoAtPrice=[" + kakaoAtPrice + "]" + + "\n , bizJsonName=[" + bizJsonName + "]" + + "\n , reserveYn=[" + reserveYn + "]" + + "\n , atDelayYn=[" + atDelayYn + "]" + + "\n , bizKakaoResendOrgnlTxt=[" + bizKakaoResendOrgnlTxt + "]" + + "\n , bizKakaoResendType=[" + bizKakaoResendType + "]" + + "\n ]"; + } + + + + + + + + +} diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java index d96b4fb8..ec298ecc 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java @@ -1,21 +1,38 @@ package itn.let.kakao.kakaoComm; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; +import egovframework.rte.fdl.idgnr.EgovIdGnrService; import itn.com.cmm.util.StringUtil; import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave; +import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate; +import itn.let.mail.service.StatusResponse; +import itn.let.mjo.mjocommon.MjonCommon; import itn.let.mjo.msg.service.MjonMsgVO; import itn.let.mjo.msgdata.service.MjonMsgDataService; import itn.let.mjo.spammsg.web.ComGetSpamStringParser; +import itn.let.module.base.PriceAndPoint; import itn.let.sym.site.service.JoinSettingVO; import itn.let.uss.umt.service.MberManageVO; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Component public class KakaoSendUtil { @@ -25,6 +42,374 @@ public class KakaoSendUtil { @Resource(name = "MjonMsgDataService") private MjonMsgDataService mjonMsgDataService; + @Autowired + KakaoApiTemplate kakaoApiTemplate; + + @Autowired + private PriceAndPoint priceAndPoint; + + @Autowired + private MjonCommon mjonCommon; + + // 클래스 수준에서 정적 Pattern 정의 (성능 최적화) + private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("#\\{[^}]+\\}"); + + private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + // 단문 메세지 타입 + public static final String SHORT_MSG_TYPE = "SMS"; + // 장문 메세지 타입 + public static final String LONG_MSG_TYPE = "MMS"; + + /** + * @methodName : populateSendLists _advc + * @author : 이호영 + * @date : 2025. 3. 7. + * @description : 기존 kakaoSendPrice 개선 + * @return : KakaoVO + * @param kakaoVO + * @param statusResponse + * @return + * @throws Exception + * + */ + public List populateSendLists(KakaoVO kakaoVO, boolean isNotified, StatusResponse statusResponse) throws Exception { + + //사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액) +// String befCash = kakaoVO.getBefCash(); + + + + + log.info(" +kakaoVO.getVarListMap().size() :: [{}]", kakaoVO.getVarListMap().size()); + + List kakaoSendAdvcListVO = new ArrayList<>(); + Calendar calendar = setupBaseDate(kakaoVO, isNotified); + + + + KakaoReturnVO templateDetail = kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO); + String templateContent = templateDetail.getTemplateContent(); // 알림톡 템플릿 + kakaoVO.setTemplateContent(templateContent); + String templateTitle = templateDetail.getTemplateTitle(); + + +// log.info(" + templateDetail :: [{}]", templateDetail); +// templateDetail.getButtonList().forEach(t->log.info(" + ButtonList :: [{}]", t.toString())); + + Boolean hasContentReplacement = this.replBooleanStrChecker(templateContent); + Boolean hasTitleReplacement = this.replBooleanStrChecker(templateTitle); + Boolean hasButtonReplacement = this.needsButtonReplacement(templateDetail.getButtonList()); + + /** @jsonStr 필요유무 */ + boolean hasTitleOrButtons = StringUtils.isNotEmpty(templateTitle) + || CollectionUtils.isNotEmpty(templateDetail.getButtonList()); + + /** @jsonStr 반복유무 */ + boolean needsJsonReplacement = hasTitleReplacement || hasButtonReplacement; + String sharedJsonStr = null; + + String subMsgTxt = kakaoVO.getSubMsgTxt(); // 실패 대체 문자 + + // 시스템 기본 단가 정보 불러오기 + JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo(); + // 사용자 개인 단가 정보 불러오기 + MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(kakaoVO.getUserId()); + + + + + /** @MSGID KEY값 */ + List idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getVarListMap().size()); +// for (int i = 0; i < kakaoSendAdvcListVO.size(); i++) { +// kakaoSendAdvcListVO.get(i).setMsgId(idList.get(i)); +// kakaoSendAdvcListVO.get(i).setBizJsonName(idList.get(i)); +// } + + + + // 분할 건수 카운터 + int counter = 0; +/** @Map에 총 갯수가 수신자 갯수와 동일함 */ + List> varList = kakaoVO.getVarListMap(); + for (int i = 0; i < varList.size(); i++) { +// for(Map variables : kakaoVO.getVarListMap()) { + // 치환 데이터 + Map variables = varList.get(i); + +/** @공통 기본값 */ + KakaoSendAdvcVO sendVO = createSendVO(kakaoVO); + String msgId = idList.get(i); + sendVO.setMsgId(msgId); + + // step1 + // Step 1-1: 값 치환 및 수신번호 셋팅 + // Step 1-2: 수신자 정보 설정 (callToList는 항상 설정). + if (variables.containsKey("callToList")) { + sendVO.setCallTo(variables.get("callToList")); + variables.remove("callToList"); // 사용 후 제거. + } + +/** @Step1-3: 템플릿 치환데이터 설정 */ + if (hasContentReplacement) { + templateContent = mjonCommon.ATReplaceTemplateVariables(templateContent, variables); + if(hasTitleReplacement) { + templateTitle = mjonCommon.ATReplaceTemplateVariables(templateTitle, variables); + } + } +/** @버튼 치환 */ // 버튼 리스트가 있으면 치환 수행, 항상 sendVO에 설정 + List buttonList = templateDetail.getButtonList(); + if(hasButtonReplacement) { + buttonList = replaceButtonLinks(buttonList, variables); + } + sendVO.setButtonList(buttonList); + + sendVO.setTemplateTitle(templateTitle); + sendVO.setTemplateContent(templateContent); + + + // Step 1-4: 실패 대체 문자 치환데이터 설정 + if("Y".equals(kakaoVO.getSubMsgSendYn())) { // 대체문자가 있나? + if ("Y".equals(kakaoVO.getSubMsgTxtReplYn())) { // 치환데이터가 있나? + subMsgTxt = mjonCommon.ATReplaceTemplateVariables(subMsgTxt, variables); + } + sendVO.setSubMsgTxt(subMsgTxt);// 실패 + } + sendVO.setSubMsgSendYn(kakaoVO.getSubMsgSendYn()); + + + /* + log.info("kakaoSendAdvcVO Details: [callTo={}\n, templateContent=\n{}\n, subMsgTxt=\n{}]\n\n\n\n", + kakaoSendAdvcVO.getCallTo(), + kakaoSendAdvcVO.getTemplateContent(), + kakaoSendAdvcVO.getSubMsgTxt() + ); + */ + + // Step1 END + + +// step3 +// 바이트 수 체크 및 금액설정 + + + Float kakaoAtPrice = mberManageVO.getKakaoAtPrice(); + // 유효한 단가 계산 + float shortPrice = getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice()); + float longPrice = getValidPrice(mberManageVO.getLongPrice(), sysJoinSetVO.getLongPrice()); + + + String shortPStr = Float.toString(shortPrice); + String mmsPStr = Float.toString(longPrice); + + // 공통 가격 설정 + sendVO.setSmsPrice(shortPStr); + sendVO.setMmsPrice(mmsPStr); + + + if("Y".equals(kakaoVO.getSubMsgSendYn())) { + int smsTxtByte = mjonCommon.getSmsTxtBytes(sendVO.getSubMsgTxt()); + String sendType = getMsgType(smsTxtByte); + sendVO.setSubMsgType(sendType); + + if ("INVALID".equals(sendType)) { + statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "전송 문자 길이를 초과하였습니다.");return kakaoSendAdvcListVO; + } + + boolean isMms = "MMS".equals(sendType); + sendVO.setEachPrice(isMms ? mmsPStr : shortPStr); + + + } else { + kakaoAtPrice = getValidPrice(mberManageVO.getKakaoAtPrice(), sysJoinSetVO.getKakaoAtPrice()); + sendVO.setEachPrice( Float.toString(kakaoAtPrice) ); + } + + + + // step4 + // 예약 시간 설정 및 분할 데이터 설정 + if ("Y".equalsIgnoreCase(kakaoVO.getReserveYn()) + && "Y".equalsIgnoreCase(kakaoVO.getDivideChk()) + && counter == Integer.parseInt(kakaoVO.getDivideCnt())) + { + counter = 0; + calendar.add(Calendar.MINUTE, Integer.parseInt(kakaoVO.getDivideTime())); + } + counter++; + // 즉시 발송인경우 현재 시간 + // 예약인 경우 위에 설정한 시간 입력 + sendVO.setReqDate(DATE_FORMATTER.format(calendar.getTime())); + + + +/** @step5 전송 메세지 설정 json파일 만들기*/ + // 타이틀과 버튼이 있고 + if(hasTitleOrButtons) { + // 버튼과 타이틀에 치환데이터가 있으면 json String을 계속 생성 + if(needsJsonReplacement) { + sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail); + sendVO.setBizJsonName(msgId); + sendVO.setJsonStr(sharedJsonStr); + } else if (StringUtils.isEmpty(sharedJsonStr)) { + // 치환 데이터가 없고 아직 생성되지 않았으면 한 번만 생성 + sharedJsonStr = kakaoApiJsonSave.kakaoApiJsonSave_advc(sendVO, templateDetail); + sendVO.setBizJsonName(idList.get(0)); + sendVO.setJsonStr(sharedJsonStr); + }else { + sendVO.setBizJsonName(idList.get(0)); + } + + } + kakaoSendAdvcListVO.add(sendVO); + } + + + return kakaoSendAdvcListVO; + } + + private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isNotified) throws ParseException { + // 예약 시간 기본값 설정 + Date now = new Date(); + // ReqDate가 비어 있으면 현재 시간으로 설정, 그렇지 않으면 ReqDate로 설정 + // 화면에서 예약문자면 예약시간을 regDate로 설정한다. + Date baseDate; + if (StringUtils.isEmpty(kakaoVO.getReqDate())) { + kakaoVO.setReqDate(DATE_FORMATTER.format(now)); // ReqDate에 현재 시간 설정 + baseDate = now; + } else { + baseDate = DATE_FORMATTER.parse(kakaoVO.getReqDate()); // ReqDate를 baseDate로 설정 + } + + // 시간 성정 + Calendar calendar = Calendar.getInstance(); + calendar.setTime(baseDate); // calendar에 baseDate 설정 + + // 지연 여부 처리 + // 알림톡 스미싱의심 + 공휴일알림 조건이 맞으면 30분 delay + if ( "Y".equalsIgnoreCase(kakaoVO.getAtSmishingYn()) + && isNotified) { + calendar.add(Calendar.MINUTE, 30); // 모든 시간을 30분 뒤로 미룸 + } + return calendar; + } + + /** + * @methodName : createSendVO + * @author : 이호영 + * @date : 2025. 3. 19. + * @description : populateSendLists 반복에 필요한 공통생성 부분 + * @return : KakaoSendAdvcVO + * @param kakaoVO + * @return + * + */ + private KakaoSendAdvcVO createSendVO(KakaoVO kakaoVO) { + KakaoSendAdvcVO sendVO = new KakaoSendAdvcVO(); + sendVO.setMsgType("8"); + sendVO.setSenderKey(kakaoVO.getSenderKey()); + sendVO.setTemplateCode(kakaoVO.getTemplateCode()); + sendVO.setUserId(kakaoVO.getUserId()); + sendVO.setCallFrom(kakaoVO.getCallFrom()); + sendVO.setAgentCode("04"); + return sendVO; + } + + private List replaceButtonLinks(List buttonList, + Map variables) { + + if (buttonList != null) { + for (KakaoButtonVO button : buttonList) { + // 각 링크 필드에 대해 치환 수행 + if (button.getLinkAnd() != null) { + button.setLinkAnd(mjonCommon.ATReplaceTemplateVariables(button.getLinkAnd(), variables)); + } + if (button.getLinkIos() != null) { + button.setLinkIos(mjonCommon.ATReplaceTemplateVariables(button.getLinkIos(), variables)); + } + if (button.getLinkMo() != null) { + button.setLinkMo(mjonCommon.ATReplaceTemplateVariables(button.getLinkMo(), variables)); + } + if (button.getLinkPc() != null) { + button.setLinkPc(mjonCommon.ATReplaceTemplateVariables(button.getLinkPc(), variables)); + } + } + // 치환된 버튼 리스트를 sendVO에 반영 +// sendVO.setButtonList(buttonList); // KakaoSendAdvcVO에 setButtonList가 있다고 가정 + } + + return buttonList; + } + + /** + * 버튼 리스트에 치환 패턴(#{...})이 있는지 확인합니다. + * @param buttonList 버튼 리스트 (null 가능) + * @return 치환 패턴이 있으면 true, 없으면 false + */ + private boolean needsButtonReplacement(List buttonList) { + if (buttonList == null) { + return false; + } + return buttonList.stream().anyMatch(button -> + replBooleanStrChecker(button.getLinkAnd()) || + replBooleanStrChecker(button.getLinkIos()) || + replBooleanStrChecker(button.getLinkMo()) || + replBooleanStrChecker(button.getLinkPc()) + ); + } + + /** + * 입력 문자열에 치환 패턴(#{...})이 있는지 확인합니다. + * @param input 확인할 문자열 (null 가능) + * @return 치환 패턴이 있으면 true, 없으면 false + */ + private boolean replBooleanStrChecker(String input) { + // #{...} 패턴을 확인하는 정규 표현식 + if (input == null) { + return false; + } + Matcher matcher = REPLACEMENT_PATTERN.matcher(input); + return matcher.find(); + } + + + public Float getValidPrice(Float personalPrice, Float defaultPrice) { + return (personalPrice != null && personalPrice > 0) ? personalPrice : defaultPrice; + } + + + /** + * @methodName : getMsgType + * @author : 이호영 + * @date : 2025. 3. 12. + * @description : 메세지 타입 구하기 + * @return : String + * @param smsTxtByte + * @return + * + */ + private String getMsgType(int smsTxtByte) { + // TODO Auto-generated method stub + + String msgType = SHORT_MSG_TYPE; + + // 1. 2000 Byte 초과는 에러 처리 + if (smsTxtByte > 2000) { + return "INVALID"; + } + + // 2. 문자 길이에 따라 메시지 타입 설정 (90 Byte 초과는 장문) + if (smsTxtByte > 90) { + msgType = LONG_MSG_TYPE; + } + + return msgType; + } + + + + + /** * @Method Name : kakaoSendPrice @@ -34,13 +419,11 @@ public class KakaoSendUtil { */ public KakaoVO kakaoSendPrice(KakaoVO kakaoVO) throws Exception { - //사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액) - String befCash = kakaoVO.getBefCash(); + System.out.println(" :: kakaoSendPrice :: "); + + //사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액) +// String befCash = kakaoVO.getBefCash(); - //VO에서 현재 보유금액이 없으면 디비에서 조회해서 불러옴 - if("".equals(befCash) || befCash == null) { - - } MjonMsgVO mjonMsgVO = new MjonMsgVO(); mjonMsgVO.setUserId(kakaoVO.getUserId()); String userMoney = mjonMsgDataService.selectBeforeCashData(mjonMsgVO); @@ -55,6 +438,7 @@ public class KakaoSendUtil { /** 대체문자 여부 체크(있으면 대체문자 가격으로 없으면 카카오톡 가격으로) */ //대체문자 발송 여부 확인 + System.out.println(" :: kakaoVO.getSubMsgSendYn() :: "+ kakaoVO.getSubMsgSendYn()); if(kakaoVO.getSubMsgSendYn().equals("Y")) { @@ -401,6 +785,107 @@ public class KakaoSendUtil { varValInfo = kakaoVO.getVarValList().get(count); } String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, varValInfo); + setSendMsgVO.setBizJsonName(jsonFileName); //json 파일명 + } + + kakaoSendList.add(setSendMsgVO); + } + kakaoVO.setKakaoSendList(kakaoSendList); + + } catch (Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + + return kakaoVO; + } + + /** + * @methodName : kakaoSendMsg_advc + * @author : 이호영 + * @date : 2025. 3. 13. + * @description : kakaoSendMsg 개선 + * @return : KakaoVO + * @param kakaoVO + * @return + * @throws Exception + * + */ + public KakaoVO kakaoSendMsg_advc(KakaoVO kakaoVO) throws Exception { + List kakaoSendList = new ArrayList(); + //전체 받는사람 수량만큼 반복 확인 + int callToCnt = kakaoVO.getCallToList().length; + try { + for(int count =0; count < callToCnt; count++) { + + KakaoVO setSendMsgVO = new KakaoVO(); + + setSendMsgVO.setDestPhone(kakaoVO.getCallToList()[count]); // 수신 번호 + // 카카오 전송내용 설정 + // 변환문자 포함(Y), 미포함(N) + if(kakaoVO.getTxtReplYn().equals("Y")) { + + String templateContent = kakaoSubMagTxtRepl(kakaoVO.getTemplateContent(), kakaoVO, count); + setSendMsgVO.setTemplateContent(templateContent); + + if(kakaoVO.getTemplateEmphasizeType().equals("TEXT")) { + + String title = kakaoSubMagTxtRepl(kakaoVO.getTemplateTitle(), kakaoVO, count); + String subTitle = kakaoVO.getTemplateSubtitle(); +// title = title +"§§"+ subTitle; + setSendMsgVO.setTemplateEmphasizeType(kakaoVO.getTemplateEmphasizeType()); + setSendMsgVO.setTemplateTitle(title); + } + + }else { + + if(kakaoVO.getTemplateEmphasizeType().equals("TEXT")) { + + String title = kakaoSubMagTxtRepl(kakaoVO.getTemplateTitle(), kakaoVO, count); + String subTitle = kakaoVO.getTemplateSubtitle(); +// title = title +"§§"+ subTitle; + setSendMsgVO.setTemplateEmphasizeType(kakaoVO.getTemplateEmphasizeType()); + setSendMsgVO.setTemplateTitle(title); + } + + // 템플릿 내용 설정 + setSendMsgVO.setTemplateContent(kakaoVO.getTemplateContent()); + } + + //대체문자 포함(Y), 미포함(N) + if(kakaoVO.getSubMsgSendYn().equals("Y")) { + + String charset = "euc-kr"; //문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산 + + String tempSubMagTxt = kakaoVO.getSubMsgTxt().replace("\r\n", "\n"); + kakaoVO.setKakaoSubMagOrgnlTxt(tempSubMagTxt); + if(kakaoVO.getSubMsgTxtReplYn().equals("Y")) { + tempSubMagTxt = kakaoSubMagTxtRepl(tempSubMagTxt, kakaoVO, count); + } + System.out.println("@@ 대체문자내용 : " + tempSubMagTxt); + setSendMsgVO.setSubMsgTxt(tempSubMagTxt); + + int FrBytes = tempSubMagTxt.getBytes(charset).length; + System.out.println("@@ 대체문자길이 : " + FrBytes); + //메세지 길이가 90Byte가 초과시 MMS + if(FrBytes > 90) { + setSendMsgVO.setSubMsgType("MMS"); + }else {// 아니면 SMS + setSendMsgVO.setSubMsgType("SMS"); + } + + System.out.println("@@ 대체문자타입 : " + setSendMsgVO.getSubMsgType()); + } + + if(kakaoVO.getBizJsonYn().equals("Y")) { + kakaoVO.setDestPhone(kakaoVO.getCallToList()[count]); // 수신 번호 + + String[] varValInfo = null; + if( kakaoVO.getVarValList().size() != 0) { + varValInfo = kakaoVO.getVarValList().get(count); + } + String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, varValInfo); +// String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave_advc(kakaoVO, varValInfo); // String jsonFileName = kakaoApiJsonSave.kakaoApiJsonSave(kakaoVO, kakaoVO.getVarValList().get(count)); setSendMsgVO.setBizJsonName(jsonFileName); //json 파일명 } @@ -509,6 +994,7 @@ public class KakaoSendUtil { public String kakaoSubMagTxtRepl(String tempSubMagTxt, KakaoVO kakaoVO, int count) { + System.out.println("tempSubMagTxt : "+ tempSubMagTxt); // String tempSubMagTxt = kakaoVO.getSubMsgTxt().replace("\r\n", "\n"); // String tempSubMagTxt = msgTxt; @@ -551,6 +1037,7 @@ public class KakaoSendUtil { return tempSubMagTxt; } + public String kakaoFTSubMagTxtRepl(String tempSubMagTxt, KakaoVO kakaoVO, int count) throws Exception{ List varValList = kakaoVO.getVarValList(); @@ -704,5 +1191,10 @@ public class KakaoSendUtil { //} return ""; } - + + public static void statusResponseSet (StatusResponse statusResponse, HttpStatus httpStatus, String msg ) { + statusResponse.setStatus(httpStatus); + statusResponse.setMessage(msg); + + } } diff --git a/src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java b/src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java index fd0a935f..527f146f 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java +++ b/src/main/java/itn/let/kakao/kakaoComm/KakaoVO.java @@ -2,8 +2,11 @@ package itn.let.kakao.kakaoComm; import java.util.ArrayList; import java.util.List; +import java.util.Map; import itn.let.mjo.msg.service.MjonMsgVO; +import lombok.Getter; +import lombok.Setter; /** * @FileName : KakaoVO.java @@ -13,6 +16,8 @@ import itn.let.mjo.msg.service.MjonMsgVO; * @프로그램 설명 : 카카오톡 요청 변수 목록 (문자온VO를 상속 받음) */ +@Getter +@Setter public class KakaoVO extends MjonMsgVO{ private static final long serialVersionUID = 536382850588307019L; @@ -255,1030 +260,60 @@ public class KakaoVO extends MjonMsgVO{ private String msgResendAllTmpKey; private String msgResendAllYellowId; - public String getSuccessDay() { - return successDay; - } - - public void setSuccessDay(String successDay) { - this.successDay = successDay; - } - - public String getSuccessMonth() { - return successMonth; - } - - public void setSuccessMonth(String successMonth) { - this.successMonth = successMonth; - } - - public String getSuccessYear() { - return successYear; - } - - public void setSuccessYear(String successYear) { - this.successYear = successYear; - } - - public String getSuccessCntDay() { - return successCntDay; - } - - public void setSuccessCntDay(String successCntDay) { - this.successCntDay = successCntDay; - } - - public String getSuccessCntMonth() { - return successCntMonth; - } - - public void setSuccessCntMonth(String successCntMonth) { - this.successCntMonth = successCntMonth; - } - - public String getSuccessCntYear() { - return successCntYear; - } - - public void setSuccessCntYear(String successCntYear) { - this.successCntYear = successCntYear; - } - - public static long getSerialversionuid() { - return serialVersionUID; - } - - public String getCategoryDepth() { - return categoryDepth; - } - - public void setCategoryDepth(String categoryDepth) { - this.categoryDepth = categoryDepth; - } - - public String getCategoryType() { - return categoryType; - } - - public void setCategoryType(String categoryType) { - this.categoryType = categoryType; - } - - public String getCategoryCode() { - return categoryCode; - } - - public void setCategoryCode(String categoryCode) { - this.categoryCode = categoryCode; - } - - public String getCategoryGroupName() { - return categoryGroupName; - } - - public void setCategoryGroupName(String categoryGroupName) { - this.categoryGroupName = categoryGroupName; - } - - public String getCategoryName() { - return categoryName; - } - - public void setCategoryName(String categoryName) { - this.categoryName = categoryName; - } - - public String getCategoryInclusion() { - return categoryInclusion; - } - - public void setCategoryInclusion(String categoryInclusion) { - this.categoryInclusion = categoryInclusion; - } - - public String getCategoryExclusion() { - return categoryExclusion; - } - - public void setCategoryExclusion(String categoryExclusion) { - this.categoryExclusion = categoryExclusion; - } - - public String getBizUrl() { - return bizUrl; - } - - public void setBizUrl(String bizUrl) { - this.bizUrl = bizUrl; - } - - public String getBizReturnMsg() { - return bizReturnMsg; - } - - public void setBizReturnMsg(String bizReturnMsg) { - this.bizReturnMsg = bizReturnMsg; - } - - public String getBizReturnCode() { - return bizReturnCode; - } - - public void setBizReturnCode(String bizReturnCode) { - this.bizReturnCode = bizReturnCode; - } - - public String getPhoneNumber() { - return phoneNumber; - } - - public void setPhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - - public String getYellowId() { - return yellowId; - } - - public void setYellowId(String yellowId) { - this.yellowId = yellowId; - } - - public String getBizJsonName() { - return bizJsonName; - } - - public void setBizJsonName(String bizJsonName) { - this.bizJsonName = bizJsonName; - } - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public String getSenderKey() { - return senderKey; - } - - public void setSenderKey(String senderKey) { - this.senderKey = senderKey; - } - - public String getProfileId() { - return profileId; - } - - public void setProfileId(String profileId) { - this.profileId = profileId; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getImgTitle() { - return imgTitle; - } - - public void setImgTitle(String imgTitle) { - this.imgTitle = imgTitle; - } - - public String getImageType() { - return imageType; - } - - public void setImageType(String imageType) { - this.imageType = imageType; - } - - public String getImgLink() { - return imgLink; - } - - public void setImgLink(String imgLink) { - this.imgLink = imgLink; - } - - public String getTemplateName() { - return templateName; - } - - public void setTemplateName(String templateName) { - this.templateName = templateName; - } - - public String getTemplateMessageType() { - return templateMessageType; - } - - public void setTemplateMessageType(String templateMessageType) { - this.templateMessageType = templateMessageType; - } - - public String getTemplateEmphasizeType() { - return templateEmphasizeType; - } - - public void setTemplateEmphasizeType(String templateEmphasizeType) { - this.templateEmphasizeType = templateEmphasizeType; - } - - public String getTemplateContent() { - return templateContent; - } - - public void setTemplateContent(String templateContent) { - this.templateContent = templateContent; - } - - public String getTemplateExtra() { - return templateExtra; - } - - public void setTemplateExtra(String templateExtra) { - this.templateExtra = templateExtra; - } - - public String getTamplateAd() { - return tamplateAd; - } - - public void setTamplateAd(String tamplateAd) { - this.tamplateAd = tamplateAd; - } - - public String getTemplateImageName() { - return templateImageName; - } - - public void setTemplateImageName(String templateImageName) { - this.templateImageName = templateImageName; - } - - public String getTemplateImageUrl() { - return templateImageUrl; - } - - public void setTemplateImageUrl(String templateImageUrl) { - this.templateImageUrl = templateImageUrl; - } - - public String getTemplateTitle() { - return templateTitle; - } - - public void setTemplateTitle(String templateTitle) { - this.templateTitle = templateTitle; - } - - public String getTemplateSubtitle() { - return templateSubtitle; - } - - public void setTemplateSubtitle(String templateSubtitle) { - this.templateSubtitle = templateSubtitle; - } - - public String getTemplateHeader() { - return templateHeader; - } - - public void setTemplateHeader(String templateHeader) { - this.templateHeader = templateHeader; - } - - public Boolean getSecurityFlag() { - return securityFlag; - } - - public void setSecurityFlag(Boolean securityFlag) { - this.securityFlag = securityFlag; - } - - public List getButtonVOList() { - return buttonVOList; - } - - public void setButtonVOList(List buttonVOList) { - this.buttonVOList = buttonVOList; - } - - public String getButtonName() { - return buttonName; - } - - public void setButtonName(String buttonName) { - this.buttonName = buttonName; - } - - public String getButtonLinkType() { - return buttonLinkType; - } - - public void setButtonLinkType(String buttonLinkType) { - this.buttonLinkType = buttonLinkType; - } - - public String getButtonLinkAnd() { - return buttonLinkAnd; - } - - public void setButtonLinkAnd(String buttonLinkAnd) { - this.buttonLinkAnd = buttonLinkAnd; - } - - public String getButtonLinkIos() { - return buttonLinkIos; - } - - public void setButtonLinkIos(String buttonLinkIos) { - this.buttonLinkIos = buttonLinkIos; - } - - public String getButtonLinkMo() { - return buttonLinkMo; - } - - public void setButtonLinkMo(String buttonLinkMo) { - this.buttonLinkMo = buttonLinkMo; - } - - public String getButtonLinkPc() { - return buttonLinkPc; - } - - public void setButtonLinkPc(String buttonLinkPc) { - this.buttonLinkPc = buttonLinkPc; - } - - public String getButtonPluginId() { - return buttonPluginId; - } - - public void setButtonPluginId(String buttonPluginId) { - this.buttonPluginId = buttonPluginId; - } - - public String getQuickName() { - return quickName; - } - - public void setQuickName(String quickName) { - this.quickName = quickName; - } - - public String getQuickLinkType() { - return quickLinkType; - } - - public void setQuickLinkType(String quickLinkType) { - this.quickLinkType = quickLinkType; - } - - public String getQuickLinkAnd() { - return quickLinkAnd; - } - - public void setQuickLinkAnd(String quickLinkAnd) { - this.quickLinkAnd = quickLinkAnd; - } - - public String getQuickLinkIos() { - return quickLinkIos; - } - - public void setQuickLinkIos(String quickLinkIos) { - this.quickLinkIos = quickLinkIos; - } - - public String getQuickLinkMo() { - return quickLinkMo; - } - - public void setQuickLinkMo(String quickLinkMo) { - this.quickLinkMo = quickLinkMo; - } - - public String getQuickLinkPc() { - return quickLinkPc; - } - - public void setQuickLinkPc(String quickLinkPc) { - this.quickLinkPc = quickLinkPc; - } - - public String getSenderKeyType() { - return senderKeyType; - } - - public void setSenderKeyType(String senderKeyType) { - this.senderKeyType = senderKeyType; - } - - public String getDeleteYn() { - return deleteYn; - } - - public void setDeleteYn(String deleteYn) { - this.deleteYn = deleteYn; - } - - public String getTemplateCode() { - return templateCode; - } - - public void setTemplateCode(String templateCode) { - this.templateCode = templateCode; - } - - public String getNewTemplateCode() { - return newTemplateCode; - } - - public void setNewTemplateCode(String newTemplateCode) { - this.newTemplateCode = newTemplateCode; - } - - public String[] getArrTemplateCode() { - return arrTemplateCode; - } - - public void setArrTemplateCode(String[] arrTemplateCode) { - this.arrTemplateCode = arrTemplateCode; - } - - public String getTemplateStatus() { - return templateStatus; - } - - public void setTemplateStatus(String templateStatus) { - this.templateStatus = templateStatus; - } - - public String getKeyword() { - return keyword; - } - - public void setKeyword(String keyword) { - this.keyword = keyword; - } - - public String getSendPhone() { - return sendPhone; - } - - public void setSendPhone(String sendPhone) { - this.sendPhone = sendPhone; - } - - public String getDestPhone() { - return destPhone; - } - - public void setDestPhone(String destPhone) { - this.destPhone = destPhone; - } - - public String getSubMsgSendYn() { - return subMsgSendYn; - } - - public void setSubMsgSendYn(String subMsgSendYn) { - this.subMsgSendYn = subMsgSendYn; - } - - public String getCount() { - return count; - } - - public void setCount(String count) { - this.count = count; - } - - public String getPage() { - return page; - } - - public void setPage(String page) { - this.page = page; - } - - public String getBizUmid() { - return bizUmid; - } - - public void setBizUmid(String bizUmid) { - this.bizUmid = bizUmid; - } - - public List getVarNmList() { - return varNmList; - } - - public void setVarNmList(List varNmList) { - this.varNmList = varNmList; - } - - public List getVarValList() { - return varValList; - } - - public void setVarValList(List varValList) { - this.varValList = varValList; - } - - public String getFormListType() { - return formListType; - } - - public void setFormListType(String formListType) { - this.formListType = formListType; - } - - public String getSubMsgTxt() { - return subMsgTxt; - } - - public void setSubMsgTxt(String subMsgTxt) { - this.subMsgTxt = subMsgTxt; - } - - public String getBizJsonYn() { - return bizJsonYn; - } - - public void setBizJsonYn(String bizJsonYn) { - this.bizJsonYn = bizJsonYn; - } - - public String getSendType() { - return sendType; - } - - public void setSendType(String sendType) { - this.sendType = sendType; - } - - public String getAdFlag() { - return adFlag; - } - - public void setAdFlag(String adFlag) { - this.adFlag = adFlag; - } - - public List getKakaoSendList() { - return kakaoSendList; - } - - public void setKakaoSendList(List kakaoSendList) { - this.kakaoSendList = kakaoSendList; - } - - public String getSubMsgTxtReplYn() { - return subMsgTxtReplYn; - } - - public void setSubMsgTxtReplYn(String subMsgTxtReplYn) { - this.subMsgTxtReplYn = subMsgTxtReplYn; - } - - public String getSubMsgType() { - return subMsgType; - } - - public void setSubMsgType(String subMsgType) { - this.subMsgType = subMsgType; - } - public List varValPaser(String[] varValList){ - - List returnVarVal = new ArrayList<>(); - - for(String varVal : varValList) - { - String[] strList = varVal.split("§"); - returnVarVal.add(strList); + private List> varListMap; + + @Override + public String toString() { + String varListMapString = "["; + if (varListMap != null && !varListMap.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (Map map : varListMap) { + if (sb.length() > 0) + sb.append(", "); + if (map == null) { + sb.append("null"); + } else { + sb.append("{"); + String prefix = ""; + for (Map.Entry entry : map.entrySet()) { + sb.append(prefix).append(entry.getKey()).append("=").append(entry.getValue()); + prefix = ", "; + } + sb.append("}"); + } + } + varListMapString += sb.toString(); } + varListMapString += "]"; - return returnVarVal; + return "KakaoSendAdvcVO[" + + "\n senderKey=[" + senderKey + "]" + + "\n , subMsgTxtReplYn=[" + subMsgTxtReplYn + "]" + + "\n , subMsgSendYn=[" + subMsgSendYn + "]" + + "\n , reserveYn=[" + getReserveYn() + "]" + + "\n , divideCnt=[" + getDivideCnt() + "]" + + "\n , bizJsonYn=[" + bizJsonYn + "]" + + "\n , templateEmphasizeType=[" + templateEmphasizeType + "]" + + "\n , templateSubtitle=[" + templateSubtitle + "]" + + "\n , txtReplYn=[" + getTxtReplYn() + "]" + + "\n , callFrom=[" + getCallFrom() + "]" + + "\n , templateCode=[" + templateCode + "]" + + "\n , divideTime=[" + getDivideTime() + "]" + + "\n , reqDate=[" + getReqDate() + "]" + + "\n , atSmishingYn=[" + getAtSmishingYn() + "]" + + "\n , menuTopTab=[" + menuTopTab + "]" + + "\n , templateContent=[" + templateContent + "]" + + "\n , templateTitle=[" + templateTitle + "]" + + "\n , subMsgTxt=[" + subMsgTxt + "]" + + "\n , divideChk=[" + getDivideChk() + "]" + + "\n , sendType=[" + sendType + "]" + + "\n , msgType=[" + getMsgType() + "]" + + "\n , userId=[" + userId + "]" + + "\n , varListMap=[" + varListMapString + "]" + + "\n , befCash=[" + getBefCash() + "]" + + "\n , befPoint=[" + getBefPoint() + "]" + + "\n ]"; } - - public String getMenuTopTab() { - return menuTopTab; - } - - public void setMenuTopTab(String menuTopTab) { - this.menuTopTab = menuTopTab; - } - - public String getMenuSubTab() { - return menuSubTab; - } - - public void setMenuSubTab(String menuSubTab) { - this.menuSubTab = menuSubTab; - } - - public String getSearchCondition2() { - return searchCondition2; - } - - public void setSearchCondition2(String searchCondition2) { - this.searchCondition2 = searchCondition2; - } - - public String getKakaoResendSuccCount() { - return kakaoResendSuccCount; - } - - public void setKakaoResendSuccCount(String kakaoResendSuccCount) { - this.kakaoResendSuccCount = kakaoResendSuccCount; - } - - public String getKakaoResendFailCount() { - return kakaoResendFailCount; - } - - public void setKakaoResendFailCount(String kakaoResendFailCount) { - this.kakaoResendFailCount = kakaoResendFailCount; - } - - public String getAtSuccessCount() { - return atSuccessCount; - } - - public void setAtSuccessCount(String atSuccessCount) { - this.atSuccessCount = atSuccessCount; - } - - public String getFtSuccessCount() { - return ftSuccessCount; - } - - public void setFtSuccessCount(String ftSuccessCount) { - this.ftSuccessCount = ftSuccessCount; - } - - public String getAtFailCount() { - return atFailCount; - } - - public void setAtFailCount(String atFailCount) { - this.atFailCount = atFailCount; - } - - public String getFtFailCount() { - return ftFailCount; - } - - public void setFtFailCount(String ftFailCount) { - this.ftFailCount = ftFailCount; - } - - public String getAtSuccPrice() { - return atSuccPrice; - } - - public void setAtSuccPrice(String atSuccPrice) { - this.atSuccPrice = atSuccPrice; - } - - public String getFtSuccPrice() { - return ftSuccPrice; - } - - public void setFtSuccPrice(String ftSuccPrice) { - this.ftSuccPrice = ftSuccPrice; - } - - public String getAtFailPrice() { - return atFailPrice; - } - - public void setAtFailPrice(String atFailPrice) { - this.atFailPrice = atFailPrice; - } - - public String getFtFailPrice() { - return ftFailPrice; - } - - public void setFtFailPrice(String ftFailPrice) { - this.ftFailPrice = ftFailPrice; - } - - public String getKakaoResendSuccPrice() { - return kakaoResendSuccPrice; - } - - public void setKakaoResendSuccPrice(String kakaoResendSuccPrice) { - this.kakaoResendSuccPrice = kakaoResendSuccPrice; - } - - public String getKakaoResendFailPrice() { - return kakaoResendFailPrice; - } - - public void setKakaoResendFailPrice(String kakaoResendFailPrice) { - this.kakaoResendFailPrice = kakaoResendFailPrice; - } - - public String getAtSuccCntSum() { - return atSuccCntSum; - } - - public void setAtSuccCntSum(String atSuccCntSum) { - this.atSuccCntSum = atSuccCntSum; - } - - public String getFtSuccCntSum() { - return ftSuccCntSum; - } - - public void setFtSuccCntSum(String ftSuccCntSum) { - this.ftSuccCntSum = ftSuccCntSum; - } - - public String getAtFailCntSum() { - return atFailCntSum; - } - - public void setAtFailCntSum(String atFailCntSum) { - this.atFailCntSum = atFailCntSum; - } - - public String getFtFailCntSum() { - return ftFailCntSum; - } - - public void setFtFailCntSum(String ftFailCntSum) { - this.ftFailCntSum = ftFailCntSum; - } - - public String getKakaoResenSuccSum() { - return kakaoResenSuccSum; - } - - public void setKakaoResenSuccSum(String kakaoResenSuccSum) { - this.kakaoResenSuccSum = kakaoResenSuccSum; - } - - public String getKakaoResenFailSum() { - return kakaoResenFailSum; - } - - public void setKakaoResenFailSum(String kakaoResenFailSum) { - this.kakaoResenFailSum = kakaoResenFailSum; - } - - public String getAtSuccPriceSum() { - return atSuccPriceSum; - } - - public void setAtSuccPriceSum(String atSuccPriceSum) { - this.atSuccPriceSum = atSuccPriceSum; - } - - public String getFtSuccPriceSum() { - return ftSuccPriceSum; - } - - public void setFtSuccPriceSum(String ftSuccPriceSum) { - this.ftSuccPriceSum = ftSuccPriceSum; - } - - public String getAtFailPriceSum() { - return atFailPriceSum; - } - - public void setAtFailPriceSum(String atFailPriceSum) { - this.atFailPriceSum = atFailPriceSum; - } - - public String getFtFailPriceSum() { - return ftFailPriceSum; - } - - public void setFtFailPriceSum(String ftFailPriceSum) { - this.ftFailPriceSum = ftFailPriceSum; - } - - public String getKakaoResendSuccPriceSum() { - return kakaoResendSuccPriceSum; - } - - public void setKakaoResendSuccPriceSum(String kakaoResendSuccPriceSum) { - this.kakaoResendSuccPriceSum = kakaoResendSuccPriceSum; - } - - public String getKakaoResendFailPriceSum() { - return kakaoResendFailPriceSum; - } - - public void setKakaoResendFailPriceSum(String kakaoResendFailPriceSum) { - this.kakaoResendFailPriceSum = kakaoResendFailPriceSum; - } - - public String getFriendId() { - return friendId; - } - - public void setFriendId(String friendId) { - this.friendId = friendId; - } - - public String getImageTitle() { - return imageTitle; - } - - public void setImageTitle(String imageTitle) { - this.imageTitle = imageTitle; - } - - public String getImageLink() { - return imageLink; - } - - public void setImageLink(String imageLink) { - this.imageLink = imageLink; - } - - public String getJsonText() { - return jsonText; - } - - public void setJsonText(String jsonText) { - this.jsonText = jsonText; - } - - public String getImageFileName() { - return imageFileName; - } - - public void setImageFileName(String imageFileName) { - this.imageFileName = imageFileName; - } - - public String getSbscrbDe() { - return sbscrbDe; - } - - public void setSbscrbDe(String sbscrbDe) { - this.sbscrbDe = sbscrbDe; - } - - public String getMoblphonNo() { - return moblphonNo; - } - - public void setMoblphonNo(String moblphonNo) { - this.moblphonNo = moblphonNo; - } - - public String getDept() { - return dept; - } - - public void setDept(String dept) { - this.dept = dept; - } - - public String getAtchFileId() { - return atchFileId; - } - - public void setAtchFileId(String atchFileId) { - this.atchFileId = atchFileId; - } - - public String getWorkAtchFileId() { - return workAtchFileId; - } - - public void setWorkAtchFileId(String workAtchFileId) { - this.workAtchFileId = workAtchFileId; - } - - public String getFileSn() { - return fileSn; - } - - public void setFileSn(String fileSn) { - this.fileSn = fileSn; - } - - public String getFileCn() { - return fileCn; - } - - public void setFileCn(String fileCn) { - this.fileCn = fileCn; - } - - public String getFileStreCours() { - return fileStreCours; - } - - public void setFileStreCours(String fileStreCours) { - this.fileStreCours = fileStreCours; - } - - public String getOrignlFileNm() { - return orignlFileNm; - } - - public void setOrignlFileNm(String orignlFileNm) { - this.orignlFileNm = orignlFileNm; - } - - public String getStreFileNm() { - return streFileNm; - } - - public void setStreFileNm(String streFileNm) { - this.streFileNm = streFileNm; - } - - public String getFileExtsn() { - return fileExtsn; - } - - public void setFileExtsn(String fileExtsn) { - this.fileExtsn = fileExtsn; - } - - public String getFileSize() { - return fileSize; - } - - public void setFileSize(String fileSize) { - this.fileSize = fileSize; - } - - public int getStartCount() { - return startCount; - } - - public void setStartCount(int startCount) { - this.startCount = startCount; - } - - public int getEndCount() { - return endCount; - } - - public void setEndCount(int endCount) { - this.endCount = endCount; - } - - public String getPhmType() { - return phmType; - } - - public void setPhmType(String phmType) { - this.phmType = phmType; - } - - public String getMsgResendAllFlag() { - return msgResendAllFlag; - } - - public void setMsgResendAllFlag(String msgResendAllFlag) { - this.msgResendAllFlag = msgResendAllFlag; - } - - public String getMsgResendAllGroupId() { - return msgResendAllGroupId; - } - - public void setMsgResendAllGroupId(String msgResendAllGroupId) { - this.msgResendAllGroupId = msgResendAllGroupId; - } - - public String getMsgResendAllTmpKey() { - return msgResendAllTmpKey; - } - - public void setMsgResendAllTmpKey(String msgResendAllTmpKey) { - this.msgResendAllTmpKey = msgResendAllTmpKey; - } - - public String getMsgResendAllYellowId() { - return msgResendAllYellowId; - } - - public void setMsgResendAllYellowId(String msgResendAllYellowId) { - this.msgResendAllYellowId = msgResendAllYellowId; - } - } diff --git a/src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java b/src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java index 2312ac1a..bbdd8f81 100644 --- a/src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java +++ b/src/main/java/itn/let/kakao/kakaoComm/kakaoApi/KakaoApiJsonSave.java @@ -8,6 +8,7 @@ import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Map; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -18,6 +19,7 @@ import org.springframework.stereotype.Component; import itn.com.cmm.util.StringUtil; import itn.let.kakao.kakaoComm.KakaoButtonVO; import itn.let.kakao.kakaoComm.KakaoReturnVO; +import itn.let.kakao.kakaoComm.KakaoSendAdvcVO; import itn.let.kakao.kakaoComm.KakaoVO; @Component @@ -32,7 +34,57 @@ public class KakaoApiJsonSave { static String json; - @SuppressWarnings("unchecked") + public String kakaoApiJsonSave_advc(KakaoSendAdvcVO sendVO, KakaoReturnVO templateDetail) { + + // 버튼리스트 JSON 생성 + JSONArray buttonList = new JSONArray(); + for(KakaoButtonVO buttonInfoVO : sendVO.getButtonList()) { + JSONObject buttonInfo = new JSONObject(); + + buttonInfo.put("name", buttonInfoVO.getName()); + buttonInfo.put("type", buttonInfoVO.getLinkType()); + + if(buttonInfoVO.getLinkType().equals("WL")) { + buttonInfo.put("url_mobile", buttonInfoVO.getLinkMo()); + buttonInfo.put("url_pc", buttonInfoVO.getLinkPc()); + }else if(buttonInfoVO.getLinkType().equals("AL")) { + buttonInfo.put("scheme_ios", buttonInfoVO.getLinkIos()); + buttonInfo.put("scheme_android", buttonInfoVO.getLinkAnd()); + }else if(buttonInfoVO.getLinkType().equals("BC")) { + // 상담톡 진행시 등록해야함 + }else if(buttonInfoVO.getLinkType().equals("BT")) { + // 봇 전환 시 전달 + } + buttonList.add(buttonInfo); + } + + // 강조유형 JSON 생성 + JSONObject templateDetailInfo = new JSONObject(); + String emphasizeType = templateDetail.getTemplateEmphasizeType(); + + + if(emphasizeType.equals("TEXT")) { + templateDetailInfo.put("title", sendVO.getTemplateTitle()); + }else if(emphasizeType.equals("IMAGE")) { + templateDetailInfo.put("msg_type", "ai"); + } + + + JSONObject jo = new JSONObject(); + + if(buttonList.size() != 0) { + jo.put("button", buttonList); + } + if(templateDetailInfo.size() != 0) { + jo.put("extra", templateDetailInfo); + } + + // 입력 json 데이터를 파일로 변경 + String jsonStr = jo.toString(); + + return jsonStr; + } + public String kakaoApiJsonSave(KakaoVO kakaoVO, String[] varValInfo) { // json파일 저장 @@ -109,12 +161,12 @@ public class KakaoApiJsonSave { for(int i=0; i < varNm.length; i++) { for(int j=0; j < varValInfo.length; j++) { if (templateTitle.indexOf(varNm[i]) > -1) { - if(varValInfo[j] != null) { - templateTitle = templateTitle.replaceAll(varNm[i] , StringUtil.getString(varValInfo[j])); - }else { - templateTitle = templateTitle.replaceAll(varNm[i] , ""); - } - } + if(varValInfo[j] != null) { + templateTitle = templateTitle.replaceAll(varNm[i] , StringUtil.getString(varValInfo[j])); + }else { + templateTitle = templateTitle.replaceAll(varNm[i] , ""); + } + } } } @@ -140,8 +192,8 @@ public class KakaoApiJsonSave { // 입력 json 데이터를 파일로 변경 String jsonStr = jo.toString(); - System.out.println("jsonFileName : "+jsonFileName); - +// System.out.println("jsonFileName : "+jsonFileName); + File outPut = new File(jsonFileName); outPut.createNewFile(); diff --git a/src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java b/src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java index c19695ea..098f9768 100644 --- a/src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java +++ b/src/main/java/itn/let/kakao/user/kakaoAt/service/KakaoAlimTalkService.java @@ -2,7 +2,11 @@ package itn.let.kakao.user.kakaoAt.service; import java.util.List; +import javax.servlet.http.HttpServletRequest; + +import itn.let.kakao.kakaoComm.KakaoSendAdvcVO; import itn.let.kakao.kakaoComm.KakaoVO; +import itn.let.mail.service.StatusResponse; import itn.let.mjo.msgdata.service.MjonMsgReturnVO; public interface KakaoAlimTalkService { @@ -24,5 +28,7 @@ public interface KakaoAlimTalkService { //카카오 친구톡 전송 실패 환불리스트 조회 public void selectKakaoFtSentRefundList() throws Exception; + + StatusResponse insertKakaoAtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception; } diff --git a/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java b/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java index 6a661ac3..fe3cd77b 100644 --- a/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java +++ b/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkDAO.java @@ -6,6 +6,7 @@ import java.util.List; import org.springframework.stereotype.Repository; import egovframework.rte.psl.dataaccess.EgovAbstractDAO; +import itn.let.kakao.kakaoComm.KakaoSendAdvcVO; import itn.let.kakao.kakaoComm.KakaoVO; @Repository("kakaoAlimTalkDAO") @@ -43,15 +44,6 @@ public class KakaoAlimTalkDAO extends EgovAbstractDAO { return result; } - public int insertKakaoAtDataInfo(List kakaoAtSandList) throws Exception{ - - int result = 0; - - result = update("kakaoAlimTalkDAO.insertKakaoAtDataInfo", kakaoAtSandList); - - return result; - } - public void insertKakaoSendPrice(KakaoVO kakaoVO) throws Exception{ insert("kakaoAlimTalkDAO.insertKakaoSendPrice",kakaoVO); } @@ -94,4 +86,26 @@ public class KakaoAlimTalkDAO extends EgovAbstractDAO { public void updateKakaoFtNotSend(KakaoVO kakaoVO) { select("kakaoAlimTalkDAO.updateKakaoFtNotSend", kakaoVO); } + + public int insertKakaoAtDataInfo(List kakaoAtSandList) throws Exception{ + + int result = 0; + + result = update("kakaoAlimTalkDAO.insertKakaoAtDataInfo", kakaoAtSandList); + + return result; + } + + public int insertKakaoAtDataInfo_advc(List kakaoSendAdvcVOList) { + + return update("kakaoAlimTalkDAO.insertKakaoAtDataInfo_advc", kakaoSendAdvcVOList); + } + + public void insertKakaoAtDataJsonInfo_advc(List kakaoSendAdvcVOList) { + insert("kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc", kakaoSendAdvcVOList); + } + + public void insertKakaoGroupDataTb_advc(KakaoSendAdvcVO sendVO) { + insert("kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc", sendVO); + } } diff --git a/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java b/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java index 61f0cd6a..0098872b 100644 --- a/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java +++ b/src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java @@ -1,19 +1,40 @@ package itn.let.kakao.user.kakaoAt.service.impl; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl; import egovframework.rte.fdl.idgnr.EgovIdGnrService; +import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper; +import itn.com.cmm.LoginVO; +import itn.com.cmm.MjonMsgSendVO; +import itn.com.utl.fcc.service.EgovStringUtil; +import itn.let.kakao.kakaoComm.KakaoSendAdvcVO; +import itn.let.kakao.kakaoComm.KakaoSendUtil; import itn.let.kakao.kakaoComm.KakaoVO; import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService; +import itn.let.mail.service.StatusResponse; +import itn.let.mjo.mjocommon.MjonCommon; import itn.let.mjo.mjocommon.MjonHolidayApi; import itn.let.mjo.msg.service.MjonMsgVO; import itn.let.mjo.msg.service.impl.MjonMsgDAO; @@ -24,9 +45,14 @@ import itn.let.mjo.msgholiday.service.MsgHolidayVO; import itn.let.mjo.msgholiday.service.impl.MsgHolidayDAO; import itn.let.mjo.pay.service.MjonPayService; import itn.let.mjo.pay.service.MjonPayVO; +import itn.let.module.base.PriceAndPoint; import itn.let.sym.site.service.JoinSettingVO; import itn.let.sym.site.service.impl.SiteManagerDAO; +import itn.let.uss.umt.service.EgovUserManageService; +import itn.let.uss.umt.service.UserManageVO; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service("kakaoAlimTalkService") public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements KakaoAlimTalkService{ @@ -47,12 +73,28 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements @Resource(name = "egovMjonMsgIdGnrService") private EgovIdGnrService idgenMsgId; + + @Resource(name = "egovMjonMsgGroupIdGnrService") + private EgovIdGnrService idgenMjonMsgGroupId; @Resource(name = "mjonPayService") private MjonPayService mjonPayService; @Resource(name = "egovMjonCashIdGnrService") private EgovIdGnrService idgenMjonCashId; + + /** userManageService */ + @Resource(name = "userManageService") + private EgovUserManageService userManageService; + + @Autowired + KakaoSendUtil kakaoSendUtil; + + @Autowired + private MjonCommon mjonCommon; + + @Autowired + private PriceAndPoint priceAndPoint; //발신프로필 상태값 변경(삭제/복구 기능) @Override @@ -816,4 +858,341 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements } } } + + @Override + public StatusResponse insertKakaoAtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception { + + log.info(" :: [{}]", kakaoVO.toString()); + + + // 측정할 메소드 호출 전 시간 기록 + Instant start = Instant.now(); +// KakaoSendAdvcVO + + Map returnMap = new HashMap<>(); + + LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated() + ? (LoginVO) EgovUserDetailsHelper.getAuthenticatedUser() + : null; + String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId()); + + if (userId.equals("")) { + return new StatusResponse(HttpStatus.BAD_REQUEST, "로그인 후 이용이 가능합니다."); + } + + kakaoVO.setUserId(userId); + + /** + * 회원 정지된 상태이면 문자 발송이 안되도록 처리함 현재 로그인 세션도 만료 처리함 + */ + boolean mberSttus = userManageService.selectUserStatusInfo(userId); + if (!mberSttus) { + request.getSession().invalidate(); + // UNAUTHORIZED : 인증되지 않은 사용자가 접근하려고 할 때 + return new StatusResponse(HttpStatus.UNAUTHORIZED, + "현재 고객님께서는 문자온 서비스 이용이 정지된 상태로 알림톡을 발송하실 수 없습니다. 이용정지 해제를 원하시면 고객센터로 연락주시기 바랍니다."); + } + + + StatusResponse statusResponse = new StatusResponse(); + +/** @isHolidayNotified + * @false : 알림 X + * @true : 알림 O */ + boolean isNotified = mjonCommon.processUserAndCheckAT(kakaoVO); + + +/** @LETTNGNRLMBER 사용자 정보 -> 스미싱의심 여부 */ + UserManageVO userManageVO = mjonCommon.getUserManageInfo(userId); + kakaoVO.setAtSmishingYn(userManageVO.getAtSmishingYn()); + +/** @카카오톡 전송 list 셋팅 -------------------------------------------*/ + List kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, isNotified, statusResponse); + if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) { + log.error(" + populateSendLists 처리 중 오류 발생: {}", statusResponse.getMessage()); + return statusResponse; + } + + + +/** @전송금액 확인 --------------------------------------------------*/ + if (!isCashSufficient(userId, kakaoSendAdvcListVO)) { + log.error("Insufficient balance for message sending."); + return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다."); + } + + + + Map> priceGroupedMessages = kakaoSendAdvcListVO.stream() + .collect(Collectors.groupingBy(KakaoSendAdvcVO::getEachPrice)); + + + // instTotalCnt : 화면에서 보여줄 총 발송건수 + int instTotalCnt = 0; + // 임시 + List nextMsgGroupIdA = new ArrayList<>(); + // 대안: entrySet() 직접 사용 + for (Map.Entry> entry : priceGroupedMessages.entrySet()) { + // entry 사용 + + List groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트 + + String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId(); + groupedMsgList.forEach(t -> t.setMsgGroupId(nextMsgGroupId)); + + + // 발송 데이터 삽입 + int instCnt = this.insertKakaoData_advc(groupedMsgList); +// int instCnt = 6; + + if(instCnt > 0) { + + instTotalCnt += instCnt; + + KakaoSendAdvcVO sendVO = groupedMsgList.get(0); + +/** @groupData 테이블 insert */ + this.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, sendVO); + + +/** @biz_kakao_price에 insert (대체문자 환불관련 테이블)*/ + kakaoVO.setMsgGroupId(sendVO.getMsgGroupId()); + kakaoVO.setKakaoAtPrice(Float.parseFloat(sendVO.getEachPrice())); + kakaoVO.setSmsPrice(Float.parseFloat(sendVO.getSmsPrice())); + kakaoVO.setMmsPrice(Float.parseFloat(sendVO.getMmsPrice())); + + kakaoAlimTalkDAO.insertKakaoSendPrice(kakaoVO); + + + priceAndPoint.insertCashAndPoint(kakaoVO.getUserId() + , -Float.parseFloat(sendVO.getTotPrice()) + , "카카오 알림톡 총 "+groupedMsgList.size()+"건 중 " + instCnt + "건 발송" + , nextMsgGroupId + ); + + +/** @SLACK발송 */ + /** @발송조건이되면 발송 */ + if(isNotified) { + mjonCommon.getAdminKakaoAtSendSlack(kakaoVO); + }else if("Y".equals(kakaoVO.getAtSmishingYn())){ + /** @발송조건이 안되면 DB INSERT */ + mjonMsgDAO.insertSpamPassMsgData(MjonMsgVO.builder() + .msgGroupId(nextMsgGroupId) + .userId(kakaoVO.getUserId()) + .reqDate(kakaoVO.getReqDate()) + .smsTxt(groupedMsgList.get(0).getTemplateContent()) + .totalCallCnt(instCnt) + .callFrom(kakaoVO.getCallFrom()) + .msgType("8") + .reserveYn(kakaoVO.getReserveYn()) + .build() + ); + } + + nextMsgGroupIdA.add(nextMsgGroupId); + + } + + } + + returnMap.put("resultSts", instTotalCnt); + returnMap.put("reserYn", kakaoVO.getReserveYn()); + returnMap.put("groupIds", nextMsgGroupIdA); + + + // 측정할 메소드 호출 후 시간 기록 + Instant end = Instant.now(); + + log.info(" + start :: [{}]", start); + // 실행 시간 계산 (나노초, 밀리초, 초) + long seconds = Duration.between(start, end).getSeconds(); + System.out.println("메소드 실행 시간 (초): " + seconds + " s"); + double minutes = seconds / 60.0; // 소수점 포함을 위해 60.0으로 나눔 + + returnMap.put("second", seconds+" s"); + returnMap.put("minutes", minutes+" min"); + + +// System.out.println("메소드 실행 시간 (분): " + minutes + " min"); + + + + +// priceAndPoint.getBefCash(userId); + + + + + statusResponse.setStatus(HttpStatus.OK); + statusResponse.setObject(returnMap); + + return statusResponse; + } + + + + + private void insertKakaoGroupDataTb_advc(int instCnt, KakaoVO kakaoVO, KakaoSendAdvcVO sendVO) throws Exception { + // TODO Auto-generated method stub + +// log.info(" + insertKakaoGroupDataTb_advc kakaoVO :: \n[{}]", kakaoVO.toString());; +// log.info(" + insertKakaoGroupDataTb_advc kakaoSendAdvcVOList :: \n[{}]", sendVO.toString()); + + sendVO.setMsgGroupCnt(Integer.toString(instCnt)); + sendVO.setReserveYn(kakaoVO.getReserveYn()); + sendVO.setBefCash(priceAndPoint.getBefCash(sendVO.getUserId())); + sendVO.setBefPoint(priceAndPoint.getBefPoint(sendVO.getUserId())); + + Float eachPrice = Float.parseFloat(sendVO.getEachPrice()); + + Float totPrice = eachPrice * instCnt; + sendVO.setTotPrice(String.format("%.1f", totPrice)); + + sendVO.setAtDelayYn(kakaoVO.getAtSmishingYn()); + sendVO.setBizKakaoResendOrgnlTxt(kakaoVO.getSubMsgTxt()); + sendVO.setBizKakaoResendType(sendVO.getSubMsgType()); + + kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc(sendVO); + + } + + /** + * @methodName : insertKakaoData_advc + * @author : 이호영 + * @date : 2025. 3. 20. + * @description : 카카오 batch 발송 => mj_msg_data + * @return : int + * @param kakaoSendAdvcVOList + * @param parentLoopCount + * @param isJsonNotEmpty + * @param isJsonNameAllSame + * @return + * + */ + private int insertKakaoData_advc(List kakaoSendAdvcVOList) { + + + // 시작 시간 측정 + long totalStartTime = System.currentTimeMillis(); + + int totalSize = kakaoSendAdvcVOList.size(); // 총 데이터 개수 + // Batch 크기 설정 (고정값) +// int batchSize = 10000; 465 + int batchSize = 50000; // 9분 18초 + + log.info("총 데이터 개수 :: [{}] ", totalSize); + log.info("설정된 Batch 크기 :: [{}] ", batchSize); + + // 총 insert 카운트 + int instCnt = 0; + int batchCount = 0; + + // 각 배치별 실행 시간 기록 + List batchExecutionTimes = new ArrayList<>(); + + + // 첫 번째 배치에서만 삽입했는지 추적하는 플래그 + for (int i = 0; i < totalSize; i += batchSize) { + // Batch 시작 시간 측정 + long batchStartTime = System.currentTimeMillis(); + + // Batch 리스트 생성 + List batchList = kakaoSendAdvcVOList.subList(i, Math.min(i + batchSize, totalSize)); + System.out.println("Batch 시작 인덱스: " + i); + + // mj_msg_data 테이블 insert + int insertedCount = kakaoAlimTalkDAO.insertKakaoAtDataInfo_advc(batchList); + + /** @kakaoSendUtil.populateSendLists + * 하단에서 + * getJsonStr 데이터 처리 후 활용 + * */ + batchList.removeIf(t -> StringUtils.isBlank(t.getJsonStr())); + if(batchList.size() > 0) { + kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc(batchList); + } + instCnt += insertedCount; + + // Batch 종료 시간 측정 및 실행 시간 계산 + long batchEndTime = System.currentTimeMillis(); + double batchExecutionTimeInSeconds = (batchEndTime - batchStartTime) / 1000.0; + + // 실행 시간 기록 + batchExecutionTimes.add(batchExecutionTimeInSeconds); + batchCount++; + } + + // 종료 시간 측정 + long totalEndTime = System.currentTimeMillis(); + + // 총 실행 시간 계산 (밀리초 -> 초로 변환) + double totalExecutionTimeInSeconds = (totalEndTime - totalStartTime) / 1000.0; + + // 실행 시간 출력 + log.info("총 배치 실행 횟수 :: [{}] ", batchCount); + log.info("batchSize :: [{}] ", batchSize); + log.info("총 실행 시간 :: [{}] ", totalExecutionTimeInSeconds + "초"); + log.info("총 삽입 건수 :: [{}] ", instCnt); + + // 각 배치별 실행 시간 출력 + for (int k = 0; k < batchExecutionTimes.size(); k++) { + System.out.println("배치 " + (k + 1) + " 실행 시간 :: " + batchExecutionTimes.get(k) + "초"); + } + + return instCnt; + + } + + // 보유 금액이 충분한지 확인하는 메서드 + private boolean isCashSufficient(String userId, List kakaoSendAdvcListVO) throws Exception { + + + String userMoney = priceAndPoint.getBefCash(userId); + // 쉼표 제거 + userMoney = userMoney.replace(",", ""); + + // 사용자 보유 금액 BigDecimal 변환 (HALF_EVEN 적용) + BigDecimal befCash = new BigDecimal(userMoney).setScale(2, RoundingMode.HALF_EVEN); + + // 총 메시지 금액 계산 (HALF_EVEN 적용) + BigDecimal totalEachPrice = kakaoSendAdvcListVO.stream() + .map(msg -> new BigDecimal(String.valueOf(msg.getEachPrice()))) // 변환 오류 방지 + .reduce(BigDecimal.ZERO, BigDecimal::add) + .setScale(2, RoundingMode.HALF_EVEN); // 일관성 유지 + + // 비교 수행 + return befCash.compareTo(totalEachPrice) >= 0; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } diff --git a/src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java b/src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java index ea1bb737..2ee69ccd 100644 --- a/src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java +++ b/src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java @@ -35,9 +35,11 @@ import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -59,6 +61,7 @@ import itn.com.cmm.util.MJUtil; import itn.com.cmm.util.StringUtil; import itn.com.utl.fcc.service.EgovStringUtil; import itn.let.kakao.kakaoComm.KakaoReturnVO; +import itn.let.kakao.kakaoComm.KakaoSendAdvcVO; import itn.let.kakao.kakaoComm.KakaoSendUtil; import itn.let.kakao.kakaoComm.KakaoVO; import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave; @@ -67,6 +70,7 @@ import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiProfileCategory; import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate; import itn.let.kakao.kakaoComm.kakaoApi.service.KakaoApiService; import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService; +import itn.let.mail.service.StatusResponse; import itn.let.mjo.mjocommon.MjonCommon; import itn.let.mjo.mjocommon.MjonHolidayApi; import itn.let.mjo.msgdata.service.MjonMsgDataService; @@ -239,6 +243,8 @@ public class KakaoAlimTalkSendController { return "web/kakao/msgdata/at/KakaoAlimtalkMsgDataView"; +// return "web/kakao/msgdata/at/KakaoAlimtalkMsgDataView_advcbackup_20250310"; + } @@ -1079,6 +1085,16 @@ public class KakaoAlimTalkSendController { return modelAndView; } + @RequestMapping(value= {"/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do"}, method = RequestMethod.POST) + public ResponseEntity kakaoAlimTalkMsgSendAjax_advc( + @RequestBody KakaoVO kakaoVO, + HttpServletRequest request + ) throws Exception { + + System.out.println(" + kakaoAlimTalkMsgSendAjax_advc + "); + return ResponseEntity.ok().body(kakaoAlimTalkService.insertKakaoAtSandAjax_advc(kakaoVO, request)) ; + } + @RequestMapping(value= {"/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax.do"}, method = RequestMethod.POST) // @ResponseBody public ModelAndView kakaoAlimTalkMsgSendAjax( @@ -1086,6 +1102,10 @@ public class KakaoAlimTalkSendController { HttpServletRequest request, @ModelAttribute("kakaoVO") KakaoVO kakaoVO ) throws Exception { + // 시작 시간 + long startTime = System.currentTimeMillis(); + + System.out.println(" :: kakaoAlimTalkMsgSendAjax :: "); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("jsonView"); @@ -1410,7 +1430,7 @@ public class KakaoAlimTalkSendController { if(!smishingAlarmPassSts) {//평일,주말, 공휴일 알림설정 시간에 포함되지 않는 경우 슬랙 알림 발송 - mjonCommon.getAdminKakaoAtSandSlack(kakaoVO); + mjonCommon.getAdminKakaoAtSendSlack(kakaoVO); } @@ -1422,6 +1442,17 @@ public class KakaoAlimTalkSendController { } catch (Exception e) { throw new Exception("++++++++++++++++++++++ getAdminPhoneSendMsgData Error !!! " + e); } + // 종료 시간 + long endTime = System.currentTimeMillis(); + +// 실행 시간 계산 (초 단위) + double executionTimeSeconds = (endTime - startTime) / 1000.0; + + System.out.println("실행 시간: " + String.format("%.3f", executionTimeSeconds) + "초"); + + + String returnTxt = String.format("%.3f", executionTimeSeconds) + "초"; + modelAndView.addObject("seconds", returnTxt); return modelAndView; } diff --git a/src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java b/src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java index e47e6a88..3203c904 100644 --- a/src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java +++ b/src/main/java/itn/let/kakao/user/kakaoFt/web/KakaoFriendsTalkSendController.java @@ -663,7 +663,7 @@ public class KakaoFriendsTalkSendController { if(!smishingAlarmPassSts) {//평일,주말, 공휴일 알림설정 시간에 포함되지 않는 경우 슬랙 알림 발송 MjonCommon comm = new MjonCommon(); - comm.getAdminKakaoAtSandSlack(kakaoVO); + comm.getAdminKakaoAtSendSlack(kakaoVO); } diff --git a/src/main/java/itn/let/mjo/mjocommon/MjonCommon.java b/src/main/java/itn/let/mjo/mjocommon/MjonCommon.java index 5803b62f..c195fc13 100644 --- a/src/main/java/itn/let/mjo/mjocommon/MjonCommon.java +++ b/src/main/java/itn/let/mjo/mjocommon/MjonCommon.java @@ -1,10 +1,12 @@ package itn.let.mjo.mjocommon; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Map; import javax.annotation.Resource; @@ -14,13 +16,17 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.PostMethod; import org.json.simple.JSONObject; import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import com.mysql.jdbc.StringUtils; +import egovframework.com.idgen.CustomIdGnrService; +import egovframework.rte.fdl.cmmn.exception.FdlException; import itn.com.cmm.MjonMsgSendVO; import itn.com.cmm.OptimalMsgResultDTO; import itn.com.cmm.util.MsgSendUtils; +import itn.com.cmm.util.SlackMessageFormatUtil; import itn.let.kakao.kakaoComm.KakaoVO; import itn.let.mail.service.StatusResponse; import itn.let.mjo.event.service.MjonEventService; @@ -36,7 +42,7 @@ import itn.let.uss.umt.service.UserManageVO; import lombok.extern.slf4j.Slf4j; @Slf4j -@Service("MjonCommon") +@Component public class MjonCommon { @@ -60,11 +66,14 @@ public class MjonCommon { /** xpedite 솔루션 ID*/ @Value("#{globalSettings['Globals.slack.channel.name']}") private String SLACK_CHANNEL; - + + @Resource(name = "egovMjonMsgIdCGnrService") + private CustomIdGnrService idgenMsgCId; + /** - * @methodName : getAdminMsgSandSlack + * @methodName : getAdminSandSlack * @author : 이호영 * @date : 2024.12.04 * @description : 기존 메소드 리펙토링 @@ -120,8 +129,8 @@ public class MjonCommon { try { // 메시지 내용 설정 - String smsTxt = formatSmsText(mjonMsgVO); - String sandName = formatSandName(mjonMsgVO); + String smsTxt = SlackMessageFormatUtil.formatSmsText(mjonMsgVO); + String sandName = SlackMessageFormatUtil.formatSandName(mjonMsgVO); // Slack 메시지 생성 JSONObject json = new JSONObject(); @@ -150,94 +159,49 @@ public class MjonCommon { } } - /** - * @throws Exception - * @Method Name : getAdminSlackSand - * @작성일 : 2022. 12. 6. - * @작성자 : WYH - * @Method 설명 : slack 메시지 전송 - */ - /*public void getAdminMsgSandSlack(MjonMsgVO mjonMsgVO) { - + public void getAdminKakaoAtSendSlack(KakaoVO kakaoVO) { HttpClient client = new HttpClient(); - PostMethod post = new PostMethod(url); - JSONObject json = new JSONObject(); + PostMethod post = new PostMethod(SLACK_URL); + try { - - String reserveYn = mjonMsgVO.getReserveYn(); - String delayYn = mjonMsgVO.getDelayYn(); - String smsTxt = mjonMsgVO.getSmsTxt(); - String smishingYn = mjonMsgVO.getSmishingYn(); - String reservSmsTxt = ""; - String smisingSmsTxt = ""; - //예약문자를 발송하는 경우 문자 내용 앞에 "[예약]" 표시되도록 처리 + // 메시지 내용 설정 + String smsTxt = SlackMessageFormatUtil.formatKakaoText(kakaoVO); + String sandName = SlackMessageFormatUtil.formatKakaoSandName(kakaoVO); - if(reserveYn.equals("Y")) { - - if(smishingYn.equals("Y") || delayYn.equals("Y")) { - reservSmsTxt = "[스미싱의심][예약]" + smsTxt; - }else { - reservSmsTxt = "[예약]" + smsTxt; - } - - smsTxt = reservSmsTxt; - System.out.println("smishingYn : "+ smishingYn); - System.out.println("delayYn : "+ delayYn); - }else if(smishingYn.equals("Y") || delayYn.equals("Y")) { - - smisingSmsTxt = "[스미싱의심]" + smsTxt; - smsTxt = smisingSmsTxt; - } - - String sandName = mjonMsgVO.getCallFrom(); - String userId = mjonMsgVO.getUserId(); - String msgType = ""; - int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt());//그림 이미지 갯수 - if(mjonMsgVO.getMsgType().equals("4")) { //단문 금액 - msgType = "[단문]"; - }else if(mjonMsgVO.getMsgType().equals("6")){ - if(fileCount == 0) { - msgType = "[장문]"; - }else { - msgType = "[그림]"; - // 2022.12.21 JSP => 텍스트없는 그림문자만 발송시 슬랙알림 안됨 - if (StringUtils.isNullOrEmpty(smsTxt)) { - smsTxt = "그림문자 " + smsTxt; - } - } - } -// sandName = "[" + userId + "]" + "[" + sandName + "]" + msgType; - sandName = "[개발테스트]"+"[" + userId + "]" + "[" + sandName + "]" + msgType; - - json.put("channel", "mjon메시지"); + // Slack 메시지 생성 + JSONObject json = new JSONObject(); + json.put("channel", SLACK_CHANNEL); json.put("text", smsTxt); json.put("username", sandName); - + // Slack 요청 post.addParameter("payload", json.toString()); - // 처음에 utf-8로 content-type안넣어주니까 한글은 깨져서 content-type넣어줌 post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + + // Slack 응답 처리 int responseCode = client.executeMethod(post); - String response = post.getResponseBodyAsString(); - if (responseCode != HttpStatus.SC_OK) { - System.out.println("Response: " + response); + if (responseCode != HttpStatus.SC_OK) { + log.warn("Slack 메시지 전송 실패. Response: {}", post.getResponseBodyAsString()); } } catch (IllegalArgumentException e) { - System.out.println("IllegalArgumentException posting to Slack " + e); - } - catch (IOException e) { - System.out.println("IOException posting to Slack " + e); - } - catch (Exception e) { - System.out.println("Exception posting to Slack " + e); - e.printStackTrace(); + log.error("Slack 메시지 전송 중 IllegalArgumentException 발생", e); + } catch (IOException e) { + log.error("Slack 메시지 전송 중 IOException 발생", e); + } catch (Exception e) { + log.error("Slack 메시지 전송 중 Exception 발생", e); } finally { post.releaseConnection(); } - - }*/ + } + private String formatKakaoSandName(KakaoVO kakaoVO) { + // TODO Auto-generated method stub + return null; + } + + + /** * @Method Name : sendSimpleSlackMsg * @작성일 : 2022. 12. 9 @@ -384,7 +348,7 @@ public class MjonCommon { return mjonMsgVO; } - + /* @SuppressWarnings("unchecked") public void getAdminKakaoAtSandSlack(KakaoVO kakaoVO) { @@ -448,7 +412,7 @@ public class MjonCommon { } } - + */ public String getCreateMsgUserIdgen(String subUserId, String lastId) throws Exception{ @@ -485,27 +449,6 @@ public class MjonCommon { -private String formatSmsText(MjonMsgVO mjonMsgVO) { - String smsTxt = mjonMsgVO.getSmsTxt(); - String reserveYn = safeGetString(mjonMsgVO.getReserveYn()); - String delayYn = safeGetString(mjonMsgVO.getDelayYn()); - String smishingYn = safeGetString(mjonMsgVO.getSmishingYn()); - - // 예약 문자와 스미싱 의심 처리 - if ("Y".equals(reserveYn)) { - smsTxt = ("Y".equals(smishingYn) || "Y".equals(delayYn)) ? "[스미싱의심][예약]" + smsTxt : "[예약]" + smsTxt; - } else if ("Y".equals(smishingYn) || "Y".equals(delayYn)) { - smsTxt = "[스미싱의심]" + smsTxt; - } - - // 그림 문자 처리 - int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0); - if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isNullOrEmpty(smsTxt)) { - smsTxt = "그림문자 " + smsTxt; - } - - return smsTxt; -} private String formatSandName(MjonMsgVO mjonMsgVO) { String userId = mjonMsgVO.getUserId(); @@ -542,7 +485,18 @@ private int parseIntOrDefault(String value, int defaultValue) { - // 전체 로직 처리 (한 번에 모든 필요한 정보 반환) + /** + * @methodName : processUserAndCheckSms + * @author : 이호영 + * @date : 2025. 3. 25. + * @description : SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환) + * @return : boolean + * @param mjonMsgVO + * @param userId + * @return + * @throws Exception + * + */ public boolean processUserAndCheckSms(MjonMsgVO mjonMsgVO, String userId) throws Exception { UserManageVO userManageVO = getUserManageInfo(userId); @@ -556,11 +510,41 @@ private int parseIntOrDefault(String value, int defaultValue) { mjonMsgVO.setSmishingYn(smishingYn); // MjonMsgVO에 스미싱 정보 설정 // 스미싱 알림 처리 - return handleSmishingAlert(mjonMsgVO); // 알림 처리 결과 반환 + return handleSmishingAlert(); // 알림 처리 결과 반환 } return false; // 알림 처리되지 않음 } + + /** + * @methodName : processUserAndCheckAT + * @author : 이호영 + * @date : 2025. 3. 25. + * @description : SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환) + * @return : boolean + * @param mjonMsgVO + * @param userId + * @return + * @throws Exception + * + */ + public boolean processUserAndCheckAT(KakaoVO kakaoVO) throws Exception { + UserManageVO userManageVO = getUserManageInfo(kakaoVO.getUserId()); + + // 기본값 처리된 사용자 정보와 문자 상태 + String adminSmsNoticeYn = userManageVO.getAdminSmsNoticeYn(); + String atSmishingYn = userManageVO.getAtSmishingYn(); + + // 조건 체크 + if ("Y".equals(adminSmsNoticeYn) || "Y".equals(atSmishingYn)) { + kakaoVO.setAtSmishingYn(atSmishingYn); // MjonMsgVO에 스미싱 정보 설정 + + // 스미싱 알림 처리 + return handleSmishingAlert(); // 알림 처리 결과 반환 + } + + return false; // 알림 처리되지 않음 + } // 사용자 정보 조회 및 기본값 처리 public UserManageVO getUserManageInfo(String userId) throws Exception { @@ -572,18 +556,28 @@ private int parseIntOrDefault(String value, int defaultValue) { } // 스미싱 알림 처리 - public boolean handleSmishingAlert(MjonMsgVO mjonMsgVO) throws Exception { + public boolean handleSmishingAlert() throws Exception { + /** + * MJ_MBER_SETTING => 기본 시스템 알림 여부 + * 슬랙 Y + * 야간스미싱알림 Y + * 등등 + * + */ JoinSettingVO joinSettingVO = egovSiteManagerService.selectAdminNotiDetail(); +/** @시스템 설정에 야간스미싱 알림 || 슬랙알림이 N이면 false*/ if (joinSettingVO == null || !"Y".equals(joinSettingVO.getHoliSmishingNoti()) || !"Y".equals(joinSettingVO.getSlackNoti())) { return false; // 알림 조건 미충족 } - // 알림 조건 충족 시 추가 작업 +/** @MJ_SPAMPASS_ALARM : 현재 활성화된 알림 SELECT */ List alarmList = getAlarmSettings(); +/** @MJ_HOLIDAY 시스템에 등록된 공휴일 설정 */ List holidayList = getHolidayList(); - boolean isNotificationAllowed = new MjonHolidayApi().getHolidaySmishingPassStatus(alarmList, holidayList); +/** @MJ_HOLIDAY 시스템에 등록된 공휴일 설정 */ + boolean isNotificationAllowed = new MjonHolidayApi().getHolidaySmishingPassStatus_advc(alarmList, holidayList); return !isNotificationAllowed; // 알림 발송 조건 미충족 } @@ -699,9 +693,55 @@ private int parseIntOrDefault(String value, int defaultValue) { + public List getNextCustomMsgCId (int cnt) throws FdlException { + + List idList = idgenMsgCId.getNextStringId(cnt); + return idList; + + } - + /** + * @methodName : getSmsTxtBytes + * @author : 이호영 + * @date : 2024.09.23 + * @description : sms 텍스트 바이트 계산 후 return; + * @param smsTxt + * @return + * @throws UnsupportedEncodingException + */ + public static int getSmsTxtBytes(String smsTxt) throws UnsupportedEncodingException { //문자열 길이 체크 해주기 + int smsBytes = 0; + //문자 바이트 계산에 필요한 캐릭터 셋 : 한글 2Byte로 계산 + String charset = "euc-kr"; + if(org.apache.commons.lang3.StringUtils.isNotEmpty(smsTxt)) { + String smsCont = smsTxt.replace("\r\n", "\n"); + smsBytes = smsCont.getBytes(charset).length; + } +// log.info(" + smsBytes :: [{}]", smsBytes); + return smsBytes; + } + + + /** + * @methodName : replaceTemplateVariables + * @author : 이호영 + * @date : 2025. 3. 12. + * @description : 헬퍼 메서드: 템플릿 변수 치환 + * @return : String + * @param content + * @param variables + * @return + */ + public static String ATReplaceTemplateVariables(String content, Map variables) { + String result = content; + for (Map.Entry entry : variables.entrySet()) { + String placeholder = entry.getKey(); + String value = entry.getValue(); + result = result.replace(placeholder, value); + } + return result; + } diff --git a/src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java b/src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java index 71f24e95..e2dfc815 100644 --- a/src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java +++ b/src/main/java/itn/let/mjo/mjocommon/MjonHolidayApi.java @@ -231,4 +231,71 @@ public class MjonHolidayApi { return smishingAlarmPassSts; } + /** + * @methodName : getHolidaySmishingPassStatus_advc + * @author : 이호영 + * @date : 2025. 3. 19. + * @description : getHolidaySmishingPassStatus 개선 버전 + * @return : boolean + * @param resultAlarmList + * @param resultHolidayList + * @return + * @throws Exception + * + */ + public boolean getHolidaySmishingPassStatus_advc(List alarmList, List holidayList) throws Exception{ + + Date now = new Date(); // 현재 시스템 시간 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 날짜-시간 포맷 (예: 2025-03-18 14:30) + + // 현재 날짜와 요일 계산 + Calendar cal = Calendar.getInstance(); + cal.setTime(now); + int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1(일요일) ~ 7(토요일) + // 오늘 날짜를 "yyyy-MM-dd" 형식으로 포맷팅 (mj_holiday.HOLIDAY_DATE와 비교용) + String today = String.format("%d-%02d-%02d", + cal.get(Calendar.YEAR), + cal.get(Calendar.MONTH) + 1, // Calendar.MONTH는 0부터 시작하므로 +1 + cal.get(Calendar.DATE)); + + // 공휴일 여부 확인 + // mj_holiday 테이블의 HOLIDAY_DATE와 오늘 날짜가 일치하는지 체크 + // HOLIDAY_DATE는 'yyyy-MM-dd' 형식으로 저장됨 (예: '2025-01-01') + boolean isHoliday = holidayList.stream() + .anyMatch(holiday -> today.equals(holiday.getHolidayDate())); + + // 알람 설정 순회 + // alarmList는 MsgAlarmSetVO 객체의 리스트로, 알람 타입과 시작/종료 시간을 포함 + for (MsgAlarmSetVO alarm : alarmList) { + String alarmType = alarm.getAlarmType(); // 알람 유형: 'W'(평일), 'E'(주말), 'H'(공휴일) + // 오늘 날짜에 알람 시작/종료 시간을 붙여 Date 객체로 변환 + Date start = sdf.parse(today + " " + alarm.getAlarmStart()); // 예: "2025-03-18 09:00" + Date end = sdf.parse(today + " " + alarm.getAlarmEnd()); // 예: "2025-03-18 18:00" + + // 현재 시간이 알람 시작~종료 시간 범위 내에 있는지 확인 + boolean isWithinTime = now.after(start) && now.before(end); + if (!isWithinTime) continue; // 시간 범위 밖이면 다음 알람으로 + + // 평일 체크 (월~금: dayOfWeek 2~6) + // alarmType 'W'는 평일에만 적용 + if (dayOfWeek > 1 && dayOfWeek < 7 && alarmType.equals("W")) { + return true; // 평일이고, 시간이 맞고, 타입이 'W'면 스미싱 알람 통과 + } + // 주말 체크 (일:1, 토:7) + // alarmType 'E'는 주말에만 적용 + else if ((dayOfWeek == 1 || dayOfWeek == 7) && alarmType.equals("E")) { + return true; // 주말이고, 시간이 맞고, 타입이 'E'면 스미싱 알람 통과 + } + // 공휴일 체크 + // alarmType 'H'는 mj_holiday에 등록된 공휴일에 적용 + // HOLIDAY_TYPE(1:법정, 2:임시, 3:기타)과 관계없이 날짜만 확인 + else if (isHoliday && alarmType.equals("H")) { + return true; // 공휴일이고, 시간이 맞고, 타입이 'H'면 스미싱 알람 통과 + } + } + + // 모든 조건에 부합하지 않으면 false 반환 (스미싱 알람 비활성화) + return false; + } + } diff --git a/src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java b/src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java index 43589dea..0e93135a 100644 --- a/src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java +++ b/src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java @@ -7,12 +7,18 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import itn.com.cmm.ComDefaultVO; import itn.com.cmm.MjonMsgSendVO; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @JsonIgnoreProperties(ignoreUnknown = true) @Getter @Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor public class MjonMsgVO extends ComDefaultVO{ private static final long serialVersionUID = 1L; diff --git a/src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java b/src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java index 8f183fb5..efade919 100644 --- a/src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java +++ b/src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java @@ -4061,7 +4061,7 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M System.out.println("================================"); // 스팸 및 스미싱 의심이면 slack 알림 - boolean isHolidayNotified = mjonCommon.handleSmishingAlert(mjonMsgVO); + boolean isHolidayNotified = mjonCommon.handleSmishingAlert(); // 스팸관련 키워드 select @@ -4095,7 +4095,9 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M MsgSendUtils.setPriceforVO(mjonMsgVO, mjonMsgSendVOList, sysJoinSetVO, mberManageVO); // msg_id 대량 생성 - List idList = idgenMsgCId.getNextStringId(mjonMsgSendVOList.size()); + +// List idList = idgenMsgCId.getNextStringId(mjonMsgSendVOList.size()); + List idList = mjonCommon.getNextCustomMsgCId(mjonMsgSendVOList.size()); for (int i = 0; i < mjonMsgSendVOList.size(); i++) { mjonMsgSendVOList.get(i).setMsgId(idList.get(i)); } @@ -4136,7 +4138,6 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M int instTotalCnt = 0; // Step 2: 그룹화 된 데이터를 그룹별로 insert 처리 for (Map.Entry> entry : priceGroupedMessages.entrySet()) { - String price = entry.getKey(); // 가격 (String) List groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트 // msgGroupId 생성 @@ -4172,7 +4173,7 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M // 수신거부 목록 업데이트 // returnMap.put("resultSts", instCnt); - log.debug("가격 [{}]의 총 갯수: [{}]", price, groupedMsgList.size()); + log.debug("가격 [{}]의 총 갯수: [{}]", entry.getKey(), groupedMsgList.size()); } diff --git a/src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java b/src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java index d4657e7a..de13ab68 100644 --- a/src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java +++ b/src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java @@ -2090,16 +2090,8 @@ public class MjonMsgDataController { } - long startTime = System.currentTimeMillis(); // 시작 시간 측정 - List resultAddrList = mjonMsgDataService.selectMsgAddrListAjax(addrVO); - long endTime = System.currentTimeMillis(); // 종료 시간 측정 - - long elapsedTime = endTime - startTime; // 소요 시간 계산 - System.out.println("소요 시간: " + elapsedTime + " 밀리초"); - - modelAndView.addObject("resultAddrList", resultAddrList); modelAndView.addObject("result", "success"); diff --git a/src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml b/src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml index 9ff146a3..4f1cfa20 100644 --- a/src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml +++ b/src/main/resources/egovframework/sqlmap/let/mjo/kakao/Kakao_AT_SQL_Mysql.xml @@ -4,9 +4,10 @@ ========= ======= ================================================= 2023.02.02 우영두 --> - + + INSERT INTO MJ_MSG_DATA @@ -54,6 +55,119 @@ + + INSERT INTO MJ_MSG_DATA + ( + MSG_ID + , MSG_GROUP_ID + , USER_ID + , AGENT_CODE + , CUR_STATE + + , MSG_NOTICETALK_SENDER_KEY + , MSG_NOTICETALK_TMP_KEY + , CALL_TO + , CALL_FROM + , MSG_TYPE + + , SMS_TXT + , BIZ_KAKAO_TITLE + + , BIZ_KAKAO_RESEND_YN + , BIZ_KAKAO_RESEND_DATA + , BIZ_KAKAO_RESEND_TYPE + , BIZ_KAKAO_JSON_FILE + , REQ_DATE + )VALUES + + ( + #[].msgId# + , #[].msgGroupId# + , #[].userId# + , #[].agentCode# + , 0 + + , #[].senderKey# + , #[].templateCode# + , #[].callTo# + , #[].callFrom# + , #[].msgType# + + , #[].templateContent# + , #[].templateTitle# + + , #[].subMsgSendYn# + , #[].subMsgTxt# + , #[].subMsgType# + , #[].bizJsonName# + , #[].reqDate# + ) + + + + INSERT INTO BIZ_ATTACHMENTS + ( + MSG_KEY + , TYPE + , CONTENTS + )VALUES + + ( + #[].msgId# + , 'JSON' + , #[].jsonStr# + ) + + + + + INSERT INTO MJ_MSG_GROUP_DATA + ( + MSG_GROUP_ID, + USER_ID, + CALL_FROM, + SMS_TXT, + + REQ_DATE, + MSG_GROUP_CNT, + MSG_TYPE, + + AGENT_CODE, + EACH_PRICE, + RESERVE_YN, + BEF_CASH, + BEF_POINT, + + TOT_PRICE, + + AT_DELAY_YN, + BIZ_KAKAO_RESEND_ORGNL_TXT, + BIZ_KAKAO_RESEND_TYPE + )VALUES + ( + #msgGroupId#, + #userId#, + #callFrom#, + #templateContent#, + + #reqDate#, + #msgGroupCnt#, + #msgType#, + + #agentCode#, + #eachPrice#, + #reserveYn#, + #befCash#, + #befPoint#, + + #totPrice#, + + #atDelayYn#, + #bizKakaoResendOrgnlTxt#, + #bizKakaoResendType# + ) + + INSERT INTO BIZ_KAKAO_PRICE ( diff --git a/src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml b/src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml index 35067b05..eb97a567 100644 --- a/src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml +++ b/src/main/resources/egovframework/sqlmap/let/uss/umt/EgovUserManage_SQL_Mysql.xml @@ -1315,6 +1315,7 @@ ADMIN_SMS_NOTICE_YN AS adminSmsNoticeYn ,PRE_PAYMENT_YN AS prePaymentYn ,SMISHING_YN AS smishingYn + ,AT_SMISHING_YN AS atSmishingYn ,AUTO_CASH AS autoCash ,IFNULL(BLINE_CODE, 'N') AS blineCode ,IFNULL(RECOMMEND_ID, '') AS recommendId diff --git a/src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp b/src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp index 4fb0fd35..14ce86b3 100644 --- a/src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp +++ b/src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp @@ -7,6 +7,8 @@ + + @@ -15,7 +17,6 @@ --> + + + + + + + + + + + + + Loading + + + + + + + + 알림 + + + + 카카오톡 알림톡은 기업회원만 전송 가능합니다.기업회원 전환 페이지로 이동하시겠습니까? + + 확인 + 취소 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<%-- --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 알림톡 전송 결과 + + + + 발송 성공 : 1 건,수신거부 : 0건의알림톡이 발송 되었습니다. + + + 알림톡 발송결과 바로가기 + 확인 + + + + + + + + 문자 전송 결과 + + + + 발송 성공 : 1 건,수신거부 : 0건의문자가 발송 되었습니다. + + + 확인 + + + + + + + + 문자 전송 결과 + + + + + + + 확인 + + + + + + + + <%@include file="/WEB-INF/jsp/web/kakao/include/KaKaoAlimtalkTopMenuTap.jsp" %> + + + + + + + + + + + + + 채널ID + + + + 채널ID 선택 + + + + + + + + + 템플릿 + + + + 알림톡 템플릿 선택 + + + 템플릿 등록 + + + * 변수명 설정파일을 다운로드 받으신 후 전송대상과 변수를 입력 후 업로드해주세요. + * 엑셀서식은 반드시 텍스트 서식으로 등록해주세요. + * 한번에 전송가능한 최대 발송건은 500건입니다. + * 배송조회시 운송장 번호는 숫자만 등록해주세요. + + {변수명} 설정 파일 다운로드 + + + + + + 받는사람 + + + + 받는 번호입력 + + 번호추가 + + + * 중복번호는 한번만 발송됩니다. + + + + * 한번에 전송가능한 최대 발송건은 500건 입니다. + + + + + + + + + + + 휴대폰 + + + + + + + + + + + + + + + 주소록 불러오기 + + + 엑셀 불러오기 + + + 최근 전송내역 + + + 자주보내는 번호 + + + 오류검사 + + 휴대폰 번호 입력 시 해당 휴대폰 번호에 대한 형식이 어긋나거나 휴대폰 번호에 오류가 있는지 등을 검사하는 기능 + (예시) 010-1234-0001(O) / 010-123-0001(X) + + + + + + + 전체삭제 + 선택삭제 + + + 총 0건 / 중복 0건 + + + + + + + + 파일선택 + + + + + + + + + + + + + + + + + + + + + 발송금액 : + + + + + + + + 0.0 원 + + + + + + 보유잔액 + 보유잔액 + + 원 + 충전 + + + + + + + + + 대체문자 + 알림톡 전송 실패 시 문자 전송 + + + + + + + + + + + 발신번호 + + + + + + + ${phonList} + + + + 등록된 발신 번호가 없습니다. + + + + 번호등록 + + + + 내용 + + + + + + + + + + + + 0 / + + 90byte + + 단문 + + + + + 초기화 + 오류검사 + + + + + + + + + + + + + + + + + + + + + + + + + + 알림톡 도착 + + + 템플릿을 선택해 주세요 + + + + + + + + 템플릿 재선택 + + + ※ 단말기 설정에 따라 다르게 보일 수 있습니다 + + + + + + + + 즉시 + + + 예약 + + + + + 발송하기 + 테스트발송 + + + + + 날짜 : + + + + 시 선택 + + + + + + 0${hour}시 + + + ${hour}시 + + + + + 분 선택 + + + + + 0${min}분 + + + ${min}분 + + + + + + + + + 분할전송 + + 건씩 + + 05분 + 10분 + 15분 + 20분 + 30분 + + 간격 + + + + + + + + + + + + + + + + 주소록 불러오기 + + + + + + - 주소록 수정 및 변경은 [주소록 관리]에서만 가능합니다. + 주소록 관리 + + + + + + + + + + 그룹명 검색 + + + + + + + + + + + + + 카테고리 선택 + + 전체 + 그룹명 + 이름 + 핸드폰번호 + + 검색어 입력 + + 검색 + + + + + + + + 추가 + 닫기 + + <%-- 주소록 레이어 팝업 닫기 실행 코드 --%> + + + + + + + + + + + + + + 전송내역 + + + + + + 최근 전송내역 + 자주보내는 번호 + + + + + + + + + + + 최근 전송내역 + + + + + + + + 최근 발송 내역이 없습니다. + + + + + + + 선택추가 + 선택취소 + + + + + + + + + + + + 최근 전송내역 + + + + + + + + 등록된 자주 보내는 번호 내역이 없습니다. + + + + + + + 선택추가 + 선택취소 + + + + + + + + + + + + + + + 엑셀 불러오기 + + + + + + + - 최대 2만 건까지 등록할 수 있습니다. + - [엑셀 불러오기]시 문서의 A, B열을 불러옵니다.(지원하는 파일 형식 : xls, xlsx) + - 휴대폰 항목은 숫자, 하이픈(-)만 인식하며, 번호 앞에 0이 생략되어도 정상 등록됩니다. + + + 샘플파일 다운로드 + + + 첨부파일 + + + + 찾아보기 + + * 첨부된 파일은 [추가]버튼을 클릭하셔야 받는 사람에 등록됩니다. + + + + 추가 + + 닫기 + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp b/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp index edea90ac..242ba050 100644 --- a/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp +++ b/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp @@ -18,8 +18,6 @@ $(document).ready(function(){ - - console.log(": MsgDataSMLView :"); // console.log(' + $(#tabDision).val() : ',$('#tabDision').val()) // if($('#tabDision').val() == 'tab02'){ diff --git a/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp b/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp index 10737a8c..1c3815e6 100644 --- a/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp +++ b/src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp @@ -71,8 +71,6 @@ $(document).ready(function(){ - diff --git a/src/main/webapp/js/MJUtill.js b/src/main/webapp/js/MJUtill.js index 1a1b1990..766a9713 100644 --- a/src/main/webapp/js/MJUtill.js +++ b/src/main/webapp/js/MJUtill.js @@ -200,6 +200,8 @@ function XSSChange(str) { //숫자 천단위 콤마 찍어주기 function numberWithCommas(x) { + console.log(' + typeof x : ',typeof x); + console.log(' + x : ',x); return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } @@ -1030,6 +1032,17 @@ function removeDuplicatesAndCount(array, key) { } +function setAllCntData(result){ + + console.log('result :: ', result); + // 합쳐진 데이터를 tableL에 설정합니다. + tableL.setData(result.uniqueArray); + // 중복데이터 건수 입력 + setRowDupCnt(result.duplicateCount); + + $('#rowTotCnt').text(result.uniqueCount) +} + function validateRowLimit(totalRows, limit = 300000) { // 값과 타입 확인 diff --git a/src/main/webapp/js/kakao/at/addr.js b/src/main/webapp/js/kakao/at/addr.js index b8987c8b..d56d58c8 100644 --- a/src/main/webapp/js/kakao/at/addr.js +++ b/src/main/webapp/js/kakao/at/addr.js @@ -101,6 +101,7 @@ function addrClose(){ } //주소록 불러오기에서 수신자 리스트 추가해 주기 +/* function addrToList(){ var selectedData = tableAddr.getSelectedRows(); @@ -114,10 +115,10 @@ function addrToList(){ }else{ // 선택한 Row 데이터 저장해주기 // 선택한 Row 데이터 저장해주기 - if(selectedData.length > 500){ - alert("최대 발송 건수는 500 입니다."); - return false; - }else{ +// if(selectedData.length > 500){ +// alert("최대 발송 건수는 500 입니다."); +// return false; +// }else{ for(var i=0; i < selectedData.length; i++){ //좌측 받는사람 리스트를 담아둔 배열에 데이터를 추가해 준다. @@ -137,10 +138,68 @@ function addrToList(){ //주소록 레이어 팝업의 Tabulator 데이터 지워주기 tableAddr.clearData(); - } +// } } } +*/ + +//주소록 불러오기에서 수신자 리스트 추가해 주기 +function addrToList_advc(type){ + + + // 선택된 데이터 또는 전체 데이터 변수 초기화 + let selectedData = type === 'select' ? tableAddr.getSelectedRows() : tableAddr.getData(); + + // 데이터가 비어있으면 경고 후 종료 + if (!selectedData || selectedData.length < 1) { + + if(tableAddr.getDataCount() < 1){ + alert("주소록을 선택해 주세요."); + }else{ + alert("전화번호를 선택해 주세요."); + } + + return false; + } + + + // 데이터 변환 로직 + const addrData = selectedData.map(row => { + const rowData = type === 'select' ? row.getData() : row; // 'select'는 행 객체에서 데이터 추출 + return { + phone: removeDash(rowData.phone), + }; + }) + .filter(row => checkHpNum(row.phone)); // 유효한 번호만 필터링; + + + // 기존 tableL의 데이터를 가져옵니다. + var existingData = tableL.getData(); + // 기존 데이터와 새로운 데이터를 합칩니다. + var combinedData = existingData.concat(addrData); + + // @ phone을 기준으로 중복 제거 및 갯수 계산 + const result = removeDuplicatesAndCount(combinedData, 'phone'); + + + + // 총 30만건이 넘으면 false + if (!validateRowLimit(result.uniqueCount)) { + return false; + } + + setAllCntData(result); + + + // 미리보기 버튼 활성화 + + + $(".closeAddr").trigger("click"); + //주소록 레이어 팝업의 Tabulator 데이터 지워주기 + tableAddr.clearData(); + fn_priceClclt(); +} function loadAddrList(){ console.log(' loadAddrList() '); @@ -150,7 +209,8 @@ function loadAddrList(){ */ var data = $("#searchAddrGrpForm").serialize(); - var url = "/web/mjon/msgdata/selectMsgAddrListAjax.do"; + // var url = "/web/mjon/msgdata/selectMsgAddrListAjax.do"; + var url = "/web/mjon/msgdata/selectMsgAddrListAjax_advc.do"; $.ajax({ type: "POST", @@ -159,43 +219,36 @@ function loadAddrList(){ dataType:'json', async: false, cache: false, - success: function (returnData, status) { - console.log('returnData : ', returnData); - if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나 - if(returnData.result == "success"){ - - var addrList = returnData.resultAddrList; - var tableData = []; - - if(addrList.length == 0){ - - alert("주소록 정보가 없습니다."); - tableAddr.setData(tableData); - return false; - } - - //받는사람 리스트를 담아둔 배열에 신규 추가 데이터를 추가해 준다. - for(var i=0; i < addrList.length; i++){ - - tableData.push({addrGroupNm: addrList[i].addrGrpNm, addrPhone: removeDash(addrList[i].addrPhoneNo) , addrName: addrList[i].addrNm, addrRep1: addrList[i].addrInfo1, addrRep2: addrList[i].addrInfo2, addrRep3: addrList[i].addrInfo3, addrRep4: addrList[i].addrInfo4}); - - } - - //우측 주소록 리스트 Tabulator에 입력해주기 - tableAddr.setData(tableData); - - }else{ - - alert(returnData.message); - return false; - - } - - } else if(status== 'fail'){ - alert("주소록 불러오기에 실패하였습니다. !!"); - } - }, - error: function (e) { alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); } + success: function (data) { + console.log('data : ', data); + if(data.status == "OK"){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나 + + var addrList = data.object; + + if(addrList.length == 0){ + + alert("주소록 정보가 없습니다."); +// tableAddr.setData([]); + return false; + } + tableAddr.setData(addrList); + } + else + { + alert("주소록 불러오기에 실패하였습니다. !!"); + } + }, + error: function (e) { + alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); + } + , beforeSend : function(xmlHttpRequest) { + //로딩창 show + $('.loading_layer').addClass('active'); + } + , complete : function(xhr, textStatus) { + //로딩창 hide + $('.loading_layer').removeClass('active'); + } }); } diff --git a/src/main/webapp/js/kakao/at/alimtalkExcel.js b/src/main/webapp/js/kakao/at/alimtalkExcel.js index 76644624..5e571f81 100644 --- a/src/main/webapp/js/kakao/at/alimtalkExcel.js +++ b/src/main/webapp/js/kakao/at/alimtalkExcel.js @@ -198,6 +198,7 @@ function excelAddAjax(){ * * */ function excelExportVarAjax(){ + console.log(' :: excelExportVarAjax ::') var data = document.getElementById('excelFile').files; @@ -245,7 +246,7 @@ function excelAddVarAjax(){ //timeout: 600000, success: function (returnData, status) { if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나 - + console.log('returnData : ', returnData); if(returnData.success){ var data = returnData.data; @@ -290,10 +291,10 @@ function excelAddVarAjax(){ var totalDuplCnt = $('#rowDupCnt').text();//중복 건수 정보 var $excelBody = $('#excelBody02'); - var bodyData; var addDiv = ""; var phoneNum; + var msgCnt = 0; //입력데이터를 역정렬해준다. data.reverse(); @@ -337,6 +338,7 @@ function excelAddVarAjax(){ if(lengthCheck){ addDiv += excelBody; + msgCnt++; } } @@ -359,6 +361,9 @@ function excelAddVarAjax(){ //화면에 수신번호 및 변수 데이터 추가해 주기 $excelBody.append(addDiv); + + // 총 금액 계산 + fn_priceClclt(msgCnt); } diff --git a/src/main/webapp/js/kakao/at/init.js b/src/main/webapp/js/kakao/at/init.js index 74f0ff36..dd38b6ad 100644 --- a/src/main/webapp/js/kakao/at/init.js +++ b/src/main/webapp/js/kakao/at/init.js @@ -12,6 +12,8 @@ * * */ + + $(document).ready(function(){ diff --git a/src/main/webapp/js/kakao/at/priceClclt.js b/src/main/webapp/js/kakao/at/priceClclt.js index fc382e42..a6d26a3f 100644 --- a/src/main/webapp/js/kakao/at/priceClclt.js +++ b/src/main/webapp/js/kakao/at/priceClclt.js @@ -70,8 +70,6 @@ $(document).ready(function(){ fn_priceClclt(); }); - - // 대상 노드에 감시자 전달 observer_wrap01.observe(target01, option); @@ -85,18 +83,24 @@ $(document).ready(function(){ /** * @description 금액 계산 function */ -function fn_priceClclt(){ +function fn_priceClclt(phoneSu = 0){ - // 미리보기 텍스트 - var templateHtml = $('#smsTxtArea').val(); - // var templateHtml = $('.template_text').html(); - - // 수신 번호 개수 - var phoneSu = $('.phoneArea').length; + console.log(":: at fn_priceClclt :: "); + // 미리보기 텍스트 + var templateHtml = $('#smsTxtArea').val(); + // var templateHtml = $('.template_text').html(); + + // 치환문자 여부 확인 + var txtReplYn = $('#txtReplYn').val() + console.log('txtReplYn : ', txtReplYn); + + // 수신 번호 개수 + if(phoneSu == 0 && txtReplYn == 'Y') + phoneSu = $('.phoneArea').length; + if(phoneSu == 0 && txtReplYn == 'N') + phoneSu = tableL.getData().length; // 대체문자 있는지 확인 var isSendFailChecked = $("#send_fail_check").is(":checked"); - // 치환문자 여부 확인 - var txtReplYn = $('#txtReplYn').val() // 대체문자 하위에 장문 / 단문 select var msgTypeText = $('.msg_com').text().trim(); @@ -212,8 +216,8 @@ function fn_writePriceText(msgTypeText, phoneSu){ if(msgTypeText == '단문') price = SHORT_PRICE * phoneSu; else if(msgTypeText == '장문') price = LONG_PRICE * phoneSu; else price = KAKAO_AT_PRICE * phoneSu; // 카카오 - - $('#totalPriceTxt').text((price).toFixed(1)); + + $('#totalPriceTxt').text(numberWithCommas((price).toFixed(1))); } diff --git a/src/main/webapp/js/kakao/at/tabulator.js b/src/main/webapp/js/kakao/at/tabulator.js index 493c1ba7..09095cc9 100644 --- a/src/main/webapp/js/kakao/at/tabulator.js +++ b/src/main/webapp/js/kakao/at/tabulator.js @@ -12,83 +12,41 @@ * * */ - +var tableL = null; $(document).ready(function (){ - /** //받는사람 연락처 내용 처리 //Tabulator AJAX Data Loading - tableL = new Tabulator(".callList_box", { + tableL = new Tabulator(".callList_box_P", { height:"255px", - layout:"fitColumns", - //data:tabledata, - //autoColumns:true, + layout:"fitColumns", + headerHozAlign:"center", + validationMode:"highlight", headerHozAlign:"center", validationMode:"highlight", - //clipboard:false, - //clipboardCopySelector:"table", - //clipboardPasteAction:"insert", // insert, update, replace placeholder:"복사(Ctrl+C)한 내용을 여기에 붙여넣기(Ctrl+V) 해주세요.", //fit columns to width of table (optional) resizableColumns:false, + columnDefaults:{ // 공통설정 + hozAlign: "center", + headerHozAlign: "center", + editor: "input", + editor: false + }, columns:[ //Define Table Columns - {formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){ + {formatter:"rowSelection", titleFormatter:"rowSelection", width:60, clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){ cell.getRow().toggleSelect(); }}, - {title:"이름", hozAlign:"center", field:"name", editor:"input", validator:["maxLength:12"], cellEdited:function(cell){ - //cell - cell component - fnReplCell(); - }}, - {title:"휴대폰", hozAlign:"center", field:"phone", editor:"input", width:100, validator:["required","minLength:10", "maxLength:12"], cellEdited:function(cell){ +// {title:"이름", hozAlign:"center", field:"name", editor:"input", validator:["maxLength:12"], cellEdited:function(cell){ +// //cell - cell component +// fnReplCell(); +// }}, + {title:"휴대폰", hozAlign:"center", field:"phone", editor:"input", validator:["required","minLength:10", "maxLength:12"], cellEdited:function(cell){ //cell - cell component fnDuplPhone(); }}, - {title:"[*1*]", hozAlign:"center", field:"rep1", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){ - //cell - cell component - fnReplCell(); - }}, - {title:"[*2*]", hozAlign:"center", field:"rep2", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){ - //cell - cell component - fnReplCell(); - }}, - {title:"[*3*]", hozAlign:"center", field:"rep3", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){ - //cell - cell component - fnReplCell(); - }}, - {title:"[*4*]", hozAlign:"center", field:"rep4", editor:"input", minWidth:60, validator:["maxLength:40"], cellEdited:function(cell){ - //cell - cell component - fnReplCell(); - }}, - - ], - validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 - 아직 잘 모르겠음 - //take action on validation fail - var valid = cell.isValid(); - var fieldNm = cell.getField(); - var cellVal = cell.getValue(); - var returnVal = ""; - if(!valid){ - - if(fieldNm == "name"){ - alert("받는사람 이름은 최대 12글자까지만 입력 가능합니다."); - cell.setValue(strMaxLengthSubstring(cellVal, 11)); //스크립트 함수가 0부터 시작이므로 원하는 글자수 -1을 해줘야한다. - cell.clearValidation(); - }else if(fieldNm == "phone"){ - alert("휴대폰번호는 하이픈(-)을 제외한 숫자만 정확히 입력해 주세요."); - }else{ - alert("치환문자를 정확히 입력해 주세요. 40글자 이내로 입력 가능합니다."); - cell.setValue(strMaxLengthSubstring(cellVal, 39)); - cell.clearValidation(); - } - - //해당 셀 데이터 삭제 - //cell.setValue(""); - - } - return value % parameters.phone; - }, + ] }); - */ //주소록 불러오기 팝업 내용 //Tabulator AJAX Data Loading tableAddr = new Tabulator(".callAddr_box", { @@ -99,13 +57,13 @@ $(document).ready(function (){ placeholder:"주소록 그룹을 선택해 주세요.", //fit columns to width of table (optional) resizableColumns:false, columns:[ //Define Table Columns - {formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){ + {formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, width: 50, cellClick:function(e, cell){ cell.getRow().toggleSelect(); } }, - {title:"그룹명", hozAlign:"center", field:"addrGroupNm", editor:"input", width:120, validator:["required","minLength:2", "maxLength:40"]}, - {title:"이름", hozAlign:"center", field:"addrName", editor:"input", width:120, validator:["maxLength:12"]}, - {title:"휴대폰번호", hozAlign:"center", field:"addrPhone", editor:"input", width:120, validator:["required","minLength:10", "maxLength:11"]}, + {title:"그룹명", hozAlign:"center", field:"addrGroupNm", widthGrow: 3, editor:"input", validator:["required","minLength:2", "maxLength:40"]}, + {title:"이름", hozAlign:"center", field:"name", widthGrow: 2, editor:"input", validator:["maxLength:12"]}, + {title:"휴대폰번호", hozAlign:"center", field:"phone", widthGrow: 3, editor:"input", validator:["required","minLength:10", "maxLength:11"]}, ], validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 - 아직 잘 모르겠음 @@ -132,53 +90,32 @@ $(document).ready(function (){ //받는사람 번호 버튼 클릭시 Tabulator에 데이터 넣어주기 $('.addCallToF').click(function(){ - var callToNum = $('#callTo').val(); - if(callToNum == null || callToNum == ""){ - - alert("받는사람 번호를 입력해 주세요."); - return false; - - }else if(!checkHpNum(callToNum)){ - - alert("올바른 전화번호를 입력해 주세요."); - $('#callTo').val(""); - return false; - } - - //핸드폰 번호에 '-' 문자 제거하기 - callToNum = removeDash(callToNum); + // checkHpNum(callToNum) + + - var dpCnt = 0; - $(".phoneArea p").each(function(index, item){ - if(this.textContent == callToNum){ - - dpCnt++; - - alert("받는사람 리스트에 동일한 연락처가 있습니다."); - $('#callTo').val(""); - return false; - } - }); - - if(dpCnt > 0){ - alert("받는사람 리스트에 동일한 연락처가 있습니다."); - $('#callTo').val(""); - return false; - }else{ - // fn_displayJsonToHtmlTable 재사용을 위한 - // 파라미터 형변환 - var data =[]; - data.push({ phone: callToNum, name: ''}); - fn_displayJsonToHtmlTable(data); - - /* - * 토탈 카운트 화면에 노출 - */ - updateTotCnt(); - - // 번호 추가란 초기화 - $('#callTo').val(''); - } + var textarea = $('#callTo'); + const numbers = textarea.val().split('\n') + .map(num => removeDash(num.trim())) + .filter(num => num !== "") + .filter(num => checkHpNum(num)); // 유효한 번호만 필터링; + + + + const formattedData = numbers.map(num => ({phone: num})); + + // 기존 tableL의 데이터를 가져옵니다. + var existingData = tableL.getData(); + // 기존 데이터와 새로운 데이터를 합칩니다. + var combinedData = existingData.concat(formattedData); + + // @ phone을 기준으로 중복 제거 및 갯수 계산 + const result = removeDuplicatesAndCount(combinedData, 'phone'); + + setAllCntData(result); + + textarea.val(''); + fn_priceClclt(); }); @@ -442,9 +379,9 @@ var totRows = 0; // 좌측 받는사람 총 갯수 * 토탈 카운트 화면에 노출 * 변수 없는 리스트만 체크 */ -function updateTotCnt(){ +function updateTotCnt(cnt){ - $("#rowTotCnt").text($('#wrap01_body .list_body').length); + $("#rowTotCnt").text(cnt); } @@ -456,10 +393,10 @@ function addPhoneInfo(taData){ return; } - if(taData.length > 500){ - alert("최대 발송 건수는 500건 입니다."); - return; - } +// if(taData.length > 500){ +// alert("최대 발송 건수는 500건 입니다."); +// return; +// } /* diff --git a/src/main/webapp/js/web/msgdata/msgDataView.js b/src/main/webapp/js/web/msgdata/msgDataView.js index df91d245..92558a98 100644 --- a/src/main/webapp/js/web/msgdata/msgDataView.js +++ b/src/main/webapp/js/web/msgdata/msgDataView.js @@ -1269,8 +1269,6 @@ function sendMsgAjax_advc(){ var url = "/web/mjon/msgdata/sendMsgDataAjax_advc.do"; // 시작 시간 - const startTime = new Date(); - // 프로그래스파 시간을 위한 계산 var estimtedTime = calculateEstimatedTime($selectedData.length);
알림
카카오톡 알림톡은 기업회원만 전송 가능합니다.기업회원 전환 페이지로 이동하시겠습니까?
알림톡 전송 결과
문자 전송 결과
휴대폰
휴대폰 번호 입력 시 해당 휴대폰 번호에 대한 형식이 어긋나거나 휴대폰 번호에 오류가 있는지 등을 검사하는 기능
총 0건 / 중복 0건
발송금액 :
0.0 원
대체문자
+ 0 / + + 90byte +
템플릿을 선택해 주세요
※ 단말기 설정에 따라 다르게 보일 수 있습니다
+
주소록 불러오기
- 주소록 수정 및 변경은 [주소록 관리]에서만 가능합니다.
전송내역
최근 발송 내역이 없습니다.
등록된 자주 보내는 번호 내역이 없습니다.
엑셀 불러오기
- 최대 2만 건까지 등록할 수 있습니다.
- [엑셀 불러오기]시 문서의 A, B열을 불러옵니다.(지원하는 파일 형식 : xls, xlsx)
- 휴대폰 항목은 숫자, 하이픈(-)만 인식하며, 번호 앞에 0이 생략되어도 정상 등록됩니다. +
* 첨부된 파일은 [추가]버튼을 클릭하셔야 받는 사람에 등록됩니다.