+++ src/main/java/itn/com/cmm/util/SlackMessageFormatUtil.java
... | ... | @@ -0,0 +1,144 @@ |
| 1 | +package itn.com.cmm.util; | |
| 2 | + | |
| 3 | +import org.apache.commons.lang3.StringUtils; | |
| 4 | + | |
| 5 | +import itn.let.kakao.kakaoComm.KakaoVO; | |
| 6 | +import itn.let.mjo.msg.service.MjonMsgVO; | |
| 7 | + | |
| 8 | +public class SlackMessageFormatUtil { | |
| 9 | + | |
| 10 | + private static final String PREFIX_SMISHING = "[스미싱의심]"; | |
| 11 | + private static final String PREFIX_RESERVE = "[예약]"; | |
| 12 | + private static final String PREFIX_IMAGE = "그림문자 "; | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 일반 SMS 메시지 텍스트 포맷팅 | |
| 16 | + */ | |
| 17 | + public static String formatSmsText(MjonMsgVO mjonMsgVO) { | |
| 18 | + String smsTxt = mjonMsgVO.getSmsTxt(); | |
| 19 | + String reserveYn = safeGetString(mjonMsgVO.getReserveYn()); | |
| 20 | + String delayYn = safeGetString(mjonMsgVO.getDelayYn()); | |
| 21 | + String smishingYn = safeGetString(mjonMsgVO.getSmishingYn()); | |
| 22 | + | |
| 23 | + // 공통 텍스트 포맷팅 로직 적용 | |
| 24 | + smsTxt = formatMessagePrefix(smsTxt, reserveYn, | |
| 25 | + "Y".equals(smishingYn) || "Y".equals(delayYn)); | |
| 26 | + | |
| 27 | + // 그림 문자 처리 (SMS 전용 로직) | |
| 28 | + int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0); | |
| 29 | + if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isEmpty(smsTxt)) { | |
| 30 | + smsTxt = "그림문자 " + smsTxt; | |
| 31 | + } | |
| 32 | + | |
| 33 | + return smsTxt; | |
| 34 | + } | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 카카오톡 메시지 텍스트 포맷팅 | |
| 38 | + */ | |
| 39 | + public static String formatKakaoText(KakaoVO kakaoVO) { | |
| 40 | + String smsTxt = kakaoVO.getTemplateContent(); | |
| 41 | + String reserveYn = safeGetString(kakaoVO.getReserveYn()); | |
| 42 | + String atDelayYn = safeGetString(kakaoVO.getAtDelayYn()); | |
| 43 | + | |
| 44 | + // 공통 텍스트 포맷팅 로직 적용 | |
| 45 | + return formatMessagePrefix(smsTxt, reserveYn, "Y".equals(atDelayYn)); | |
| 46 | + } | |
| 47 | + | |
| 48 | + | |
| 49 | + public static String formatSandName(MjonMsgVO mjonMsgVO) { | |
| 50 | + String userId = mjonMsgVO.getUserId(); | |
| 51 | + String callFrom = mjonMsgVO.getCallFrom(); | |
| 52 | + String msgType = getMessageTypeLabel(mjonMsgVO.getMsgType(), mjonMsgVO.getFileCnt()); | |
| 53 | + return String.format("[%s][%s]%s", userId, callFrom, msgType); | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 메시지 접두사 포맷팅 공통 로직 (예약 및 스미싱 의심 접두사 처리) | |
| 58 | + * | |
| 59 | + * @param messageText 원본 메시지 텍스트 | |
| 60 | + * @param reserveYn 예약 여부 | |
| 61 | + * @param isSmishing 스미싱 의심 여부 | |
| 62 | + * @return 포맷팅된 메시지 텍스트 | |
| 63 | + */ | |
| 64 | + public static String formatMessagePrefix(String messageText, String reserveYn, boolean isSmishing) { | |
| 65 | + if ("Y".equals(reserveYn)) { | |
| 66 | + return isSmishing ? PREFIX_SMISHING + PREFIX_RESERVE + messageText : PREFIX_RESERVE + messageText; | |
| 67 | + } else if (isSmishing) { | |
| 68 | + return PREFIX_SMISHING + messageText; | |
| 69 | + } | |
| 70 | + return messageText; | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * @카카오톡용 sandName 포맷팅 메서드 | |
| 75 | + */ | |
| 76 | + public static String formatKakaoSandName(KakaoVO kakaoVO) { | |
| 77 | + String userId = kakaoVO.getUserId(); | |
| 78 | + String callFrom = kakaoVO.getCallFrom(); | |
| 79 | + String msgType = getKakaoMessageTypeLabel(kakaoVO.getMsgType()); | |
| 80 | + return String.format("[%s][%s]%s", userId, callFrom, msgType); | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * 메시지 타입 레이블 반환 (SMS 전용) | |
| 85 | + * | |
| 86 | + * @param msgType 메시지 타입 | |
| 87 | + * @param fileCnt 파일 개수 | |
| 88 | + * @return 메시지 타입 레이블 | |
| 89 | + */ | |
| 90 | + public static String getMessageTypeLabel(String msgType, String fileCnt) { | |
| 91 | + int fileCount = parseIntOrDefault(fileCnt, 0); | |
| 92 | + | |
| 93 | + switch (msgType) { | |
| 94 | + case "4": | |
| 95 | + return "[단문]"; | |
| 96 | + case "6": | |
| 97 | + return fileCount == 0 ? "[장문]" : "[그림]"; | |
| 98 | + default: | |
| 99 | + return ""; | |
| 100 | + } | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * 카카오톡 메시지 타입 레이블 반환 | |
| 105 | + * | |
| 106 | + * @param msgType 메시지 타입 | |
| 107 | + * @return 메시지 타입 레이블 | |
| 108 | + */ | |
| 109 | + public static String getKakaoMessageTypeLabel(String msgType) { | |
| 110 | + switch (msgType) { | |
| 111 | + case "8": | |
| 112 | + return "[알림톡]"; | |
| 113 | + case "9": | |
| 114 | + return "[친구톡]"; | |
| 115 | + default: | |
| 116 | + return ""; | |
| 117 | + } | |
| 118 | + } | |
| 119 | + | |
| 120 | + /** | |
| 121 | + * 정수로 변환, 변환 실패 시 기본값 반환 | |
| 122 | + * | |
| 123 | + * @param value 변환할 문자열 | |
| 124 | + * @param defaultValue 기본값 | |
| 125 | + * @return 변환된 정수 또는 기본값 | |
| 126 | + */ | |
| 127 | + public static int parseIntOrDefault(String value, int defaultValue) { | |
| 128 | + try { | |
| 129 | + return Integer.parseInt(value); | |
| 130 | + } catch (NumberFormatException e) { | |
| 131 | + return defaultValue; | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * 안전하게 문자열 가져오기 (null 체크) | |
| 137 | + * | |
| 138 | + * @param value 원본 문자열 | |
| 139 | + * @return 원본 문자열 또는 빈 문자열 | |
| 140 | + */ | |
| 141 | + public static String safeGetString(String value) { | |
| 142 | + return value == null ? "" : value; | |
| 143 | + } | |
| 144 | +} |
--- src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
+++ src/main/java/itn/let/kakao/kakaoComm/KakaoSendUtil.java
... | ... | @@ -73,7 +73,7 @@ |
| 73 | 73 |
* @throws Exception |
| 74 | 74 |
* |
| 75 | 75 |
*/ |
| 76 |
- public List<KakaoSendAdvcVO> populateSendLists(KakaoVO kakaoVO, boolean isHolidayNotified, StatusResponse statusResponse) throws Exception {
|
|
| 76 |
+ public List<KakaoSendAdvcVO> populateSendLists(KakaoVO kakaoVO, boolean isNotified, StatusResponse statusResponse) throws Exception {
|
|
| 77 | 77 |
|
| 78 | 78 |
//사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액) |
| 79 | 79 |
// String befCash = kakaoVO.getBefCash(); |
... | ... | @@ -84,7 +84,7 @@ |
| 84 | 84 |
log.info(" +kakaoVO.getVarListMap().size() :: [{}]", kakaoVO.getVarListMap().size());
|
| 85 | 85 |
|
| 86 | 86 |
List<KakaoSendAdvcVO> kakaoSendAdvcListVO = new ArrayList<>(); |
| 87 |
- Calendar calendar = setupBaseDate(kakaoVO, isHolidayNotified); |
|
| 87 |
+ Calendar calendar = setupBaseDate(kakaoVO, isNotified); |
|
| 88 | 88 |
|
| 89 | 89 |
|
| 90 | 90 |
|
... | ... | @@ -120,9 +120,7 @@ |
| 120 | 120 |
|
| 121 | 121 |
|
| 122 | 122 |
/** @MSGID KEY값 */ |
| 123 |
- log.info("idList ===================================================== ");
|
|
| 124 | 123 |
List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getVarListMap().size()); |
| 125 |
- log.info("+ idList:: [{}]", idList.toArray().toString());
|
|
| 126 | 124 |
// for (int i = 0; i < kakaoSendAdvcListVO.size(); i++) {
|
| 127 | 125 |
// kakaoSendAdvcListVO.get(i).setMsgId(idList.get(i)); |
| 128 | 126 |
// kakaoSendAdvcListVO.get(i).setBizJsonName(idList.get(i)); |
... | ... | @@ -270,7 +268,7 @@ |
| 270 | 268 |
return kakaoSendAdvcListVO; |
| 271 | 269 |
} |
| 272 | 270 |
|
| 273 |
- private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isHolidayNotified) throws ParseException {
|
|
| 271 |
+ private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isNotified) throws ParseException {
|
|
| 274 | 272 |
// 예약 시간 기본값 설정 |
| 275 | 273 |
Date now = new Date(); |
| 276 | 274 |
// ReqDate가 비어 있으면 현재 시간으로 설정, 그렇지 않으면 ReqDate로 설정 |
... | ... | @@ -290,7 +288,7 @@ |
| 290 | 288 |
// 지연 여부 처리 |
| 291 | 289 |
// 알림톡 스미싱의심 + 공휴일알림 조건이 맞으면 30분 delay |
| 292 | 290 |
if ( "Y".equalsIgnoreCase(kakaoVO.getAtSmishingYn()) |
| 293 |
- && isHolidayNotified) {
|
|
| 291 |
+ && isNotified) {
|
|
| 294 | 292 |
calendar.add(Calendar.MINUTE, 30); // 모든 시간을 30분 뒤로 미룸 |
| 295 | 293 |
} |
| 296 | 294 |
return calendar; |
--- src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/service/impl/KakaoAlimTalkServiceImpl.java
... | ... | @@ -899,7 +899,7 @@ |
| 899 | 899 |
/** @isHolidayNotified |
| 900 | 900 |
* @false : 알림 X |
| 901 | 901 |
* @true : 알림 O */ |
| 902 |
- boolean isHolidayNotified = mjonCommon.handleSmishingAlert(); |
|
| 902 |
+ boolean isNotified = mjonCommon.processUserAndCheckAT(kakaoVO); |
|
| 903 | 903 |
|
| 904 | 904 |
|
| 905 | 905 |
/** @LETTNGNRLMBER 사용자 정보 -> 스미싱의심 여부 */ |
... | ... | @@ -907,7 +907,7 @@ |
| 907 | 907 |
kakaoVO.setAtSmishingYn(userManageVO.getAtSmishingYn()); |
| 908 | 908 |
|
| 909 | 909 |
/** @카카오톡 전송 list 셋팅 -------------------------------------------*/ |
| 910 |
- List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, isHolidayNotified, statusResponse); |
|
| 910 |
+ List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendLists(kakaoVO, isNotified, statusResponse); |
|
| 911 | 911 |
if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) {
|
| 912 | 912 |
log.error(" + populateSendLists 처리 중 오류 발생: {}", statusResponse.getMessage());
|
| 913 | 913 |
return statusResponse; |
... | ... | @@ -923,13 +923,14 @@ |
| 923 | 923 |
|
| 924 | 924 |
|
| 925 | 925 |
|
| 926 |
- start = Instant.now(); |
|
| 927 | 926 |
Map<String, List<KakaoSendAdvcVO>> priceGroupedMessages = kakaoSendAdvcListVO.stream() |
| 928 | 927 |
.collect(Collectors.groupingBy(KakaoSendAdvcVO::getEachPrice)); |
| 929 | 928 |
|
| 930 | 929 |
|
| 931 | 930 |
// instTotalCnt : 화면에서 보여줄 총 발송건수 |
| 932 | 931 |
int instTotalCnt = 0; |
| 932 |
+ // 임시 |
|
| 933 |
+ List<String> nextMsgGroupIdA = new ArrayList<>(); |
|
| 933 | 934 |
// 대안: entrySet() 직접 사용 |
| 934 | 935 |
for (Map.Entry<String, List<KakaoSendAdvcVO>> entry : priceGroupedMessages.entrySet()) {
|
| 935 | 936 |
// entry 사용 |
... | ... | @@ -965,22 +966,39 @@ |
| 965 | 966 |
|
| 966 | 967 |
priceAndPoint.insertCashAndPoint(kakaoVO.getUserId() |
| 967 | 968 |
, -Float.parseFloat(sendVO.getTotPrice()) |
| 968 |
-// , "SMS 문자 " + groupedMsgList.size() + "건 발송" |
|
| 969 | 969 |
, "카카오 알림톡 총 "+groupedMsgList.size()+"건 중 " + instCnt + "건 발송" |
| 970 | 970 |
, nextMsgGroupId |
| 971 | 971 |
); |
| 972 |
+ |
|
| 973 |
+ |
|
| 974 |
+/** @SLACK발송 */ |
|
| 975 |
+ /** @발송조건이되면 발송 */ |
|
| 976 |
+ if(isNotified) {
|
|
| 977 |
+ mjonCommon.getAdminKakaoAtSendSlack(kakaoVO); |
|
| 978 |
+ }else if("Y".equals(kakaoVO.getAtSmishingYn())){
|
|
| 979 |
+ /** @발송조건이 안되면 DB INSERT */ |
|
| 980 |
+ mjonMsgDAO.insertSpamPassMsgData(MjonMsgVO.builder() |
|
| 981 |
+ .msgGroupId(nextMsgGroupId) |
|
| 982 |
+ .userId(kakaoVO.getUserId()) |
|
| 983 |
+ .reqDate(kakaoVO.getReqDate()) |
|
| 984 |
+ .smsTxt(groupedMsgList.get(0).getTemplateContent()) |
|
| 985 |
+ .totalCallCnt(instCnt) |
|
| 986 |
+ .callFrom(kakaoVO.getCallFrom()) |
|
| 987 |
+ .msgType("8")
|
|
| 988 |
+ .reserveYn(kakaoVO.getReserveYn()) |
|
| 989 |
+ .build() |
|
| 990 |
+ ); |
|
| 991 |
+ } |
|
| 972 | 992 |
|
| 993 |
+ nextMsgGroupIdA.add(nextMsgGroupId); |
|
| 973 | 994 |
|
| 974 | 995 |
} |
| 975 | 996 |
|
| 976 |
- |
|
| 977 | 997 |
} |
| 978 |
- |
|
| 979 |
- |
|
| 980 |
- if(isHolidayNotified |
|
| 981 |
- && "Y".equals(kakaoVO.getAtSmishingYn())) {
|
|
| 982 |
- |
|
| 983 |
- } |
|
| 998 |
+ |
|
| 999 |
+ returnMap.put("resultSts", instTotalCnt);
|
|
| 1000 |
+ returnMap.put("reserYn", kakaoVO.getReserveYn());
|
|
| 1001 |
+ returnMap.put("groupIds", nextMsgGroupIdA);
|
|
| 984 | 1002 |
|
| 985 | 1003 |
|
| 986 | 1004 |
// 측정할 메소드 호출 후 시간 기록 |
... | ... | @@ -988,15 +1006,15 @@ |
| 988 | 1006 |
|
| 989 | 1007 |
log.info(" + start :: [{}]", start);
|
| 990 | 1008 |
// 실행 시간 계산 (나노초, 밀리초, 초) |
| 991 |
- System.out.println("메소드 실행 시간 (초): " + Duration.between(start, end).getSeconds() + " s");
|
|
| 992 |
- System.out.println("메소드 실행 시간 (Nano): " + Duration.between(start, end).getNano() + " Nano");
|
|
| 993 |
-// kakaoSendAdvcListVO.forEach(t-> log.info(" + t.toString() :: [{}]", t.toString()) );
|
|
| 1009 |
+ long seconds = Duration.between(start, end).getSeconds(); |
|
| 1010 |
+ System.out.println("메소드 실행 시간 (초): " + seconds + " s");
|
|
| 1011 |
+ double minutes = seconds / 60.0; // 소수점 포함을 위해 60.0으로 나눔 |
|
| 1012 |
+ |
|
| 1013 |
+ returnMap.put("second", seconds+" s");
|
|
| 1014 |
+ returnMap.put("minutes", minutes+" min");
|
|
| 994 | 1015 |
|
| 995 |
-// idgenMjonMsgGroupId.getNextStringId(); |
|
| 996 |
- |
|
| 997 |
- |
|
| 998 |
- |
|
| 999 |
- |
|
| 1016 |
+ |
|
| 1017 |
+// System.out.println("메소드 실행 시간 (분): " + minutes + " min");
|
|
| 1000 | 1018 |
|
| 1001 | 1019 |
|
| 1002 | 1020 |
|
... | ... | @@ -1005,7 +1023,9 @@ |
| 1005 | 1023 |
|
| 1006 | 1024 |
|
| 1007 | 1025 |
|
| 1008 |
- |
|
| 1026 |
+ |
|
| 1027 |
+ statusResponse.setStatus(HttpStatus.OK); |
|
| 1028 |
+ statusResponse.setObject(returnMap); |
|
| 1009 | 1029 |
|
| 1010 | 1030 |
return statusResponse; |
| 1011 | 1031 |
} |
... | ... | @@ -1032,6 +1052,7 @@ |
| 1032 | 1052 |
sendVO.setAtDelayYn(kakaoVO.getAtSmishingYn()); |
| 1033 | 1053 |
sendVO.setBizKakaoResendOrgnlTxt(kakaoVO.getSubMsgTxt()); |
| 1034 | 1054 |
sendVO.setBizKakaoResendType(sendVO.getSubMsgType()); |
| 1055 |
+ |
|
| 1035 | 1056 |
kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc(sendVO); |
| 1036 | 1057 |
|
| 1037 | 1058 |
} |
--- src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java
+++ src/main/java/itn/let/kakao/user/kakaoAt/web/KakaoAlimTalkSendController.java
... | ... | @@ -1408,7 +1408,7 @@ |
| 1408 | 1408 |
|
| 1409 | 1409 |
if(!smishingAlarmPassSts) {//평일,주말, 공휴일 알림설정 시간에 포함되지 않는 경우 슬랙 알림 발송
|
| 1410 | 1410 |
|
| 1411 |
- mjonCommon.getAdminKakaoAtSandSlack(kakaoVO); |
|
| 1411 |
+ mjonCommon.getAdminKakaoAtSendSlack(kakaoVO); |
|
| 1412 | 1412 |
|
| 1413 | 1413 |
} |
| 1414 | 1414 |
|
--- src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
+++ src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
... | ... | @@ -26,6 +26,7 @@ |
| 26 | 26 |
import itn.com.cmm.MjonMsgSendVO; |
| 27 | 27 |
import itn.com.cmm.OptimalMsgResultDTO; |
| 28 | 28 |
import itn.com.cmm.util.MsgSendUtils; |
| 29 |
+import itn.com.cmm.util.SlackMessageFormatUtil; |
|
| 29 | 30 |
import itn.let.kakao.kakaoComm.KakaoVO; |
| 30 | 31 |
import itn.let.mail.service.StatusResponse; |
| 31 | 32 |
import itn.let.mjo.event.service.MjonEventService; |
... | ... | @@ -72,7 +73,7 @@ |
| 72 | 73 |
|
| 73 | 74 |
|
| 74 | 75 |
/** |
| 75 |
- * @methodName : getAdminMsgSandSlack |
|
| 76 |
+ * @methodName : getAdminSandSlack |
|
| 76 | 77 |
* @author : 이호영 |
| 77 | 78 |
* @date : 2024.12.04 |
| 78 | 79 |
* @description : 기존 메소드 리펙토링 |
... | ... | @@ -128,8 +129,8 @@ |
| 128 | 129 |
|
| 129 | 130 |
try {
|
| 130 | 131 |
// 메시지 내용 설정 |
| 131 |
- String smsTxt = formatSmsText(mjonMsgVO); |
|
| 132 |
- String sandName = formatSandName(mjonMsgVO); |
|
| 132 |
+ String smsTxt = SlackMessageFormatUtil.formatSmsText(mjonMsgVO); |
|
| 133 |
+ String sandName = SlackMessageFormatUtil.formatSandName(mjonMsgVO); |
|
| 133 | 134 |
|
| 134 | 135 |
// Slack 메시지 생성 |
| 135 | 136 |
JSONObject json = new JSONObject(); |
... | ... | @@ -158,21 +159,21 @@ |
| 158 | 159 |
} |
| 159 | 160 |
} |
| 160 | 161 |
|
| 161 |
- public void getAdminKakaoAtSandSlack(KakaoVO kakaoVO) {
|
|
| 162 |
+ public void getAdminKakaoAtSendSlack(KakaoVO kakaoVO) {
|
|
| 162 | 163 |
HttpClient client = new HttpClient(); |
| 163 | 164 |
PostMethod post = new PostMethod(SLACK_URL); |
| 164 |
- |
|
| 165 |
+ |
|
| 165 | 166 |
try {
|
| 166 | 167 |
// 메시지 내용 설정 |
| 167 |
- String smsTxt = formatKakaoText(kakaoVO); |
|
| 168 |
- String sandName = formatKakaoSandName(kakaoVO); |
|
| 169 |
- |
|
| 168 |
+ String smsTxt = SlackMessageFormatUtil.formatKakaoText(kakaoVO); |
|
| 169 |
+ String sandName = SlackMessageFormatUtil.formatKakaoSandName(kakaoVO); |
|
| 170 |
+ |
|
| 170 | 171 |
// Slack 메시지 생성 |
| 171 | 172 |
JSONObject json = new JSONObject(); |
| 172 | 173 |
json.put("channel", SLACK_CHANNEL);
|
| 173 | 174 |
json.put("text", smsTxt);
|
| 174 | 175 |
json.put("username", sandName);
|
| 175 |
- |
|
| 176 |
+ |
|
| 176 | 177 |
// Slack 요청 |
| 177 | 178 |
post.addParameter("payload", json.toString());
|
| 178 | 179 |
post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
... | ... | @@ -180,9 +181,8 @@ |
| 180 | 181 |
// Slack 응답 처리 |
| 181 | 182 |
int responseCode = client.executeMethod(post); |
| 182 | 183 |
if (responseCode != HttpStatus.SC_OK) {
|
| 183 |
- log.warn("Slack 메시지 전송 실패. Response: {}", post.getResponseBodyAsString());
|
|
| 184 |
+ log.warn("Slack 메시지 전송 실패. Response: {}", post.getResponseBodyAsString());
|
|
| 184 | 185 |
} |
| 185 |
- |
|
| 186 | 186 |
} catch (IllegalArgumentException e) {
|
| 187 | 187 |
log.error("Slack 메시지 전송 중 IllegalArgumentException 발생", e);
|
| 188 | 188 |
} catch (IOException e) {
|
... | ... | @@ -200,32 +200,6 @@ |
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 | 202 |
|
| 203 |
- |
|
| 204 |
- /** |
|
| 205 |
- * 카카오톡 메시지 텍스트 포맷팅 |
|
| 206 |
- */ |
|
| 207 |
- public String formatKakaoText(KakaoVO kakaoVO) {
|
|
| 208 |
- String smsTxt = kakaoVO.getTemplateContent(); |
|
| 209 |
- String reserveYn = safeGetString(kakaoVO.getReserveYn()); |
|
| 210 |
- String atDelayYn = safeGetString(kakaoVO.getAtDelayYn()); |
|
| 211 |
- |
|
| 212 |
- // 공통 텍스트 포맷팅 로직 적용 |
|
| 213 |
- return formatMessagePrefix(smsTxt, reserveYn, "Y".equals(atDelayYn)); |
|
| 214 |
- } |
|
| 215 |
- |
|
| 216 |
- |
|
| 217 |
- /** |
|
| 218 |
- * 메시지 접두사 포맷팅 공통 로직 |
|
| 219 |
- * (예약 및 스미싱 의심 접두사 처리) |
|
| 220 |
- */ |
|
| 221 |
- private static String formatMessagePrefix(String messageText, String reserveYn, boolean isSmishing) {
|
|
| 222 |
- if ("Y".equals(reserveYn)) {
|
|
| 223 |
- return isSmishing ? "[스미싱의심][예약]" + messageText : "[예약]" + messageText; |
|
| 224 |
- } else if (isSmishing) {
|
|
| 225 |
- return "[스미싱의심]" + messageText; |
|
| 226 |
- } |
|
| 227 |
- return messageText; |
|
| 228 |
- } |
|
| 229 | 203 |
|
| 230 | 204 |
|
| 231 | 205 |
/** |
... | ... | @@ -374,7 +348,7 @@ |
| 374 | 348 |
|
| 375 | 349 |
return mjonMsgVO; |
| 376 | 350 |
} |
| 377 |
- |
|
| 351 |
+ /* |
|
| 378 | 352 |
@SuppressWarnings("unchecked")
|
| 379 | 353 |
public void getAdminKakaoAtSandSlack(KakaoVO kakaoVO) {
|
| 380 | 354 |
|
... | ... | @@ -438,7 +412,7 @@ |
| 438 | 412 |
} |
| 439 | 413 |
|
| 440 | 414 |
} |
| 441 |
- |
|
| 415 |
+ */ |
|
| 442 | 416 |
|
| 443 | 417 |
public String getCreateMsgUserIdgen(String subUserId, String lastId) throws Exception{
|
| 444 | 418 |
|
... | ... | @@ -475,27 +449,6 @@ |
| 475 | 449 |
|
| 476 | 450 |
|
| 477 | 451 |
|
| 478 |
-private String formatSmsText(MjonMsgVO mjonMsgVO) {
|
|
| 479 |
- String smsTxt = mjonMsgVO.getSmsTxt(); |
|
| 480 |
- String reserveYn = safeGetString(mjonMsgVO.getReserveYn()); |
|
| 481 |
- String delayYn = safeGetString(mjonMsgVO.getDelayYn()); |
|
| 482 |
- String smishingYn = safeGetString(mjonMsgVO.getSmishingYn()); |
|
| 483 |
- |
|
| 484 |
- // 예약 문자와 스미싱 의심 처리 |
|
| 485 |
- if ("Y".equals(reserveYn)) {
|
|
| 486 |
- smsTxt = ("Y".equals(smishingYn) || "Y".equals(delayYn)) ? "[스미싱의심][예약]" + smsTxt : "[예약]" + smsTxt;
|
|
| 487 |
- } else if ("Y".equals(smishingYn) || "Y".equals(delayYn)) {
|
|
| 488 |
- smsTxt = "[스미싱의심]" + smsTxt; |
|
| 489 |
- } |
|
| 490 |
- |
|
| 491 |
- // 그림 문자 처리 |
|
| 492 |
- int fileCount = parseIntOrDefault(mjonMsgVO.getFileCnt(), 0); |
|
| 493 |
- if ("6".equals(mjonMsgVO.getMsgType()) && fileCount > 0 && StringUtils.isNullOrEmpty(smsTxt)) {
|
|
| 494 |
- smsTxt = "그림문자 " + smsTxt; |
|
| 495 |
- } |
|
| 496 |
- |
|
| 497 |
- return smsTxt; |
|
| 498 |
-} |
|
| 499 | 452 |
|
| 500 | 453 |
private String formatSandName(MjonMsgVO mjonMsgVO) {
|
| 501 | 454 |
String userId = mjonMsgVO.getUserId(); |
... | ... | @@ -532,7 +485,18 @@ |
| 532 | 485 |
|
| 533 | 486 |
|
| 534 | 487 |
|
| 535 |
- // 전체 로직 처리 (한 번에 모든 필요한 정보 반환) |
|
| 488 |
+ /** |
|
| 489 |
+ * @methodName : processUserAndCheckSms |
|
| 490 |
+ * @author : 이호영 |
|
| 491 |
+ * @date : 2025. 3. 25. |
|
| 492 |
+ * @description : SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환) |
|
| 493 |
+ * @return : boolean |
|
| 494 |
+ * @param mjonMsgVO |
|
| 495 |
+ * @param userId |
|
| 496 |
+ * @return |
|
| 497 |
+ * @throws Exception |
|
| 498 |
+ * |
|
| 499 |
+ */ |
|
| 536 | 500 |
public boolean processUserAndCheckSms(MjonMsgVO mjonMsgVO, String userId) throws Exception {
|
| 537 | 501 |
UserManageVO userManageVO = getUserManageInfo(userId); |
| 538 | 502 |
|
... | ... | @@ -551,6 +515,36 @@ |
| 551 | 515 |
|
| 552 | 516 |
return false; // 알림 처리되지 않음 |
| 553 | 517 |
} |
| 518 |
+ |
|
| 519 |
+ /** |
|
| 520 |
+ * @methodName : processUserAndCheckAT |
|
| 521 |
+ * @author : 이호영 |
|
| 522 |
+ * @date : 2025. 3. 25. |
|
| 523 |
+ * @description : SMS 알림 전체 로직 처리 (한 번에 모든 필요한 정보 반환) |
|
| 524 |
+ * @return : boolean |
|
| 525 |
+ * @param mjonMsgVO |
|
| 526 |
+ * @param userId |
|
| 527 |
+ * @return |
|
| 528 |
+ * @throws Exception |
|
| 529 |
+ * |
|
| 530 |
+ */ |
|
| 531 |
+ public boolean processUserAndCheckAT(KakaoVO kakaoVO) throws Exception {
|
|
| 532 |
+ UserManageVO userManageVO = getUserManageInfo(kakaoVO.getUserId()); |
|
| 533 |
+ |
|
| 534 |
+ // 기본값 처리된 사용자 정보와 문자 상태 |
|
| 535 |
+ String adminSmsNoticeYn = userManageVO.getAdminSmsNoticeYn(); |
|
| 536 |
+ String atSmishingYn = userManageVO.getAtSmishingYn(); |
|
| 537 |
+ |
|
| 538 |
+ // 조건 체크 |
|
| 539 |
+ if ("Y".equals(adminSmsNoticeYn) || "Y".equals(atSmishingYn)) {
|
|
| 540 |
+ kakaoVO.setAtSmishingYn(atSmishingYn); // MjonMsgVO에 스미싱 정보 설정 |
|
| 541 |
+ |
|
| 542 |
+ // 스미싱 알림 처리 |
|
| 543 |
+ return handleSmishingAlert(); // 알림 처리 결과 반환 |
|
| 544 |
+ } |
|
| 545 |
+ |
|
| 546 |
+ return false; // 알림 처리되지 않음 |
|
| 547 |
+ } |
|
| 554 | 548 |
|
| 555 | 549 |
// 사용자 정보 조회 및 기본값 처리 |
| 556 | 550 |
public UserManageVO getUserManageInfo(String userId) throws Exception {
|
--- src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java
+++ src/main/java/itn/let/mjo/msg/service/MjonMsgVO.java
... | ... | @@ -7,12 +7,18 @@ |
| 7 | 7 |
|
| 8 | 8 |
import itn.com.cmm.ComDefaultVO; |
| 9 | 9 |
import itn.com.cmm.MjonMsgSendVO; |
| 10 |
+import lombok.AllArgsConstructor; |
|
| 11 |
+import lombok.Builder; |
|
| 10 | 12 |
import lombok.Getter; |
| 13 |
+import lombok.NoArgsConstructor; |
|
| 11 | 14 |
import lombok.Setter; |
| 12 | 15 |
|
| 13 | 16 |
@JsonIgnoreProperties(ignoreUnknown = true) |
| 14 | 17 |
@Getter |
| 15 | 18 |
@Setter |
| 19 |
+@Builder |
|
| 20 |
+@NoArgsConstructor |
|
| 21 |
+@AllArgsConstructor |
|
| 16 | 22 |
public class MjonMsgVO extends ComDefaultVO{
|
| 17 | 23 |
|
| 18 | 24 |
private static final long serialVersionUID = 1L; |
--- src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/kakao/msgdata/at/KakaoAlimtalkMsgDataView.jsp
... | ... | @@ -686,16 +686,38 @@ |
| 686 | 686 |
|
| 687 | 687 |
if(confirm("알림톡을 발송하시겠습니까?")){
|
| 688 | 688 |
|
| 689 |
- |
|
| 690 |
- |
|
| 691 |
- $.ajax({
|
|
| 692 |
- type: "POST", |
|
| 693 |
- url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do", |
|
| 694 |
- data: JSON.stringify(formData), |
|
| 695 |
- contentType: 'application/json', |
|
| 696 |
- dataType: 'json', |
|
| 697 |
- success: function (data) {
|
|
| 689 |
+ // 프로그래스파 시간을 위한 계산 |
|
| 690 |
+ var estimtedTime = calculateEstimatedTime(dataList.length); |
|
| 691 |
+ |
|
| 692 |
+ $.ajax({
|
|
| 693 |
+ type: "POST", |
|
| 694 |
+ url: "/web/mjon/kakao/alimtalk/kakaoAlimTalkMsgSendAjax_advc.do", |
|
| 695 |
+ data: JSON.stringify(formData), |
|
| 696 |
+ contentType: 'application/json', |
|
| 697 |
+ dataType: 'json', |
|
| 698 |
+ success: function (data) {
|
|
| 698 | 699 |
console.log('data : ', data);
|
| 700 |
+ |
|
| 701 |
+ |
|
| 702 |
+ |
|
| 703 |
+ var status = data.status; |
|
| 704 |
+ if("OK" == status){
|
|
| 705 |
+ var resultSts = data.object.resultSts; |
|
| 706 |
+ var reserYn = data.object.reserYn; |
|
| 707 |
+ var resText = (reserYn === 'Y') ? '예약' : '발송'; |
|
| 708 |
+ |
|
| 709 |
+ $('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
|
|
| 710 |
+ $('.pop_msg_success .msg_text').html(resText+" 성공 : <strong>"+ resultSts + "</strong>건의<br>알림톡이 " + resText + " 되었습니다.");
|
|
| 711 |
+ |
|
| 712 |
+ }else if("UNAUTHORIZED" == status){
|
|
| 713 |
+ alert(data.message); |
|
| 714 |
+ location.reload(); |
|
| 715 |
+ }else{
|
|
| 716 |
+ alert(data.message); |
|
| 717 |
+ return false; |
|
| 718 |
+ } |
|
| 719 |
+ |
|
| 720 |
+ |
|
| 699 | 721 |
// if(data == 'success'){
|
| 700 | 722 |
/* if("loginFail" == returnData.result){
|
| 701 | 723 |
|
... | ... | @@ -731,11 +753,16 @@ |
| 731 | 753 |
} |
| 732 | 754 |
,beforeSend : function(xmlHttpRequest) {
|
| 733 | 755 |
//로딩창 show |
| 734 |
- $('.loading_layer').addClass('active');
|
|
| 756 |
+// $('.loading_layer').addClass('active');
|
|
| 757 |
+ // 프로그래스 바 실행 |
|
| 758 |
+ progressStart(estimtedTime); |
|
| 735 | 759 |
} |
| 736 | 760 |
,complete : function(xhr, textStatus) {
|
| 737 | 761 |
//로딩창 hide |
| 738 |
- $('.loading_layer').removeClass('active');
|
|
| 762 |
+// $('.loading_layer').removeClass('active');
|
|
| 763 |
+ |
|
| 764 |
+ // 프로그래스 바 종료 |
|
| 765 |
+ progressComplete();; |
|
| 739 | 766 |
} |
| 740 | 767 |
,error: function (e) {
|
| 741 | 768 |
console.log("ERROR : ", e);
|
... | ... | @@ -743,6 +770,82 @@ |
| 743 | 770 |
} |
| 744 | 771 |
}); |
| 745 | 772 |
} |
| 773 |
+} |
|
| 774 |
+//선택된 데이터의 길이에 따라 예상 시간 계산 함수 |
|
| 775 |
+function calculateEstimatedTime(selectedCount) {
|
|
| 776 |
+ //기준값 |
|
| 777 |
+ // const processTimePerBatch = 130; // 130초 |
|
| 778 |
+ |
|
| 779 |
+ |
|
| 780 |
+ // 30만건 기준 10분으로 기준을 잡아서 |
|
| 781 |
+ // 시간계산함 |
|
| 782 |
+ const processTimePerBatch = 600; |
|
| 783 |
+ const batchSize = 300000; |
|
| 784 |
+ |
|
| 785 |
+ // 1건당 처리 시간 |
|
| 786 |
+ const timePerRecord = processTimePerBatch / batchSize; |
|
| 787 |
+ |
|
| 788 |
+ // 예상 시간 계산 |
|
| 789 |
+ const estimatedTimeInSeconds = selectedCount * timePerRecord; |
|
| 790 |
+ |
|
| 791 |
+ return estimatedTimeInSeconds.toFixed(2); |
|
| 792 |
+} |
|
| 793 |
+ |
|
| 794 |
+ |
|
| 795 |
+//프로그레스바 |
|
| 796 |
+var start, change; |
|
| 797 |
+var progressInterval = null; // 전역 변수로 타이머 ID 관리 |
|
| 798 |
+function progressStart(time) {
|
|
| 799 |
+ // 기존 타이머 정지 및 초기화 |
|
| 800 |
+ if (progressInterval !== null) {
|
|
| 801 |
+ clearInterval(progressInterval); // 이전 타이머 정지 |
|
| 802 |
+ progressInterval = null; // 타이머 ID 초기화 |
|
| 803 |
+ } |
|
| 804 |
+ resetProgressBar(); // 프로그레스바 초기화 |
|
| 805 |
+ |
|
| 806 |
+ // 프로그레스바 보이기 |
|
| 807 |
+ $(".progress_bar_wrap").css("display", "flex");
|
|
| 808 |
+ |
|
| 809 |
+ // 프로그레스바 요소 가져오기 |
|
| 810 |
+ var timeText = document.querySelector(".time_text");
|
|
| 811 |
+ var bar = document.querySelector(".change_bar");
|
|
| 812 |
+ |
|
| 813 |
+ // 초기 상태 설정 |
|
| 814 |
+ var width = 1; |
|
| 815 |
+ var totalTime = time * 1000; // 총 실행 시간 (밀리초) |
|
| 816 |
+ var cmpWid = totalTime / 100; // width 증가 간격 (밀리초) |
|
| 817 |
+ |
|
| 818 |
+ // 새 타이머 시작 |
|
| 819 |
+ progressInterval = setInterval(changeWidth, cmpWid); |
|
| 820 |
+ |
|
| 821 |
+ function changeWidth() {
|
|
| 822 |
+ if (width >= 100) {
|
|
| 823 |
+ // 프로그레스바 100% 도달 |
|
| 824 |
+ clearInterval(progressInterval); // 타이머 종료 |
|
| 825 |
+ progressInterval = null; // 타이머 ID 초기화 |
|
| 826 |
+ |
|
| 827 |
+ timeText.innerHTML = "100%"; |
|
| 828 |
+ |
|
| 829 |
+ setTimeout(function () {
|
|
| 830 |
+ // 100% 표시 후 "잠시만 기다려주세요" 변경 |
|
| 831 |
+ timeText.innerHTML = "잠시만 기다려주세요..."; |
|
| 832 |
+ $(".time_text").addClass("animation");
|
|
| 833 |
+ }, 1000); |
|
| 834 |
+ } else {
|
|
| 835 |
+ // 프로그레스바 진행 |
|
| 836 |
+ width++; |
|
| 837 |
+ bar.style.width = width + "%"; |
|
| 838 |
+ timeText.innerHTML = width + "%"; |
|
| 839 |
+ } |
|
| 840 |
+ } |
|
| 841 |
+} |
|
| 842 |
+ |
|
| 843 |
+ |
|
| 844 |
+//프로그레스바 완료 |
|
| 845 |
+function progressComplete() {
|
|
| 846 |
+ // var width = parseInt($(".time_text").text().replace('%', '')) || 0; // 현재 width 가져오기
|
|
| 847 |
+ |
|
| 848 |
+ $(".progress_bar_wrap").hide();
|
|
| 746 | 849 |
} |
| 747 | 850 |
|
| 748 | 851 |
/* |
... | ... | @@ -1132,6 +1235,17 @@ |
| 1132 | 1235 |
</div> |
| 1133 | 1236 |
</div> |
| 1134 | 1237 |
|
| 1238 |
+ <div class="progress_bar_wrap"> |
|
| 1239 |
+ <div class="progress_box"> |
|
| 1240 |
+ <p class="time_text">0%</p> |
|
| 1241 |
+ <div class="bar"> |
|
| 1242 |
+ <span class="change_bar"></span> |
|
| 1243 |
+ </div> |
|
| 1244 |
+ </div> |
|
| 1245 |
+ <div class="btn_wrap"> |
|
| 1246 |
+ </div> |
|
| 1247 |
+ |
|
| 1248 |
+ </div> |
|
| 1135 | 1249 |
<!-- 기업회원 이동 팝업 --> |
| 1136 | 1250 |
<div class="tooltip-wrap cvt_member_popup_wrap"> |
| 1137 | 1251 |
<div class="popup-com cvt_member_layer" tabindex="0" data-tooltip-con="cvt_member_layer" data-focus="cvt_member_layer" data-focus-prev="cvt_member_layer-close"> |
... | ... | @@ -1766,6 +1880,7 @@ |
| 1766 | 1880 |
|
| 1767 | 1881 |
|
| 1768 | 1882 |
|
| 1883 |
+ |
|
| 1769 | 1884 |
<!-- 엑셀 불러오기 --> |
| 1770 | 1885 |
<form id="excelToolTipForm" name="excelToolTipForm" method="post"> |
| 1771 | 1886 |
<div class="tooltip-wrap"> |
--- src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
... | ... | @@ -71,8 +71,6 @@ |
| 71 | 71 |
</div> |
| 72 | 72 |
</div> |
| 73 | 73 |
<div class="btn_wrap"> |
| 74 |
- <!-- <button type="button" class="btnType btnType2" style="margin:50px 0;" onclick="progressStart(10,'완료되었습니다.');">시작</button> |
|
| 75 |
- <button type="button" class="btnType btnType2" style="margin:50px 0;" onclick="progressComplete('완료되었습니다.');return false;">멈춤</button> -->
|
|
| 76 | 74 |
</div> |
| 77 | 75 |
|
| 78 | 76 |
</div> |
--- src/main/webapp/js/web/msgdata/msgDataView.js
+++ src/main/webapp/js/web/msgdata/msgDataView.js
... | ... | @@ -1265,8 +1265,6 @@ |
| 1265 | 1265 |
|
| 1266 | 1266 |
var url = "/web/mjon/msgdata/sendMsgDataAjax_advc.do"; |
| 1267 | 1267 |
// 시작 시간 |
| 1268 |
- const startTime = new Date(); |
|
| 1269 |
- |
|
| 1270 | 1268 |
|
| 1271 | 1269 |
// 프로그래스파 시간을 위한 계산 |
| 1272 | 1270 |
var estimtedTime = calculateEstimatedTime($selectedData.length); |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?