Merge branch 'master' into 5102_친구톡_발송속도_개선

This commit is contained in:
hehihoho3@gmail.com 2025-04-16 16:03:06 +09:00
commit 7967c5cd6a
14 changed files with 127 additions and 129 deletions

View File

@ -80,9 +80,6 @@ public class KakaoSendUtil {
log.info(" +kakaoVO.getVarListMap().size() :: [{}]", kakaoVO.getVarListMap().size());
List<KakaoSendAdvcVO> kakaoSendAdvcListVO = new ArrayList<>();
Calendar calendar = setupBaseDate(kakaoVO, isNotified);
@ -133,9 +130,10 @@ public class KakaoSendUtil {
/** @Map에 총 갯수가 수신자 갯수와 동일함 */
List<Map<String, String>> varList = kakaoVO.getVarListMap();
for (int i = 0; i < varList.size(); i++) {
// for(Map<String, String> variables : kakaoVO.getVarListMap()) {
// for(Map<String, String> variables : kakaoVO.getVarListMap()) {
// 치환 데이터
Map<String, String> variables = varList.get(i);
log.info("");
/** @공통 기본값 */
KakaoSendAdvcVO sendVO = createSendVO(kakaoVO);
@ -151,10 +149,12 @@ public class KakaoSendUtil {
}
/** @Step1-3: 템플릿 치환데이터 설정 */
String templateContentTemp = templateContent;
String templateTitleTemp = templateTitle;
if (hasContentReplacement) {
templateContent = mjonCommon.ATReplaceTemplateVariables(templateContent, variables);
templateContentTemp = mjonCommon.ATReplaceTemplateVariables(templateContent, variables);
if(hasTitleReplacement) {
templateTitle = mjonCommon.ATReplaceTemplateVariables(templateTitle, variables);
templateTitleTemp = mjonCommon.ATReplaceTemplateVariables(templateTitle, variables);
}
}
/** @버튼 치환 */ // 버튼 리스트가 있으면 치환 수행, 항상 sendVO에 설정
@ -164,8 +164,8 @@ public class KakaoSendUtil {
}
sendVO.setButtonList(buttonList);
sendVO.setTemplateTitle(templateTitle);
sendVO.setTemplateContent(templateContent);
sendVO.setTemplateTitle(templateTitleTemp);
sendVO.setTemplateContent(templateContentTemp);
// Step 1-4: 실패 대체 문자 치환데이터 설정
@ -261,6 +261,7 @@ public class KakaoSendUtil {
}
}
log.info(" sendVO :: [{}]", sendVO);
kakaoSendAdvcListVO.add(sendVO);
}

View File

@ -550,8 +550,8 @@ public class KakaoAlimTalkSendController {
HSSFWorkbook workbook = new HSSFWorkbook(files.get(0).getInputStream());
HSSFSheet sheet = workbook.getSheetAt(0);
if(sheet.getLastRowNum() > 501) {
errMessage = "한번에 전송 가능한 최대 발송건은 500건 입니다.";
if(sheet.getLastRowNum() > 300000) {
errMessage = "한번에 전송 가능한 최대 발송건은 300,000건 입니다.";
jr.setSuccess(false);
jr.setMessage(errMessage);
return jr;
@ -683,13 +683,21 @@ public class KakaoAlimTalkSendController {
}
if(totRowDataCnt > 501) { //
errMessage = "한번에 전송 가능한 최대 발송건은 500건 입니다.";
// if(totRowDataCnt > 501) { //
// errMessage = "한번에 전송 가능한 최대 발송건은 500건 입니다.";
// jr.setSuccess(false);
// jr.setMessage(errMessage);
// return jr;
// }
if(sheet.getLastRowNum() > 300000) {
errMessage = "한번에 전송 가능한 최대 발송건은 300,000건 입니다.";
jr.setSuccess(false);
jr.setMessage(errMessage);
return jr;
}
List<HashMap<String, String>> json = new ArrayList<HashMap<String, String>>();
for(int i=1; i< sheet.getLastRowNum() + 1; i++){ //먼저 밸리데이션 체크(1줄은 생략)

View File

@ -322,25 +322,24 @@ public class KakaoFriendsTalkSendController {
/**
* 문자 발송 기능
* @param searchVO
* @methodName : sendMsgData_ft_advc
* @author : 이호영
* @date : 2025. 4. 17.
* @description : 친구톡 발송기능
* @return : ResponseEntity<StatusResponse>
* @param kakaoVO
* @param request
* @param model
* @return "/web/mjon/msgdata/sendMsgDataAjax.do"
* @return
* @throws Exception
*
*/
@RequestMapping(value = "/web/mjon/kakao/friendstalk/kakaoFriendsTalkMsgSendAjax_advc.do")
public ResponseEntity<StatusResponse> sendMsgData_ft_advc(
public ResponseEntity<StatusResponse> kakaoFriendsTalkMsgSendAjax_advc(
@RequestBody KakaoVO kakaoVO,
HttpServletRequest request,
ModelMap model) throws Exception {
HttpServletRequest request
) throws Exception {
System.out.println(" :: sendMsgData_ft_advc :: ");
// 디버깅 출력
// System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().toString());
// System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().size());
return ResponseEntity.ok().body(kakaoFriendsTalkService.insertKakaoFtSandAjax_advc(kakaoVO, request)) ;
}

View File

@ -1,26 +1,23 @@
package itn.let.kakao.user.sent.web;
import java.io.FileReader;
import java.io.OutputStream;
import org.apache.commons.lang3.StringUtils;
import itn.com.cmm.util.DateUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -117,26 +114,16 @@ public class KakaoSentController {
if(kakaoSentVO.getSearchSortCnd().equals("")) kakaoSentVO.setSearchSortCnd("regdate");
String startDate = kakaoSentVO.getStartDate();
String endDate = kakaoSentVO.getEndDate();
if(startDate == null && endDate == null ) {
if(StringUtils.isEmpty(startDate)
&& StringUtils.isEmpty(endDate))
{
Calendar cal = Calendar.getInstance();
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
//종료일은 오늘날짜
cal.setTime(now);
endDate = format.format(cal.getTime());
//시작일은 전날로 셋팅
cal.add(Calendar.DATE, -89);
startDate = format.format(cal.getTime());
kakaoSentVO.setStartDate(startDate);
kakaoSentVO.setEndDate(endDate);
kakaoSentVO.setStartDate(DateUtils.getDateMonthsAgo(3));
kakaoSentVO.setEndDate(DateUtils.getCurrentDate());
}

View File

@ -3980,6 +3980,7 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M
}
String smsTxt = mjonMsgVO.getSmsTxtArea();
smsTxt = StringUtils.isEmpty(smsTxt) ? "" : smsTxt;
// 광고문자면 처리 - 광고 A
if ("A".equals(mjonMsgVO.getMsgKind())) {
smsTxt = "(광고)" + smsTxt + "\n" + "무료거부 0808800858";
@ -3987,7 +3988,7 @@ public class MjonMsgDataServiceImpl extends EgovAbstractServiceImpl implements M
mjonMsgVO.setSmsTxt(smsTxt);
// log.debug(" :: smsTxt :: [{}]", smsTxt);
log.debug(" :: smsTxt :: [{}]", smsTxt);
StatusResponse statusResponse = new StatusResponse();

View File

@ -29,6 +29,7 @@ Globals.Env = local
# mysql
Globals.DriverClassName=com.mysql.jdbc.Driver
Globals.Url=jdbc:mysql://119.193.215.98:3306/mjon
#Globals.Url=jdbc:mysql://192.168.0.60:3308/mjon
Globals.UserName= mjonUr
Globals.Password= mjon!@#$
#Globals.Url=jdbc:mysql://192.168.0.125:3306/mjon

View File

@ -3,7 +3,7 @@
========= ======= =================================================
2021.03.01 신명섭
-->
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="KakaoAT">
<typeAlias alias="mjonKakaoATVO" type="itn.let.kakao.admin.kakaoAt.service.MjonKakaoATVO"/>
<typeAlias alias="ChannelIDVO" type="itn.let.kakao.admin.kakaoAt.service.ChannelIDVO"/>
@ -2787,7 +2787,7 @@
, B.MSG_GROUP_CNT
, A.MSG_ID
, A.USERDATA
, B.SMS_TXT
, A.SMS_TXT
, B.SUBJECT
, B.REGDATE
, A.REQ_DATE

View File

@ -41,11 +41,6 @@
<script>
$(document).ready(function (){
$(document).on('click', '#id_text', function () {
actionLogin_temp();
});
$(document).on('click', '#secuLoginFlag', function () {
var secuLoginFlag = "";
@ -345,11 +340,6 @@ function whoisIpCountry() {
}
function actionLogin_temp(){
location.href='/web/user/login/login.do'
}
function actionLogin() {
// location.href="<c:url value='/web/user/login/login.do'/>";
@ -1709,6 +1699,8 @@ function actionLogin_end(){
<input type="hidden" id="ip" name="ip" value="${userIp}">
<input type="hidden" id="passFlag" name="passFlag">
<input type="hidden" id="headerLoginResult" name="headerLoginResult">
<input type="hidden" id="hp" name="hp" value="">
<input type="hidden" id="num" name="num" value="">
<div id="login" class="login">
<div class="inner">
@ -1719,9 +1711,9 @@ function actionLogin_end(){
<input type="text" placeholder="아이디를 입력해주세요"id="id_text" name="id_text" class="id_text" maxlength="20" size="18">
<label for="password_text" class="label"></label>
<!-- <input type="password" placeholder="비밀번호를 입력해주세요" id="password_text" class="password_text" maxlength="30"size="18" onkeypress="if(event.keyCode==13) {actionLogin(); return false;}" onclick="actionLogin();"> -->
<input type="password" placeholder="비밀번호를 입력해주세요" id="password_text" class="password_text" maxlength="30"size="18" onkeypress="if(event.keyCode==13) {actionLogin_temp(); return false;}">
<input type="password" placeholder="비밀번호를 입력해주세요" id="password_text" class="password_text" maxlength="30"size="18" onkeypress="if(event.keyCode==13) {actionLogin(); return false;}">
<label for="login_button" class="label"></label>
<button type="button" id="login_button" class="btnType btnType1" class="login_button" onclick="actionLogin_temp();">로그인</button>
<button type="button" id="login_button" class="btnType btnType1" class="login_button" onclick="actionLogin();">로그인</button>
</div>
<div class="login_save">
<input type="checkbox" id="save_id" name="checkId">

View File

@ -1070,11 +1070,8 @@ function fn_sendMsgData(){
phoneNum[i] = phone;
}
}
}
}
//예약문자 시간 체크
@ -1225,6 +1222,32 @@ function fn_sendMsgData(){
formData[field.name] = field.value;
});
// 2. buttonVOList 수동으로 수집
var buttonList = [];
$('input[name^="buttonVOList"]').each(function() {
let nameAttr = $(this).attr('name');
let match = nameAttr.match(/buttonVOList\[(\d+)\]\.(\w+)/);
if (match) {
let index = parseInt(match[1]);
let key = match[2];
let value = $(this).val();
if (!buttonList[index]) buttonList[index] = {};
buttonList[index][key] = value;
}
});
// 3. formData에 배열로 추가
formData["buttonVOList"] = buttonList;
// ✅ 4. 기존의 buttonVOList[0].xxx 형태 제거
Object.keys(formData).forEach(function(key) {
if (/^buttonVOList\[\d+\]\./.test(key)) {
delete formData[key];
}
});
// 빈 값 제거
removeEmptyValues(formData);
// 선택된 데이터 추가
@ -1238,12 +1261,9 @@ function fn_sendMsgData(){
$.ajax({
type: "POST"
, url: "/web/mjon/kakao/friendstalk/kakaoFriendsTalkMsgSendAjax_advc.do"
, data: data
, data: JSON.stringify(formData)
, contentType: 'application/json'
, dataType: 'json'
, async: true
, processData: false
, contentType: false
, cache: false
, success: function (returnData) {
console.log('returnData : ', returnData);
@ -1817,8 +1837,8 @@ function updateButtons(){
<!-- 친구톡 발송 단가 정보 -->
<input type="hidden" id="kakaoFtPrice" name="kakaoFtPrice" value="<c:out value='${sendPrice.kakaoFtPrice}' />"/>
<input type="hidden" id="eachPrice" name="eachPrice" value="0"/>
<input type="hidden" id="totPrice" name="totalPrice" value="0"/>
<!-- <input type="hidden" id="eachPrice" name="eachPrice" value="0"/> -->
<!-- <input type="hidden" id="totPrice" name="totalPrice" value="0"/> -->
<!-- 친구톡 발송 json 파일 필요 유무 -->
<input type="hidden" id="bizJsonYn" name="bizJsonYn" value="N"/>
@ -1904,8 +1924,8 @@ function updateButtons(){
<tr>
<th>광고포함 여부</th>
<td>
<input type="radio" class="inputAdFlag" name="ad_flag" id="ad_Y" value="Y" <c:if test="${resultTemplateVO.adFlag eq 'Y'}">checked</c:if> ><label for="ad_Y">광고성 정보 포함</label>
<%-- <input type="radio" class="inputAdFlag" name="ad_flag" id="ad_N" value="N" <c:if test="${resultTemplateVO.adFlag eq 'N'}">checked</c:if> ><label for="ad_N">포함 안함</label> --%>
<%-- <input type="radio" class="inputAdFlag" name="ad_flag" id="ad_Y" value="Y" <c:if test="${resultTemplateVO.adFlag eq 'Y'}">checked</c:if> ><label for="ad_Y">광고성 정보 포함</label> --%>
<input type="radio" class="inputAdFlag" id="ad_Y" value="Y" <c:if test="${resultTemplateVO.adFlag eq 'Y'}">checked</c:if> ><label for="ad_Y">광고성 정보 포함</label>
</td>
</tr>
<tr>

View File

@ -104,15 +104,6 @@ function fnReservCancel(msgGroupId){
}
function fn_sentDetailView(msgGroupId) {
// msgGroupId 값을 form에 설정
$("#searchForm #msgGroupId").val(msgGroupId);
// form을 해당 URL로 제출
$("#searchForm").attr("action", "/web/kakao/sent/selectKakaoSentDetailView.do");
$("#searchForm").submit();
}
</script>
<div class="list_info">
<p>총 발송건수 <span class="c_e40000"><c:out value="${totalRecordCount}"/></span>건</p>

View File

@ -796,7 +796,7 @@ function previewPhone(){
<!-- 목록-->
<div class="btn_list_type1">
<button class="btnType btnType17">목록</button>
<button class="btnType btnType17" id="goPageBtn">목록</button>
</div>
<!--// 목록-->
@ -889,14 +889,14 @@ function previewPhone(){
<!--// 주소록에 등록 팝업 -->
<!-- 이전 리스트 상태(검색조건, 페이징) 그대로 가기 위한 form -->
<form id="goList" name="goList" method="post" action="/web/mjon/msgsent/selectMsgSentView.do">
<form id="goList" name="goList" method="post" action="/web/kakao/sent/selectKakaoSentView.do">
<input type="hidden" name="pageIndex" value="<c:out value="${searchVO.pageIndex}" />" />
<input type="hidden" name="searchSortCnd" value="<c:out value='${searchVO.searchSortCnd }' />" />
<input type="hidden" name="searchSortOrd" value="<c:out value='${searchVO.searchSortOrd }' />" />
<input type="hidden" name="searchCondition01" value="<c:out value='${searchVO.searchCondition01 }' />" />
<input type="hidden" name="searchCondition02" value="<c:out value='${searchVO.searchCondition02 }' />" />
<input type="hidden" name="searchStartDate" value="<c:out value='${searchVO.searchStartDate }' />" />
<input type="hidden" name="searchEndDate" value="<c:out value='${searchVO.searchEndDate }' />" />
<input type="hidden" name="startDate" value="<c:out value='${searchVO.startDate }' />" />
<input type="hidden" name="endDate" value="<c:out value='${searchVO.endDate }' />" />
<input type="hidden" name="searchCondition" value="<c:out value='${searchVO.searchCondition }' />" />
<input type="hidden" name="searchKeyword" value="<c:out value='${searchVO.searchKeyword }' />" />
<input type="hidden" name="pageUnit" value="<c:out value='${searchVO.pageUnit }' />" />

View File

@ -21,7 +21,7 @@ $(document).ready(function(){
//초기 전체 리스트 페이지 보여주기
var form = document.searchForm;
form.listType.value = "groupList";
linkPage(1);
linkPage(<c:out value="${searchVO.pageIndex}"/>);
var date = new Date() ;
//이전달 첫날/마지막날 조회
@ -246,33 +246,6 @@ $(document).on('click', '.msgGgoupList', function(){
});
function fnReSendMsg(){
var msgSeq = [];
if($("input:checkbox[name='msgSentDel']").is(":checked")==false){
alert("선택된 항목이 없습니다.");
return;
}
$("input:checkbox[name='msgSentDel']:checked").each(function(index){
var disabledChk = $(this).prop('disabled');
if(!disabledChk){ //checkbox disabled 인 것은 제외하고 아이디 저장
msgSeq[index] = $(this).val();
}
});
var form = document.reSendForm;
form.msgSeqList.value = msgSeq;
form.msgResendFlag.value = "Y";
form.action="/web/mjon/msgdata/selectMsgDataView.do";
form.submit();
}
/* 사용내역서 클릭 시 내역서 새창 팝업 오픈 */
function fnShowPrintPopup(tabType, type) {
//만들려는 팝업의 크기
@ -382,6 +355,18 @@ function fnDelete(){
}
function fn_sentDetailView(msgGroupId) {
// msgGroupId 값을 form에 설정
$("#searchForm #msgGroupId").val(msgGroupId);
$('#ntceBgnde').val($('#startDate').val());
$('#ntceEndde').val($('#endDate').val());
// form을 해당 URL로 제출
$("#searchForm").attr("action", "/web/kakao/sent/selectKakaoSentDetailView.do");
$("#searchForm").submit();
}
</script>
@ -426,7 +411,9 @@ function fnDelete(){
<!--// tab button -->
</div>
<form id="searchForm" name="searchForm" method="post">
<input type="hidden" id="pageIndex" name="pageIndex" value="1"/>
<input type="hidden" id="pageIndex" name="pageIndex" value="<c:out value="${searchVO.pageIndex}" />"/>
<%-- <input type="hidden" id="pageIndex" name="pageIndex" value="<c:out value="${searchVO.pageIndex}" />" /> --%>
<input type="hidden" id="pageUnit" name="pageUnit" value="<c:out value="${searchVO.pageUnit}" />" />
<input type="hidden" id="msgGroupIdList" name="msgGroupIdList" value=""/>
<input type="hidden" name="searchSortCnd" value="<c:out value="${searchVO.searchSortCnd}" />" />
<input type="hidden" name="searchSortOrd" value="<c:out value="${searchVO.searchSortOrd}" />" />
@ -649,10 +636,6 @@ function fnDelete(){
<input type="hidden" id="fileCnt" name="fileCnt" value=""/>
<input type="hidden" id="resultType" name="resultType" value="S"/>
</form>
<form id="reSendForm" name="reSendForm" method="post">
<input type="hidden" id="msgSeqList" name="msgSeqList" value=""/>
<input type="hidden" id="msgResendFlag" name="msgResendFlag" value="N"/>
</form>
<form name="popForm" id="popForm" method="post">
<input type="hidden" name="pageType" id="pageType" value=""/>
</form>

View File

@ -296,6 +296,7 @@ function excelAddVarAjax(){
var varListArr = [];
varListArr = form.excelVarList.value.split(",");
var forBreakB = true
$.each(data, function(i, item){
if(checkHpNum(item.phone)){
@ -319,8 +320,11 @@ function excelAddVarAjax(){
var bodyData = varValArr[i];
// 기타변수는 50자리 까지 입력
if(bodyData.length > 100 || bodyData.length == 0){
if(bodyData.length > 100 || bodyData.length == 0 ){
if(forBreakB){
alert("등록 변수[ "+varListArr[i]+" ] \n기타변수의 입력 값이 없거나 100자리를 초과하는 내용이 포함되어 해당 내용 제외되었습니다.");
forBreakB = false;
}
lengthCheck = false;
break;
}

View File

@ -132,6 +132,17 @@ $(document).ready(function (){
// ⬇️ 기존 tableL 데이터 개수 확인
var existingData = tableL.getData();
var totalCount = existingData.length + numbers.length;
// ⬇️ 30만건 초과 시 경고 및 중단
if (totalCount > 300000) {
alert("안정적인 서비스 운영을 위해서 최대 300000건 이내로 분할 발송해 주시기 바랍니다.");
return;
}
const formattedData = numbers.map(num => ({phone: num}));
// 기존 tableL의 데이터를 가져옵니다.