발송결과 상세 진행중

This commit is contained in:
hehihoho3@gmail.com 2025-02-04 17:29:22 +09:00
parent 4d320f7401
commit 1230dea6ac
6 changed files with 487 additions and 288 deletions

View File

@ -16,8 +16,10 @@ public class MjonMsgDetailSentVO extends UserDefaultVO{
private String msgGroupId;
private String reqDate;
private String regDate;
private String msgGroupCnt;
private String reserveYn;
private String reserveCYn;
private String callFrom;
private String userId;
private String smsTxt;
@ -25,6 +27,7 @@ public class MjonMsgDetailSentVO extends UserDefaultVO{
private String msgType;
private String fileCnt;
private String msgKind;
private String eachPrice;
private String sentDate;
private String filePath1;
private String filePath2;
@ -33,6 +36,24 @@ public class MjonMsgDetailSentVO extends UserDefaultVO{
private String callTo;
private String statusTxt;
private String addrNm;
private String resultSValue;
private String resultFValue;
private String resultWValue;
private String successPct;
private String failedPct;
private String waitingPct;
private String statusCd; // 진행상태 코드
private String divideYN;
private int diffMin;
private String totPrice;
// FileInfo 리스트 필드 추가

View File

@ -4,11 +4,17 @@ import java.util.Date;
import java.util.List;
import itn.let.uss.umt.service.UserDefaultVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MjonMsgSentVO extends UserDefaultVO{
private static final long serialVersionUID = 1L;

View File

@ -127,7 +127,6 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
Map<String, Object> resultMap = new HashMap<String, Object>();
System.out.println("mjonMsgSentVO.getSearchConditionSite() :: "+ mjonMsgSentVO.getSearchConditionSite());
// 목록
List<MjonMsgSentVO> resultList = mjonMsgSentDAO.selectAllMsgSentList_advc(mjonMsgSentVO);
@ -136,36 +135,11 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
resultList = makeDetailFunction(resultList);
// 공통코드 ITN057에 대한 코드화 진행
/*
* CODE_ID CODE CODE_NM CODE_DC
* ITN057 01 진행중 진행중
* ITN057 02 완료 완료출해야함
* ITN057 03 예약대기 예약대기(발송전) 버튼으로 노출해야함
* ITN057 04 - 예약취소 ( - 으로 노출 )
* 진행상태 코드화
* */
resultList.stream().forEach(t->{
String code;
log.info(" + t.getDiffMin() :: [{}]", t.getDiffMin());
log.info(" + t.getDiffMin() :: [{}]", t.getDiffMin() > -5);
if ("Y".equals(t.getReserveCYn())) {
code = "04"; // 예약취소 코드
} else if (
"Y".equals(t.getReserveYn())
&& "N".equals(t.getReserveCYn())
&& t.getMsgGroupCnt().equals(t.getResultWValue())
&& t.getDiffMin() < -5 // 예약 시간이 5분 이상인 것들만
) {
code = "03"; // 예약대기 코드 ( 예약취소 버튼 노출 )
} else if (t.getMsgGroupCnt().equals(t.getResultSValue()) || t.getMsgGroupCnt().equals(t.getResultFValue())) {
code = "02"; // 완료 코드
} else {
code = "01"; // 진행중 코드
}
String code = getStatusCode(t);
t.setStatusCd(code);
});
@ -187,25 +161,61 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
Map<String, Object> resultMap = new HashMap<String, Object>();
// 목록
MjonMsgDetailSentVO result = mjonMsgSentDAO.selectAllMsgSentDetailView(mjonMsgDetailSentVO);
MjonMsgDetailSentVO resultVO = mjonMsgSentDAO.selectAllMsgSentDetailView(mjonMsgDetailSentVO);
// 성공 대기 실패 발송금액 분할여부
MjonMsgSentVO updatedVO = getDetailFunction(resultVO.getMsgGroupId(), resultVO.getEachPrice());
resultVO.setResultSValue(updatedVO.getResultSValue()); // 성공건수
resultVO.setResultWValue(updatedVO.getResultWValue()); // 대기건수
resultVO.setResultFValue(updatedVO.getResultFValue()); // 실패건수
resultVO.setTotPrice(updatedVO.getTotPrice());
resultVO.setDivideYN(updatedVO.getDivideYN());
// 퍼센트 계산 실행
Map<String, String> returnMap = calculatePercentages(resultVO);
resultVO.setSuccessPct(returnMap.get("successPct"));
resultVO.setWaitingPct(returnMap.get("waitingPct"));
resultVO.setFailedPct(returnMap.get("failedPct"));
// 진행상태 코드화
String statusCode = getStatusCode(MjonMsgSentVO.builder()
.reserveCYn(resultVO.getReserveCYn())
.reserveYn(resultVO.getReserveYn())
.msgGroupCnt(resultVO.getMsgGroupCnt())
.resultSValue(resultVO.getResultSValue())
.resultWValue(resultVO.getResultWValue())
.resultFValue(resultVO.getResultFValue())
.diffMin(resultVO.getDiffMin())
.build());
log.info(" ++ statusCode :: [{}]" ,statusCode);
resultVO.setStatusCd(statusCode);
// 결과 출력
System.out.println("성공률: " + returnMap.get("successPct"));
System.out.println("대기율: " + returnMap.get("waitingPct"));
System.out.println("실패율: " + returnMap.get("failedPct"));
// 광고일떄 (광고) 줄바꿈+무료거부 0808800858 삭제
if("A".equals(result.getMsgKind())) {
result.setSmsTxt(result.getSmsTxt().replace("(광고)", "")
if("A".equals(resultVO.getMsgKind())) {
resultVO.setSmsTxt(resultVO.getSmsTxt().replace("(광고)", "")
.replaceAll("\\s*무료거부 0808800858", ""));
}
if(StringUtils.isNotEmpty(result.getFileCnt()) && Integer.parseInt(result.getFileCnt()) > 0)
if(StringUtils.isNotEmpty(resultVO.getFileCnt()) && Integer.parseInt(resultVO.getFileCnt()) > 0)
{
List<FileInfoVO> fileInfos = getFileInfo(result);
result.setFileInfos(fileInfos);
List<FileInfoVO> fileInfos = getFileInfo(resultVO);
resultVO.setFileInfos(fileInfos);
}
resultMap.put("result", result);
resultMap.put("result", resultVO);
return resultMap;
}
@ -428,11 +438,11 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
//예약 관리 리스트 불러오기
List<MjonMsgSentVO> resultAllSentList = mjonMsgSentDAO.selectAllMsgSentList_advc(mjonMsgSentVO);
long startTime = System.nanoTime(); // 시작 시간 측정
// long startTime = System.nanoTime(); // 시작 시간 측정
resultAllSentList = makeDetailFunction(resultAllSentList);
long endTime = System.nanoTime(); // 끝난 시간 측정
double executionTimeInSeconds = (endTime - startTime) / 1_000_000_000.0;
System.out.println("Execution time: " + executionTimeInSeconds + " seconds");
// long endTime = System.nanoTime(); // 끝난 시간 측정
// double executionTimeInSeconds = (endTime - startTime) / 1_000_000_000.0;
// System.out.println("Execution time: " + executionTimeInSeconds + " seconds");
SXSSFWorkbook workbook = null; // SXSSFWorkbook 변수 선언
try{
@ -658,41 +668,122 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
}
/**
* @methodName : makeDetailFunction
* @author : 이호영
* @date : 2025.02.04
* @description : 발송결과 성공건수, 실패건수, 대기건수, 분할발송여부, 발송금액 구하기
* @param resultList
* @return
*/
private List<MjonMsgSentVO> makeDetailFunction(List<MjonMsgSentVO> resultList) {
resultList.stream().forEach(t->{
MjonMsgSWFDTO mjonMsgSWFDTO = mjonMsgSentDAO.findBySWF(t.getMsgGroupId());
t.setResultSValue(String.valueOf(mjonMsgSWFDTO.getResultSValue())); // 성공건수
t.setResultFValue(String.valueOf(mjonMsgSWFDTO.getResultFValue())); // 실패건수
t.setResultWValue(String.valueOf(mjonMsgSWFDTO.getResultWValue())); // 대기건수
t.setDivideYN(mjonMsgSWFDTO.getDivideYN());
// TotPrice : 성공건수에 대한 금액 곱하기
BigDecimal eachPrice = new BigDecimal(t.getEachPrice());
BigDecimal resultSValue = new BigDecimal(mjonMsgSWFDTO.getResultSValue());
BigDecimal totalPrice = eachPrice.multiply(resultSValue);
// 소수점 자리로 설정 (반올림)// totalPrice 값을 소수점 자리까지 반올림하여 roundedTotalPrice에 저장
// RoundingMode.HALF_UP: 반올림 방식으로, 소수점 기준 5 이상이면 올림, 그렇지 않으면 내림
BigDecimal roundedTotalPrice = totalPrice.setScale(1, RoundingMode.HALF_UP);
MjonMsgSentVO updatedVO = getDetailFunction(t.getMsgGroupId(), t.getEachPrice());
// roundedTotalPrice가 0인지 확인
// BigDecimal.compareTo(BigDecimal.ZERO) 값을 비교하는 메서드
// 결과:
// - 반환 값이 0이면 값이 같음
// - 반환 값이 음수이면 roundedTotalPrice가 0보다 작음
// - 반환 값이 양수이면 roundedTotalPrice가 0보다
if (roundedTotalPrice.compareTo(BigDecimal.ZERO) == 0) {
// roundedTotalPrice 값이 0이면, "-" 문자열을 totPrice에 설정
t.setTotPrice("-");
} else {
// roundedTotalPrice 값이 0이 아닌 경우
// 반올림된 BigDecimal 값을 toPlainString() 사용하여 문자열로 변환 totPrice에 설정
// toPlainString(): 지수 표기법 없이 일반적인 문자열 형태로 반환
t.setTotPrice(roundedTotalPrice.toPlainString());
}
t.setResultSValue(updatedVO.getResultSValue());
t.setResultFValue(updatedVO.getResultFValue());
t.setResultWValue(updatedVO.getResultWValue());
t.setDivideYN(updatedVO.getDivideYN());
t.setTotPrice(updatedVO.getTotPrice());
});
return resultList;
}
private MjonMsgSentVO getDetailFunction(String p_msgGroupId, String p_eachPrice) {
MjonMsgSentVO returnVO = new MjonMsgSentVO();
MjonMsgSWFDTO mjonMsgSWFDTO = mjonMsgSentDAO.findBySWF(p_msgGroupId);
returnVO.setResultSValue(String.valueOf(mjonMsgSWFDTO.getResultSValue())); // 성공건수
returnVO.setResultFValue(String.valueOf(mjonMsgSWFDTO.getResultFValue())); // 실패건수
returnVO.setResultWValue(String.valueOf(mjonMsgSWFDTO.getResultWValue())); // 대기건수
returnVO.setDivideYN(mjonMsgSWFDTO.getDivideYN());
// TotPrice : 성공건수에 대한 금액 곱하기
BigDecimal eachPrice = new BigDecimal(p_eachPrice);
BigDecimal resultSValue = new BigDecimal(mjonMsgSWFDTO.getResultSValue());
BigDecimal totalPrice = eachPrice.multiply(resultSValue);
// 소수점 자리로 설정 (반올림)// totalPrice 값을 소수점 자리까지 반올림하여 roundedTotalPrice에 저장
// RoundingMode.HALF_UP: 반올림 방식으로, 소수점 기준 5 이상이면 올림, 그렇지 않으면 내림
BigDecimal roundedTotalPrice = totalPrice.setScale(1, RoundingMode.HALF_UP);
// roundedTotalPrice가 0인지 확인
// BigDecimal.compareTo(BigDecimal.ZERO) 값을 비교하는 메서드
// 결과:
// - 반환 값이 0이면 값이 같음
// - 반환 값이 음수이면 roundedTotalPrice가 0보다 작음
// - 반환 값이 양수이면 roundedTotalPrice가 0보다
if (roundedTotalPrice.compareTo(BigDecimal.ZERO) == 0) {
// roundedTotalPrice 값이 0이면, "-" 문자열을 totPrice에 설정
returnVO.setTotPrice("-");
} else {
// roundedTotalPrice 값이 0이 아닌 경우
// 반올림된 BigDecimal 값을 toPlainString() 사용하여 문자열로 변환 totPrice에 설정
// toPlainString(): 지수 표기법 없이 일반적인 문자열 형태로 반환
returnVO.setTotPrice(roundedTotalPrice.toPlainString());
}
log.info(" + returnVO.getTotPrice() :: [{}]", returnVO.getTotPrice());
return returnVO;
}
private Map<String, String> calculatePercentages(MjonMsgDetailSentVO result) {
int total = Integer.parseInt(result.getMsgGroupCnt()); // 전체 건수
int success = Integer.parseInt(result.getResultSValue()); // 성공 건수
int waiting = Integer.parseInt(result.getResultWValue()); // 대기 건수
int failed = Integer.parseInt(result.getResultFValue()); // 실패 건수
// 퍼센트 계산 (0으로 나누는 경우 대비)
String successPct = total > 0 ? String.format("%.1f%%", (success / (double) total) * 100) : "0.0%";
String waitingPct = total > 0 ? String.format("%.1f%%", (waiting / (double) total) * 100) : "0.0%";
String failedPct = total > 0 ? String.format("%.1f%%", (failed / (double) total) * 100) : "0.0%";
// 결과 맵에 저장
Map<String, String> percentages = new HashMap<>();
percentages.put("successPct", successPct);
percentages.put("waitingPct", waitingPct);
percentages.put("failedPct", failedPct);
return percentages;
}
// 공통코드 ITN057에 대한 코드화 진행
/*
* CODE_ID CODE CODE_NM CODE_DC
* ITN057 01 진행중 진행중
* ITN057 02 완료 완료출해야함
* ITN057 03 예약대기 예약대기(발송전) 버튼으로 노출해야함
* ITN057 04 - 예약취소 ( - 으로 노출 )
* */
private String getStatusCode(MjonMsgSentVO result) {
String returnCode;
if ("Y".equals(result.getReserveCYn())) {
returnCode = "04"; // 예약취소 코드
} else if (
"Y".equals(result.getReserveYn())
&& "N".equals(result.getReserveCYn())
&& result.getMsgGroupCnt().equals(result.getResultWValue())
&& result.getDiffMin() < -5 // 예약 시간이 5분 이상인 것들만
) {
returnCode = "03"; // 예약대기 코드 ( 예약취소 버튼 노출 )
} else if (result.getMsgGroupCnt().equals(result.getResultSValue())
|| result.getMsgGroupCnt().equals(result.getResultFValue())) {
returnCode = "02"; // 완료 코드
} else {
returnCode = "01"; // 진행중 코드
}
return returnCode;
}
}

View File

@ -164,13 +164,21 @@ private static final Logger logger = LoggerFactory.getLogger(MjonMsgSentControll
/**
* 발송관리 화면
* @param searchVO
* @param model
* @param model/web/user/login/login.do
* @return "/web/mjon/msgtxt/selectMsgTxtView.do"
* @throws Exception
*/
@RequestMapping(value= {"/web/mjon/msgsent/msgSentDetailView.do"})
public String selectMsgSentDetailView(@ModelAttribute("searchVO") MjonMsgDetailSentVO mjonMsgDetailSentVO,
RedirectAttributes redirectAttributes, ModelMap model) throws Exception{
public String selectMsgSentDetailView(@ModelAttribute("searchVO") MjonMsgDetailSentVO mjonMsgDetailSentVO
, ModelMap model) throws Exception{
//로그인 권한정보 불러오기
LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
if(loginVO == null) {
return "redirect:/web/user/login/login.do";
}
Map<String, Object> resultMap = mjonMsgSentService.selectAllMsgSentDetailView(mjonMsgDetailSentVO);
model.addAttribute("result", resultMap.get("result"));

View File

@ -354,18 +354,22 @@
MGD.MSG_GROUP_ID as msgGroupId
, MGD.MSG_GROUP_CNT as msgGroupCnt
, MGD.RESERVE_YN as reserveYn
, MGD.RESERVE_C_YN as reserveCYn
, MGD.CALL_FROM as callFrom
, MGD.USER_ID as userId
, MGD.SMS_TXT as smsTxt
, MGD.SUBJECT as subject
, MGD.REQ_DATE as reqdate
, DATE_FORMAT(MGD.REQ_DATE, '%Y-%m-%d %H:%i') as reqDate
, DATE_FORMAT(MGD.REGDATE, '%Y-%m-%d %H:%i') as regDate
, MGD.MSG_TYPE as msgType
, MGD.MSG_KIND as msgKind
, MD.SENT_DATE as sentDate
, MGD.EACH_PRICE as eachPrice
, DATE_FORMAT(MD.SENT_DATE, '%Y-%m-%d %H:%i') as sentDate
, MD.FILE_CNT as fileCnt
, MD.FILE_PATH1 as filePath1
, MD.FILE_PATH2 as filePath2
, MD.FILE_PATH3 as filePath3
, TIMESTAMPDIFF(minute, DATE_FORMAT(MGD.REQ_DATE, '%Y-%m-%d %T'), DATE_FORMAT(NOW(), '%Y-%m-%d %T')) as diffMin
from
MJ_MSG_GROUP_DATA MGD
inner join MJ_MSG_DATA MD on

View File

@ -3,9 +3,25 @@
<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="ec" uri="/WEB-INF/tld/ecnet_tld.tld"%>
<%@ page import="itn.com.cmm.LoginVO" %>
<style>
/* Tabulator Placeholder 기본 스타일 유지 */
.tabulator-placeholder {
font-size: 22px !important; /* 기존 폰트 크기 유지 */
color: #e2d6d6 !important; /* 기존 색상 유지 */
font-weight: normal !important; /* 기본 폰트 두께 유지 */
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
</style>
<script type="text/javascript">
var $tbDtailList = null; //에러 팝업 영역
@ -16,36 +32,31 @@ $(document).ready(function(){
$tbDtailList = new Tabulator("#detailPopup", {
height: "255px",
width: "20%",
layout: "fitDataStretch", // 데이터가 너비에 맞게 늘어나도록 설정
// layout: "fitDataStretch", // 데이터가 너비에 맞게 늘어나도록 설정
layout: "fitColumns", // fitDataStretch 대신 fitColumns 사용
autoColumns: false,
headerHozAlign: "center",
validationMode: "highlight",
clipboard: false,
clipboardCopySelector: "table",
clipboardPasteAction: "insert", // insert, update, replace
columns: [
{
title: "이름",
field: "addrNm",
hozAlign: "center",
headerHozAlign: "center",
width: 140
},
{
title: "휴대폰",
field: "phone",
hozAlign: "center",
headerHozAlign: "center",
width: 200
},
{
title: "상세결과",
field: "result",
hozAlign: "center",
headerHozAlign: "center",
width: 180
}
]
placeholder:"데이터를 불러오고 있습니다...",
columns: [
{
title: "휴대폰",
field: "phone",
hozAlign: "center",
headerHozAlign: "center",
widthGrow: 1
},
{
title: "상세결과",
field: "result",
hozAlign: "center",
headerHozAlign: "center",
widthGrow: 1
}
]
});
fn_getDetailList();
@ -56,11 +67,42 @@ $(document).ready(function(){
$("#goList").submit();
});
// 검색 버튼 클릭 시 실행
$("#searchBtn").on("click", function () {
searchTable();
});
// Enter 키 입력 시 실행
$("#searchInput").on("keyup", function (event) {
if (event.key === "Enter") {
searchTable();
}
});
// 탭 버튼 클릭 이벤트
$(".tabType3 .tab button").on("click", function () {
console.log('.tabType3 .tab button');
// 모든 탭의 active 클래스 제거
$(".tabType3 .tab").removeClass("active");
// 클릭한 버튼의 부모 요소(li)에 active 클래스 추가
$(this).parent().addClass("active");
// 기존 버튼들의 title 속성 초기화
$(".tabType3 .tab button").removeAttr("title");
// 선택된 버튼의 title 속성을 "선택됨"으로 변경
$(this).attr("title", "선택됨");
// 클릭한 버튼의 텍스트 가져오기
let resultText = $(this).text().trim();
fn_tabTable('result', resultText);
});
});
@ -91,11 +133,12 @@ function fn_getDetailList(){
}
/**
* @Description: 데이터 설정
*/
function fn_setData(data){
console.log('data : ', data);
// $tbDtailList.clearData();
// console.log('data : ', data);
// $tbDtailList.clearData();
const resultData = []; // 오류 데이터를 저장할 배열
@ -115,7 +158,70 @@ function fn_setData(data){
};
/**
* @Description: 검색 기능
*/
function searchTable() {
let column = $("#searchColumn").val(); // 선택한 컬럼
let keyword = $("#searchInput").val(); // 검색어
// 검색어가 3자 이상일 때만 필터 적용
// if (keyword.length >= 3) {
$tbDtailList.setFilter(column, "like", keyword);
fn_setPlaceholder("검색 결과가 없습니다.");
// } else {
// $tbDtailList.clearFilter(); // 검색어가 짧으면 필터 제거
// }
}
/**
* @Description: 탭 검색 기능
*/
function fn_tabTable(column, keyword) {
if(keyword == '전체'){
$tbDtailList.clearFilter();
}else{
$tbDtailList.setFilter(column, "like", keyword);
}
fn_setPlaceholder("검색 결과가 없습니다.");
}
/**
* @Description: 타블레이서 설명 수정
*/
function fn_setPlaceholder(msg){
// 검색 후 데이터가 있는지 확인 후 placeholder 변경
setTimeout(() => {
let filteredRows = $tbDtailList.getRows('active').length; // 필터링된 행 개수 가져오기
if (filteredRows === 0) {
// 기존 데이터 유지하면서 빈 데이터 추가하여 placeholder 변경
$(".tabulator-placeholder").text(msg); // placeholder 메시지 변경
}
}, 300); // 필터 적용 후 반영되도록 약간의 딜레이 추가
}
/**
* @Description: 필터링된 데이터만 다운로드
*/
function fn_downloadFilteredExcel() {
let filteredData = $tbDtailList.getData("active"); // 필터링된 데이터 가져오기
if (filteredData.length === 0) {
alert("다운로드할 데이터가 없습니다.");
return;
}
// console.log("엑셀 다운로드 - 필터링된 데이터:", filteredData);
$tbDtailList.download("xlsx", "filtered_data.xlsx", {
sheetName: "Filtered Data",
data: filteredData // 필터링된 데이터만 다운로드
});
}
</script>
<div class="inner">
@ -144,95 +250,136 @@ function fn_setData(data){
<div class="send_general">
<!-- 발송결과 상세 정보 -->
<div class="resultcont_left">
<!--발송정보-->
<div class="res_info">
<div class="res_info_in">
<div class="res_info_top clearfix">
<p>발송정보</p>
<p><button type="button" class="btnType btnType3">재전송</button></p>
<!--발송정보-->
<div class="res_info">
<div class="res_info_in">
<div class="res_info_top clearfix">
<p>발송정보</p>
<p><button type="button" class="btnType btnType3">재전송</button></p>
</div>
<div class="res_info_btm">
<dl>
<dt>발송일시</dt>
<dd>
${result.reqDate}
</dd>
</dl>
<c:if test="${result.reserveYn eq 'Y' }">
<dl><!-- 예약 시 -->
<dt>등록일시</dt>
<dd>${result.regDate }</dd>
</dl>
</c:if>
<dl>
<dt>제목</dt>
<dd>${result.subject }</dd>
</dl>
<dl>
<dt>형태</dt>
<dd>
${result.msgType == '4'
? '단문'
: (result.fileCnt == '0'
? '장문'
: '그림')}
</dd>
</dl>
<dl>
<dt>발송건수</dt>
<dd><span class="c_222"><fmt:formatNumber value="${result.msgGroupCnt}" type="number" groupingUsed="true" /></span>건</dd>
</dl>
<dl>
<dt>발신번호</dt>
<dd>${result.callFrom }</dd>
</dl>
<dl>
<dt>진행상황
<!-- 예약인 경우 -->
<c:if test="${result.reserveYn eq 'Y'}">
<div class="icon_wrap">
<div class="re">예약</div>
<!-- 예약일때만 분할이 있음 -->
<c:if test="${result.divideYN eq 'Y'}">
<div class="di_info">
<button class="di">분할</button>
<div class="di_hover_layer">
<strong>100,000건</strong>씩 <strong>35분</strong> 간격
</div>
</div>
</c:if>
</div>
</c:if>
<!--// 예약인 경우 -->
</dt>
<!--<dd>진행중</dd>-->
<!--<dd>완료</dd>-->
<dd>
<c:choose>
<c:when test="${result.statusCd ne '03' }">
<ec:code codeId="ITN057" code="${result.statusCd }" />
</c:when>
<c:otherwise>
<p><button class="btnType btnType20" onClick="javascript:fnReservCancel('${result.msgGroupId}'); return false;">예약취소</button></p>
</c:otherwise>
</c:choose>
<!-- -->
<!-- <button class="btnType btnType20">예약취소</button> -->
</dd>
<!--<dd>예약취소 2024-07-16 15:07</dd>--><!-- 예역취소 후 버튼 대신 취소 일시 노출 -->
</dl>
</div>
<div class="res_info_btm">
<dl>
<dt class="btm_charge">발송요금</dt>
<dd><span class="stcharge">78,100</span>원</dd>
<!--<dd><span class="stcharge">-</span>원</dd>--><!-- 예역취소 후 금액은 하이픈 처리-->
</dl>
</div>
</div>
</div>
<div class="res_info_btm">
<dl>
<dt>발송일시</dt>
<dd>2024-07-18 15:25</dd>
</dl>
<dl>
<dt>형태</dt>
<dd>그림</dd>
</dl>
<dl>
<dt>발송건수</dt>
<dd><span class="c_222">100</span>건</dd>
</dl>
<dl>
<dt>발신번호</dt>
<dd>010-1234-5678</dd>
</dl>
<dl>
<dt>예약관리</dt>
<!--<dd>-</dd>--><!-- 예약건이 아닌 경우는 하이픈 처리-->
<dd><button class="btnType btnType25">예약취소</button></dd>
<!--<dd>예약취소 2024-07-16 15:07</dd>--><!-- 예역취소 후 버튼 대신 취소 일시 노출 -->
</dl>
<!--// 발송정보-->
<!--상세결과-->
<div class="res_info">
<div class="res_info_in">
<div class="res_info_top clearfix" style="padding:0 0 10px 0;">
<p>상세결과</p>
<p></p>
</div>
<div class="res_num">
<div class="res_info_btm1">
<dl>
<dt>전체건수</dt>
<dd><a href="#" data-tooltip="rev_popup04"><span class="c_222_g"><fmt:formatNumber value="${result.msgGroupCnt}" type="number" groupingUsed="true" /></span>건</a></dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>성공건수</dt>
<dd><span class="c_002c9a_g"><fmt:formatNumber value="${result.resultSValue}" type="number" groupingUsed="true" /></span>건(${result.successPct})</dd>
</dl>
</div>
</div>
<div class="res_num">
<div class="res_info_btm1">
<dl>
<dt>대기건수</dt>
<dd><span class="c_666_g"><fmt:formatNumber value="${result.resultWValue}" type="number" groupingUsed="true" /></span>건(${result.waitingPct})</dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>실패건수</dt>
<dd><span class="c_e40000_g"><fmt:formatNumber value="${result.resultFValue}" type="number" groupingUsed="true" /></span>건(${result.failedPct})</dd>
</dl>
</div>
</div>
<p class="table_bottom_txt">* 전체건수를 클릭하면 받는 사람 상세정보를 확인하실 수 있습니다.</p>
</div>
</div>
<div class="res_info_btm">
<dl>
<dt class="btm_charge">발송요금</dt>
<dd><span class="stcharge">100</span>원</dd>
<!--<dd><span class="stcharge">-</span>원</dd>--><!-- 예역취소 후 금액은 하이픈 처리-->
</dl>
</div>
</div>
</div>
<!--// 발송정보-->
<!--상세결과-->
<div class="res_info">
<div class="res_info_in">
<div class="res_info_top clearfix" style="padding:0 0 10px 0;">
<p>상세결과</p>
<p><button type="button" class="refresh_btn btnType"><i class="refresh_img"></i>새로고침</button></p>
</div>
<div class="res_num">
<div class="res_info_btm1">
<dl>
<dt>전체건수</dt>
<dd><a href="#" data-tooltip="rev_popup04"><span class="c_222_g">101</span>건(100%)</a></dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>성공건수</dt>
<dd><span class="c_002c9a_g">100</span>건(100%)</dd>
</dl>
</div>
</div>
<div class="res_num">
<div class="res_info_btm1">
<dl>
<dt>대기건수</dt>
<dd><span class="c_666_g">0</span>건(0%)</dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>실패건수</dt>
<dd><span class="c_e40000_g">1</span>건(100%)</dd>
</dl>
</div>
</div>
</div>
</div>
<!--// 발송결과-->
<!--// 발송결과-->
<div class="table_btn clearfix">
<div class="table_btn_left">
<button type="button" data-tooltip="rev_popup02" class="btnType btnType14"><i class="add_img"></i>주소록 등록</button>
<button type="button" class="excel_btn btnType"><i class="downroad"></i>엑셀 다운로드</button>
</div>
<div class="table_btn_right">
<p class="table_btn_right_txt">* 전체 건수를 클릭하면 받는 사람 상세정보를 확인하실 수 있습니다.</p>
</div>
</div>
</div>
<!--// 발송결과 상세 정보 -->
@ -294,12 +441,12 @@ function fn_setData(data){
</div>
<div class="preview_auto">
<c:if test="${result.msgKind eq 'A' }" >
<p class="ad_tit">(광고)</p>
<p class="ad_tit">(광고)</p>
</c:if>
<p class="none_txt"><c:out value="${result.smsTxt }" /></p>
<p class="realtime"></p>
<c:if test="${result.msgKind eq 'A' }" >
<p class="deny_receipt">무료 거부 080-0000-0000</p>
<p class="deny_receipt">무료 거부 080-0000-0000</p>
</c:if>
</div>
</div>
@ -327,7 +474,7 @@ function fn_setData(data){
<!-- 발송대상리스트 팝업 -->
<div class="tooltip-wrap">
<div class="popup-com ad_layer rev_popup04" tabindex="0" data-tooltip-con="rev_popup04" data-focus="rev_popup04" data-focus-prev="rev_popup04-close" style="width:595px;">
<div class="popup-com ad_layer rev_popup04" tabindex="0" data-tooltip-con="rev_popup04" data-focus="rev_popup04" data-focus-prev="rev_popup04-close" style="width:530px;">
<div class="popup_heading">
<p>발송대상 리스트</p>
<button type="button" class="tooltip-close" data-focus="rev_popup04-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
@ -343,113 +490,35 @@ function fn_setData(data){
<div class="popup_search_type1">
<label for="" class="label">검색종류 선택</label>
<select id="" class="selType2 select_btn">
<option value="1">수신번호</option>
<option value="2">이름</option>
<option value="3">상세결과</option>
<select id="searchColumn" class="selType1 select_btn">
<option value="phone">수신번호</option>
<option value="result">상세결과</option>
</select>
<label for="" class="label">검색어입력</label>
<input type="text" class="send_text" id="" name="" value="" placeholder="3자 이상 입력하세요." onfocus="this.placeholder=''" onblur="this.placeholder='3자 이상 입력하세요.'">
<button type="button" class="btnType btnType2" style="width:63px; margin:0;">검색</button>
<input type="text" class="send_text" id="searchInput" name="" value="" placeholder="3자 이상 입력하세요." onfocus="this.placeholder=''" onblur="this.placeholder='3자 이상 입력하세요.'">
<button type="button" id="searchBtn" class="btnType btnType2" style="width:63px; margin:0;">검색</button>
</div>
<div class="list_tab_wrap2 type4">
<ul class="tabType3" id="tabType" name="tabType">
<li class="tab active"><button type="button" title="선택됨">전체</button></li>
<li class="tab"><button type="button">대기</button></li>
<li class="tab"><button type="button">성공</button></li>
<li class="tab"><button type="button">실패</button></li>
</ul>
</div>
<div class="tb_wrap" id="detailPopup" style="min-height:200px;">
<%-- <table class="tType4">
<colgroup>
<col style="width: 30%;">
<col style="width: 40%;">
<col style="width: 30%;">
</colgroup>
<thead>
<tr>
<th>이름
<div class="sort_wrap">
<input type="button" class="sort sortBtn">
</div>
</th>
<th>수신번호
<div class="sort_wrap">
<input type="button" class="sort sortBtn">
</div>
</th>
<th>상세결과
<div class="sort_wrap">
<input type="button" class="sort sortBtn">
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
<tr>
<td>홍길동</td>
<td>010-1234-5678</td>
<td>성공</td>
</tr>
</tbody>
</table>
--%>
<!-- 타블레이터 영역 -->
</div>
<div class="table_btn clearfix">
<div class="table_btn_left"></div>
<div class="table_btn_right">
<div class="table_btn_left">
<button type="button" onclick="fn_downloadFilteredExcel()" class="excel_btn btnType"><i class="downroad"></i>엑셀 다운로드</button>
<button type="button" data-tooltip="rev_popup02" class="btnType btnType14"><i class="add_img"></i>주소록 등록</button>
<button type="button" class="excel_btn btnType"><i class="downroad"></i>엑셀 다운로드</button>
<button type="button" class="btnType btnType15"><i class="remove_img"></i>주소록에서 번호 삭제</button>
</div>
</div>
<!--
pagination
<ul class="pagination">
<li class="page_first"><button><img src="/publish/images/content/page_first.png"
alt=""></button></li>
<li class="page_prev"><button><img src="/publish/images/content/page_prev.png"
alt=""></button></li>
<li class="on"><button>1</button></li>
<li><button>2</button></li>
<li><button>3</button></li>
<li><button>4</button></li>
<li><button>5</button></li>
<li><button>6</button></li>
<li><button>7</button></li>
<li><button>8</button></li>
<li><button>9</button></li>
<li><button>10</button></li>
<li class="page_next"><button><img src="/publish/images/content/page_next.png"
alt=""></button></li>
<li class="page_last"><button><img src="/publish/images/content/page_last.png"
alt=""></button></li>
</ul>pagination
-->
</div>
<div class="popup_btn_wrap2" style="margin: -40px auto 30px auto;">
<button type="button" class="tooltip-close" data-focus="adr_popup01-close" data-focus-next="popup02">닫기</button>