1. 관리자 문자전송 리스트 30분 딜레이 발송승인/취소 버튼 날짜처리 변경

- 기존 날짜 시간 비교가 24시간 단위로 안되어 있어 24시간 단위로 변경
	- yyyyMMddhhmm --> yyyyMMddHHmm 으로 변경

2. 카카오 알림톡 발송 화면 #{변수명} 설정파일 첨부기능 변경
	- 기존 자바스크립트로 처리되고 있어 한셀 엑셀파일로 저장된 경우 오류 발생
	- 컨트롤러에서 POI방식으로 처리되도록 로직 변경
This commit is contained in:
rosewiper 2024-08-30 16:10:15 +09:00
parent 20dad44b26
commit 78a4cdcaf8
4 changed files with 523 additions and 5 deletions

View File

@ -466,6 +466,318 @@ public class KakaoAlimTalkSendController {
return jr;
}
/*
* 20240829 신규 추가 우영두
* 기존 Script에서 처리하던 방식 변경
* 카카오 알림톡 엑셀 불러오기 엑셀 처리
*
* */
@RequestMapping(value = "/web/mjon/alimtalk/sendAlimtalkExelVarFilePhoneNumAjax.do")
@ResponseBody
public Object sendAlimtalkExelVarFilePhoneNumAjax(final MultipartHttpServletRequest multiRequest) throws Exception {
JsonResult jr = new JsonResult();
jr.setSuccess(false);
jr.setMessage("엑셀 파일만 업로드할 수 있습니다.");
try {
//final Map<String, MultipartFile> files = multiRequest.getFileMap();
List<MultipartFile> files = (List<MultipartFile>) multiRequest.getFiles("file0");
// 파일명에 . 있을경우 오류 => Ex) 테스트6.20.xlsx
int fileNameSplitCnt = 0;
int excelVarCnt = Integer.parseInt(multiRequest.getParameter("excelVarCnt"));// 알림톡 템플릿 변수 갯수 데이터
String [] excelVarArr = multiRequest.getParameter("excelVarList").split(",");
if(!files.isEmpty()) {
fileNameSplitCnt = files.get(0).getOriginalFilename().split("[.]").length;
if (files.get(0).getSize() > 0
&& (files.get(0).getContentType().indexOf("spreadsheetml") > -1)
|| files.get(0).getContentType().indexOf("ms-excel") > -1
|| files.get(0).getOriginalFilename().split("[.]")[fileNameSplitCnt-1].indexOf("xlsx") > -1
|| files.get(0).getOriginalFilename().split("[.]")[fileNameSplitCnt-1].indexOf("xls") > -1) {
// 엑셀 파일 용량 3MB이상 10만건 이상으로 서버가 다운되는 증상 발생
long fileSize = multiRequest.getFile("file0").getSize();
String Ext = files.get(0).getOriginalFilename().split("[.]")[1];
String errMessage = "";
String cellValue = "";
String errPhoneLine = "";
int errPhoneCnt = 0;
//수신번호 유효성 체크
String phoneRegExp = "^(050[2345678]{1}|01[016789]{1})-?[0-9]{3,4}-?[0-9]{4}$";
if(Ext.equals("xls")) {
HSSFWorkbook workbook = new HSSFWorkbook(files.get(0).getInputStream());
HSSFSheet sheet = workbook.getSheetAt(0);
if(sheet.getLastRowNum() > 501) {
errMessage = "한번에 전송 가능한 최대 발송건은 500건 입니다.";
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줄은 생략)
HSSFRow row = sheet.getRow(i); //열읽기
if(null == row) {
continue;
}
HashMap<String, String> jm = new HashMap<>();
// 행의 두번째 (이름부터 받아오기)
HSSFCell cell = null;
boolean errSts = true;
String rtnValueStr = "";
for(int j = 0 ; j < excelVarCnt + 1; j++){ //행읽기(변수갯수 +1 만큼 컬럼을 읽음 수신번호 + 변수들)
cellValue = "";
cell = row.getCell(j); //수신번호 , 변수들
if(null == cell || "".equals(cell.toString().trim())) { //수신번호 셀에 값이 없으면
if(j == 0) {
if (sheet.getLastRowNum() == i) {
continue;
}
break;
}
}
if(j == 0) {
if(null != cell){
switch(cell.getCellType()){ //숫자타임을 문자로 변환
case Cell.CELL_TYPE_NUMERIC:
cell.setCellType(Cell.CELL_TYPE_STRING);
}
cellValue = StringUtil.getString(cell.getStringCellValue().trim()) ;
if(cellValue.matches(phoneRegExp) && errSts) {
jm.put("phone", cellValue);
}else {
errPhoneCnt++;
errPhoneLine += (i+1) + "";
errSts = false;
break;
}
}
}else {
if(cell != null) {
if(j <= excelVarCnt) {//등록 변수 갯수 까지만 입력
switch(cell.getCellType()){ //숫자타임을 문자로 변환
case Cell.CELL_TYPE_NUMERIC:
cell.setCellType(Cell.CELL_TYPE_STRING);
}
cellValue = StringUtil.getString(cell.getStringCellValue().trim()) ;
if(cellValue != null && !cellValue.equals("")) {
rtnValueStr += cellValue + "§";
}else {//변ㅅ
rtnValueStr += "" + "§";
}
}
}else {
rtnValueStr += "" + "§";
}
}
}
jm.put("varVal", rtnValueStr.replaceFirst(".$", ""));//변수 데이터 추가
if(null != jm.get("phone") && errSts) {
json.add(jm);
}
}
int resultErrCnt = errPhoneCnt;
jr.setData(json);
jr.setSuccess(true);
if(resultErrCnt > 0) {
if (errPhoneCnt <= 10) {
if (StringUtils.isNotEmpty(errPhoneLine.trim())) {
errPhoneLine = "[" + errPhoneLine.trim() + "]";
}
}
else {
errPhoneLine = "";
}
jr.setMessage("유효하지 않은 형식의 전화번호 "+ errPhoneCnt +"" + errPhoneLine.trim() + " 있습니다.\n해당 건을 제외하고 문자 발송됩니다.");
}else {
jr.setMessage("");
}
}else {//xlsx 엑셀 자료 처리
OPCPackage opcPackage = OPCPackage.open(files.get(0).getInputStream());
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
XSSFSheet sheet = workbook.getSheetAt(0); // 첫번째 시트 불러오기
opcPackage.close();
int totRowDataCnt = 0;
for(int r=1; r<sheet.getPhysicalNumberOfRows(); r++) {
XSSFRow tmpRow = sheet.getRow(r);
//System.out.println("=================r:"+r);
XSSFCell cell = null;
if(tmpRow.getCell(0) != null) {
cell = tmpRow.getCell(0); //이름/핸드폰/변환1/변환2/변환3/변환4/변환5
if(cell != null && !cell.toString().trim().equals("")) {
//System.out.println("value-" + r + ":" +cell.getStringCellValue());
totRowDataCnt++;
//System.out.println("tmpRowCnt:"+totRowDataCnt);
}
}
}
if(totRowDataCnt > 501) { //
errMessage = "한번에 전송 가능한 최대 발송건은 500건 입니다.";
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줄은 생략)
XSSFRow row = sheet.getRow(i); //열읽기
if(null == row) {
continue;
}
HashMap<String, String> jm = new HashMap<>();
// 행의 두번째 (이름부터 받아오기)
XSSFCell cell = null;
boolean errSts = true;
String rtnValueStr = "";
for(int j = 0 ; j < excelVarCnt + 1; j++){ //행읽기(변수갯수 +1 만큼 컬럼을 읽음 수신번호 + 변수들)
cellValue = "";
cell = row.getCell(j); //수신번호 , 변수들
if(null == cell || "".equals(cell.toString().trim())) { //셀에 값이 없으면
//System.out.println("Cell 데이터가 없습니다.");
if(j == 1) {
if (sheet.getLastRowNum() == i) {
continue;
}
break;
}
}
if(null != cell){
switch(cell.getCellType()){ //숫자타임을 문자로 변환
case Cell.CELL_TYPE_NUMERIC:
cell.setCellType(Cell.CELL_TYPE_STRING);
}
cellValue = StringUtil.getString(cell.getStringCellValue().trim()) ;
}
if(j == 0) {//수신번호 추가
if(cellValue.matches(phoneRegExp) && errSts) {
jm.put("phone", cellValue);
}else {
errPhoneCnt++;
errPhoneLine += (i+1) + "";
errSts = false;
break;
}
}else {//변수 데이터 추가
if(cell != null) {
if(j <= excelVarCnt) {//등록 변수 갯수 까지만 입력
switch(cell.getCellType()){ //숫자타임을 문자로 변환
case Cell.CELL_TYPE_NUMERIC:
cell.setCellType(Cell.CELL_TYPE_STRING);
}
cellValue = StringUtil.getString(cell.getStringCellValue().trim()) ;
if(cellValue != null && !cellValue.equals("")) {
rtnValueStr += cellValue + "§";
}else {
rtnValueStr += "" + "§";
}
}
}else {
rtnValueStr += "" + "§";
}
}
}
jm.put("varVal", rtnValueStr.replaceFirst(".$", ""));//변수 데이터 추가
if(null != jm.get("phone") && errSts) {
json.add(jm);
}
}
int resultErrCnt = errPhoneCnt;
jr.setData(json);
jr.setSuccess(true);
if(resultErrCnt > 0) {
if (errPhoneCnt <= 10) {
if (StringUtils.isNotEmpty(errPhoneLine.trim())) {
errPhoneLine = "[" + errPhoneLine.trim() + "]";
}
}
else {
errPhoneLine = "";
}
jr.setMessage("유효하지 않은 형식의 전화번호 "+ errPhoneCnt +"" + errPhoneLine.trim() + " 있습니다.\n해당 건을 제외하고 문자 발송됩니다.");
}else {
jr.setMessage("");
}
}
}
}
} catch (Exception e) {
// TODO: handle exception
System.out.println("+++++++++++++++++ sendAlimtalkExelVarFilePhoneNumAjax Controller Error !!! "+e);
jr.setSuccess(false);
jr.setMessage("엑셀 데이터에 오류가 있습니다. 엑셀 데이터를 확인해 주세요.");
return jr;
}
return jr;
}
// 카카오 템플릿 목록 조회

View File

@ -781,9 +781,9 @@ function fn_SpamMberUpdt(userId, p_mberSttus, p_smiMemo, p_confirm_msg) {
<c:if test="${result.reserveCYn eq 'N' && result.delayYn eq 'Y' && result.delayCompleteYn eq 'N'}">
<br />
<fmt:formatDate value="${now}" pattern="yyyyMMddhhmm" var="nowDate" />
<fmt:formatDate value="${now}" pattern="yyyyMMddHHmm" var="nowDate" />
<fmt:parseDate value="${result.reqFullDate}" pattern="yyyy-MM-dd HH:mm" var="checkValue" />
<fmt:formatDate value="${checkValue}" pattern="yyyyMMddhhmm" var="checkDate"/>
<fmt:formatDate value="${checkValue}" pattern="yyyyMMddHHmm" var="checkDate"/>
<c:if test="${nowDate < checkDate}">
<button type="button" class="fillBlue" onclick="fnMsgDelaySendArray('<c:out value="${result.msgGroupId}"/>','<c:out value="${result.userId}"/>'); return false;">발송승인</button>
<button type="button" class="fillRed" onclick="fnMsgDelayCancelArray('<c:out value="${result.msgGroupId}"/>','<c:out value="${result.userId}"/>'); return false;">발송취소</button>

View File

@ -1355,7 +1355,8 @@ function checkNumber(event) {
<div class="receipt_num_top">
<input type="text" placeholder="선택된 파일이 없습니다." onfocus="this.placeholder=''" onblur="this.placeholder='번호를 입력하세요'" style="width:340px;">
<button type="button" class="btnType btnType6" id="fileClick"/>파일선택</button>
<input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExport02(event); return false;" style="display:none"/>
<input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExportVarAjax(event); return false;" style="display:none"/>
<!-- <input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExport02(event); return false;" style="display:none"/> -->
</div>
<div class="receipt_num_midde">
<div class="listType list01" id="wrap02">
@ -1754,7 +1755,11 @@ function checkNumber(event) {
</div>
</div><!--// 엑셀 불러오기 -->
</form>
<form id="excelVarFileForm" name="excelVarFileForm" method="post">
<input type="hidden" id="excelVarCnt" name="excelVarCnt" value="0"/>
<input type="hidden" id="excelVarList" name="excelVarList" value=""/>
</form>
<form id="msgResendForm" name="msgResendForm" method="post">
<input name="msgResendFlag" type="hidden" value="N"/>

View File

@ -192,6 +192,208 @@ function excelAddAjax(){
}
/*
* 신규 변수명 설정 엑셀 파일 불러오기
* 기존 json 처리가 아닌 POI 방식으로 처리하기 위함
*
* */
function excelExportVarAjax(){
var data = document.getElementById('excelFile').files;
var fileValue = $("#excelFile").val().split("\\");
var fileName = fileValue[fileValue.length-1];
var fileExt = fileName.split('.').pop().toLowerCase();
if(fileExt.length > 0){
if($.inArray(fileExt, ['xls','xlsx']) == -1) {
alert('xls, xlsx 파일만 업로드 할수 있습니다.');
return false;
}
}
fn_viewDataInit01();
excelAddVarAjax();
}
function excelAddVarAjax(){
var varList = $("#excelTemplateContent").val().match(/#\{([^}]+)\}/g);
var form = document.excelVarFileForm;
form.excelVarCnt.value = varList.length;
form.excelVarList.value = varList;
var data = new FormData(form);
data.append("file0", $('#excelFile').prop('files')[0]);
var url = "/web/mjon/alimtalk/sendAlimtalkExelVarFilePhoneNumAjax.do";
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: url,
data: data,
dataType:'json',
async: true,
processData: false,
contentType: false,
cache: false,
//timeout: 600000,
success: function (returnData, status) {
if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
if(returnData.success){
var data = returnData.data;
var message = returnData.message;
if(message != '' ){
alert(returnData.message);
}
if(data != null){
//수신목록 Html 태그
// 엑셀 헤더
var excelTitleHeadText ='<div class="list_table_name">'
+'\t<p>$HEADTITLE$</p>'
+'</div>';
// 바디 row 수신자 tag
var excelBodyRowTextIndex00 ='<div class="list_table_name phoneArea">'
+'\t\t<p>$ROWTEXT$</p>'
+'\t</div>';
// 바디 row tag
var excelBodyRowTextIndex01 ='<div class="list_table_name transData">'
+'\t\t<p>$ROWTEXT$</p>'
+'\t</div>';
//맨 앞에 수신번호 배열 추가
varList.unshift('수신번호');
//변수 문자열 중복 제거
var newList = Array.from(new Set(varList));
//엑셀헤더 selector
var $excelHead = $('#excelHead');
//엑셀바디 selector
var $excelBody = $('#excelBody02');
// 엑셀 헤더 부분
$.each(newList, function(headerIndex, value) {
$excelHead.append(excelTitleHeadText.replace('$HEADTITLE$', value));
});
var totalDuplCnt = $('#rowDupCnt').text();//중복 건수 정보
var $excelBody = $('#excelBody02');
var bodyData;
var addDiv = "";
var phoneNum;
//입력데이터를 역정렬해준다.
data.reverse();
//변수명 추출해주기
var varListArr = [];
varListArr = form.excelVarList.value.split(",");
$.each(data, function(i, item){
if(checkHpNum(item.phone)){
phoneNum = removeDash(item.phone);
if(!phoneDupl(phoneNum)){
var varVal = item.varVal;
var lengthCheck =true;
/*23.04.06 이름제거 요청으로인한 화면 이름 제거*/
var excelBody = '<div class="list_table list_body excelBody">';
//수신번호 화면 태그 생성
excelBody += excelBodyRowTextIndex00.replace('$ROWTEXT$', removeDash(phoneNum));
//변수 데이터 태그 생성
var varValArr = []
varValArr = varVal.split("§");
for(var i=0; i < varValArr.length; i++){
var bodyData = varValArr[i];
// 기타변수는 50자리 까지 입력
if(bodyData.length > 100 || bodyData.length == 0){
alert("등록 변수[ "+varListArr[i]+" ] \n기타변수의 입력 값이 없거나 100자리를 초과하는 내용이 포함되어 해당 내용 제외되었습니다.");
lengthCheck = false;
break;
}
excelBody += excelBodyRowTextIndex01.replace('$ROWTEXT$', bodyData);
}
excelBody += '</div>';
if(lengthCheck){
addDiv += excelBody;
}
}
else
totalDuplCnt++;
} else{
alert("엑셀 파일 데이터의 형식이 맞지 않는 부분이 있습니다.");
excelAddr = []; //엑셀 데이터 저장 변수 초기화
$("#excelFile").val(""); //첨부파일 input 초기화
$("#excelNm").val(""); // 첨부파일 명 초기화
fileName = "";
return;
}
});
//화면에 수신번호 및 변수 데이터 추가해 주기
$excelBody.append(addDiv);
}
}else{
alert(returnData.message);
// alert("첨부파일 불러오는 중 오류가 발생하였습니다.");
excelAddr = []; //엑셀 데이터 저장 변수 초기화
$("#excelFile01").val(""); //첨부파일 input 초기화
$("#excelNm01").val(""); // 첨부파일 명 초기화
fileName = "";
return;
}
} else if(status== 'fail'){
alert("첨부파일 불러오는 중 오류가 발생하였습니다.");
console.log("status : fail ~");
}
},
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');
}
});
}
/**
* 엑셀 파일 불러오기
*/
@ -481,7 +683,6 @@ function phoneDupl(data){
var resultBoo = true;
data = removeDash(data);
/*
* 중복체크
* 기존 데이터 배열화