Merge branch 'master' into 알림톡api

This commit is contained in:
hehihoho3@gmail.com 2025-08-18 18:55:06 +09:00
commit 314a9421e5
111 changed files with 10307 additions and 4210 deletions

View File

@ -0,0 +1,130 @@
package itn.com.cmm;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class MjonFTSendVO{
/**
* @description : 수신자번호
*/
private String phone;
/**
* @description : [*이름*] - 치환문자
*/
private String name;
/**
* @description : [*1*] - 치환문자
*/
private String rep1;
/**
* @description : [*2*] - 치환문자
*/
private String rep2;
/**
* @description : [*3*] - 치환문자
*/
private String rep3;
/**
* @description : [*4*] - 치환문자
*/
private String rep4;
/**
* @description : 문자ID
*/
private String msgId;
/**
* @description : 전송그룹ID (대량문자의 경우 하나의 그룹으로 세팅)
*/
private String msgGroupId;
/**
* @description : 문자온 일반회원ID
*/
private String userId;
/**
* @description : 발신번호 (하이픈 등의 문자를 제외한 12byte이하의 숫자로 입력한다.)
*/
private String callFrom;
/**
* @description : 수신번호 (하이픈 등의 문자를 제외한 12byte이하의 숫자로 입력한다.)
*/
private String callTo;
/**
* @description : 예약 발송일시
*/
private String reqDate;
/**
* @description :전송사(04:다우, 05:JJ, 07:IVT, 01:아이하트 , 02:현대퓨처넷, 03:아이엠오)
*/
private String agentCode;
/**
* @description : MMS용 메시지제목
*/
private String subject;
/**
* @description : SMS용 메시지본문
*/
private String smsTxt;
/**
* @description : 메세지타입(4: SMS 전송, 5: URL 전송, 6: MMS전송, 7: BARCODE전송, 8: 카카오 알림톡 전송)
*/
private String msgType;
/**
* @description : 첨부파일 갯수
*/
private String fileCnt;
/**
* @description : 파일이름1
*/
private String filePath1;
/**
* @description : 파일이름2
*/
private String filePath2;
/**
* @description : 파일이름3
*/
private String filePath3;
/**
* @description : event 여부 / group tb에 넣는 용도 / 기본값 N
*/
private String eventYn="N";
/**
* @description : 개별단가
*/
private String eachPrice;
}

View File

@ -318,4 +318,17 @@ public final class MJUtil {
return dupliBlockList;
}
/**
* 사업자등록번호 대시('-') 추가
* 대시 유무 상관없음
* 유효성 맞지 않을시 변환안됨.
*/
public static String bizNoAddDash(String str) {
if(str == null) {
return str;
}
String regExp = "(\\d{3})(\\d{2})(\\d{5})$";
String chgf = "$1-$2-$3";
return str.replaceFirst(regExp, chgf);
}
}

View File

@ -466,7 +466,7 @@ public final class MsgSendUtils {
}
}
private static Boolean getReplaceYN(String smsTxtTemplate) {// 여러 치환 구문이 포함된 정규식 패턴
public static Boolean getReplaceYN(String smsTxtTemplate) {// 여러 치환 구문이 포함된 정규식 패턴
if (smsTxtTemplate == null) {
return false; // null일 경우 false 반환

View File

@ -796,9 +796,16 @@ public class MjonKakaoATController {
String lastUpdtPnttm = resultChannelList.get(i).getLastUpdtPnttm();
kakaoProfileVO.setSenderKey(senderKey);
kakaoProfileVO.setProfileId(profileId);
KakaoReturnVO tmpProfileVO = kakaoApiProfile.kakaoApiProfileList(kakaoProfileVO);
KakaoReturnVO tmpProfileVO = null;
// try {
//
// tmpProfileVO = kakaoApiProfile.kakaoApiProfileList(kakaoProfileVO);
// } catch (Exception e) {
// e.printStackTrace();
// // TODO: handle exception
// }
tmpProfileVO = kakaoApiProfile.kakaoApiProfileList(kakaoProfileVO);
ChannelIDVO returnChannelVO = new ChannelIDVO();
returnChannelVO.setSenderKey(tmpProfileVO.getSenderKey());

View File

@ -0,0 +1,34 @@
package itn.let.kakao.kakaoComm;
import java.math.BigDecimal;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
* @ BIZ_KAKAO_PRICE 테이블 관련
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class BizKakaoPriceVO {
private Long bizKakaoPriceId;
private String bizKakaoAtPrice; // 알림톡 단가
private String bizKakaoFtPrice; // 친구톡 단가
private String bizKakaoFtImgPrice; // 친구톡 이미지 단가
private String bizKakaoFtWideImgPrice; // 친구톡 와이드 이미지 단가
private String bizSmsPrice; // SMS 단가
private String bizMmsPrice; // MMS 단가
private String msgGroupId; // 메시지 그룹 ID
// getters and setters 생략
}

View File

@ -45,7 +45,13 @@ public class KakaoSendAdvcVO implements Serializable {
private String subMsgType; // 대체문자 타입
private String reqDate; // 예약일시
private String msgKind; // 예약일시
private String jsonStr; // jsonStr
private String adFlag; //친구톡 광고성 정보 사용 유무(Y:사용 , N:미사용)
private String sendKind; //문자전송 타입(H:홈페이지, A:API)
// =====
@ -54,6 +60,7 @@ public class KakaoSendAdvcVO implements Serializable {
private String eachPrice; // sms 단가
private String smsPrice; // sms 단가
private String mmsPrice; // mms 단가
private String picturePrice; // mms 단가
private String totPrice; // mms 단가
private String befCash; // mms 단가
private String befPoint; // mms 단가
@ -63,6 +70,9 @@ public class KakaoSendAdvcVO implements Serializable {
private String atDelayYn; // 카카오 알림톡 단가
private String bizKakaoResendOrgnlTxt; // 카카오 알림톡 단가
private String bizKakaoResendType; // 카카오 알림톡 단가
private String filePath1; // 대체문자 이미지
private String fileCnt; // 파일 카운트
private String bizKakaoImageType; // 파일 카운트
@ -84,7 +94,7 @@ public class KakaoSendAdvcVO implements Serializable {
"\n , msgType=[" + msgType + "]" +
"\n , templateContent=[" + templateContent + "]" +
"\n , templateTitle=[" + templateTitle + "]" +
"\n , buttonList=[" + buttonList.toString() + "]" +
"\n , buttonList=[" + (buttonList != null ? buttonList.toString() : "") + "]" +
"\n , subMsgSendYn=[" + subMsgSendYn + "]" +
"\n , subMsgTxt=[" + subMsgTxt + "]" +
"\n , subMsgType=[" + subMsgType + "]" +
@ -105,6 +115,8 @@ public class KakaoSendAdvcVO implements Serializable {
"\n , atDelayYn=[" + atDelayYn + "]" +
"\n , bizKakaoResendOrgnlTxt=[" + bizKakaoResendOrgnlTxt + "]" +
"\n , bizKakaoResendType=[" + bizKakaoResendType + "]" +
"\n , filePath1=[" + filePath1 + "]" +
"\n , bizKakaoImageType=[" + bizKakaoImageType + "]" +
"\n ]";
}

View File

@ -1,12 +1,17 @@
package itn.let.kakao.kakaoComm;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -19,12 +24,17 @@ import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import itn.com.cmm.MjonFTSendVO;
import itn.com.cmm.MjonMsgSendVO;
import itn.com.cmm.util.MsgSendUtils;
import itn.com.cmm.util.StringUtil;
import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiJsonSave;
import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate;
import itn.let.kakao.user.kakaoAt.service.impl.KakaoAlimTalkDAO;
import itn.let.mail.service.StatusResponse;
import itn.let.mjo.mjocommon.MjonCommon;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msg.service.impl.MjonMsgDAO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.spammsg.web.ComGetSpamStringParser;
import itn.let.module.base.PriceAndPoint;
@ -38,9 +48,15 @@ public class KakaoSendUtil {
@Autowired
KakaoApiJsonSave kakaoApiJsonSave;
@Resource(name="kakaoAlimTalkDAO")
private KakaoAlimTalkDAO kakaoAlimTalkDAO;
@Resource(name = "MjonMsgDataService")
private MjonMsgDataService mjonMsgDataService;
@Resource(name = "mjonMsgDAO")
private MjonMsgDAO mjonMsgDAO;
@Autowired
KakaoApiTemplate kakaoApiTemplate;
@ -51,6 +67,7 @@ public class KakaoSendUtil {
@Autowired
private MjonCommon mjonCommon;
// 클래스 수준에서 정적 Pattern 정의 (성능 최적화)
private static final Pattern REPLACEMENT_PATTERN = Pattern.compile("#\\{[^}]+\\}");
@ -141,7 +158,7 @@ public class KakaoSendUtil {
log.info("");
/** @공통 기본값 */
KakaoSendAdvcVO sendVO = createSendVO(kakaoVO);
KakaoSendAdvcVO sendVO = createATSendVO(kakaoVO);
String msgId = idList.get(i);
sendVO.setMsgId(msgId);
@ -284,19 +301,266 @@ public class KakaoSendUtil {
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로 설정
/**
* @methodName : populateSendListsFT
* @author : 이호영
* @date : 2025. 4. 18.
* @description :
* @return : List<KakaoSendAdvcVO>
* @param kakaoVO
* @param isNotified
* @param statusResponse
* @return
* @throws Exception
*
*/
public List<KakaoSendAdvcVO> populateSendListsFT(KakaoVO kakaoVO, boolean isNotified, StatusResponse statusResponse) throws Exception {
//사용자 현재 보유 금액 불러오기(문자 발송 금액 차감 이전 금액)
// String befCash = kakaoVO.getBefCash();
log.info("kakaoVO.ftToString() :: [{}]", kakaoVO.ftToString());
List<KakaoSendAdvcVO> kakaoSendAdvcListVO = new ArrayList<>();
Calendar calendar = setupBaseDate(kakaoVO, isNotified);
// 친구톡 내용
String templateContent = kakaoVO.getTemplateContent();
// 실패 대체 문자
String subMsgTxt = kakaoVO.getSubMsgTxt();
log.info(" + StringUtils.isNotEmpty(subMsgTxt) :: [{}]", StringUtils.isNotEmpty(subMsgTxt));
if(StringUtils.isNotEmpty(subMsgTxt)) {
kakaoVO.setSubMsgSendYn("Y");
// 광고문자면 처리 - 광고 Y
if ("Y".equals(kakaoVO.getAdFlag())) {
subMsgTxt = "(광고)" + subMsgTxt + "\n" + "무료거부 0808800858";
}
}
// 사용자 개인 단가 정보 불러오기
MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(kakaoVO.getUserId());
// 시스템 기본 단가 정보 불러오기
JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo();
// 치환 문구가 있는지 확인
Boolean replaceYN = MsgSendUtils.getReplaceYN(templateContent);
Boolean replaceSubYN = MsgSendUtils.getReplaceYN(subMsgTxt);
/** @MSGID KEY값 */
List<String> idList = mjonCommon.getNextCustomMsgCId(kakaoVO.getMjonFTSendVOList().size());
Map<String, Function<MjonFTSendVO, String>> placeholders = new HashMap<>();
placeholders.put("[*이름*]", MjonFTSendVO::getName);
placeholders.put("[*1*]", MjonFTSendVO::getRep1);
placeholders.put("[*2*]", MjonFTSendVO::getRep2);
placeholders.put("[*3*]", MjonFTSendVO::getRep3);
placeholders.put("[*4*]", MjonFTSendVO::getRep4);
String imageType = kakaoVO.getImageType();
// 개인단가
Float kakaoMemberFtPrice =
imageType == null ? mberManageVO.getKakaoFtPrice() :
"I".equals(imageType) ? mberManageVO.getKakaoFtImgPrice() :
"W".equals(imageType) ? mberManageVO.getKakaoFtWideImgPrice() :
mberManageVO.getKakaoFtPrice();
// 시스템단가
Float kakaoSysJoinFtPrice =
imageType == null ? sysJoinSetVO.getKakaoFtPrice() :
"I".equals(imageType) ? sysJoinSetVO.getKakaoFtImgPrice() :
"W".equals(imageType) ? sysJoinSetVO.getKakaoFtWideImgPrice() :
sysJoinSetVO.getKakaoFtPrice();
Float kakaoFtPrice =
getValidPrice(kakaoMemberFtPrice, kakaoSysJoinFtPrice);
// 대체문자가 있을경우 사용
float shortPrice = getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice());
float longPrice = getValidPrice(mberManageVO.getLongPrice(), sysJoinSetVO.getLongPrice());
float picturePrice = getValidPrice(mberManageVO.getPicturePrice(), sysJoinSetVO.getPicturePrice());
// String shortPStr = Float.toString(shortPrice);
// String mmsPStr = Float.toString(longPrice);
// String imgPrice = Float.toString(picturePrice);
String imgFilePath = "";
if(StringUtils.isNotEmpty(kakaoVO.getAtchFileId()) &&
("I".equals(imageType) || "W".equals(imageType))) {
imgFilePath = mjonMsgDAO.selectPhotoImgFileRealPath(kakaoVO.getAtchFileId());
}
/** @jsonStr 필요유무 */
boolean hasButtons = CollectionUtils.isNotEmpty(kakaoVO.getButtonVOList());
String sharedJsonStr = null;
List<MjonFTSendVO> mjonFTSendVOList = kakaoVO.getMjonFTSendVOList();
for (int i = 0; i < mjonFTSendVOList.size(); i++) {
MjonFTSendVO mjonFTSendVO = mjonFTSendVOList.get(i);
KakaoSendAdvcVO sendVO = createFTSendVO(kakaoVO, calendar);
// 공통 가격 설정
sendVO.setSmsPrice(Float.toString(shortPrice));
sendVO.setMmsPrice(Float.toString(longPrice));
sendVO.setPicturePrice(Float.toString(picturePrice));
sendVO.setCallTo(mjonFTSendVO.getPhone());
sendVO.setMsgId(idList.get(i));
String smsTxt = templateContent;
// 치환 문자면
if(replaceYN) {
// 치환 구문을 확인하고 치환할 값이 없으면 오류 반환
for (Map.Entry<String, Function<MjonFTSendVO, String>> entry : placeholders.entrySet()) {
String placeholder = entry.getKey();
String value = entry.getValue().apply(mjonFTSendVO);
if (smsTxt.contains(placeholder)) {
if (StringUtils.isEmpty(value)) {
statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "치환 문구중 " + placeholder + " 데이터가 없습니다.");
return null;
}
smsTxt = smsTxt.replace(placeholder, value);
}
}
}
sendVO.setTemplateContent(smsTxt);
String subMsgTxtTemp = null;
if(StringUtils.isNotEmpty(subMsgTxt)) {
subMsgTxtTemp = subMsgTxt;
if(replaceSubYN) {
// 치환 구문을 확인하고 치환할 값이 없으면 오류 반환
for (Map.Entry<String, Function<MjonFTSendVO, String>> entry : placeholders.entrySet()) {
String placeholder = entry.getKey();
String value = entry.getValue().apply(mjonFTSendVO);
if (subMsgTxtTemp.contains(placeholder)) {
if (StringUtils.isEmpty(value)) {
statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "치환 문구중 " + placeholder + " 데이터가 없습니다.");
return null;
}
subMsgTxtTemp = subMsgTxtTemp.replace(placeholder, value);
}
}
}
}
sendVO.setSubMsgTxt(subMsgTxtTemp);
//대체문자가 있으면
// Step 1-4: 실패 대체 문자 치환데이터 설정
if(StringUtils.isNotEmpty(subMsgTxtTemp)) { // 대체문자가 있나?
String sendType = "MMS";
if(StringUtils.isEmpty(imgFilePath)) {
int smsTxtByte = mjonCommon.getSmsTxtBytes(subMsgTxtTemp); // 문자 byte 계산
sendType = getMsgType(smsTxtByte); // 문자 타입(SHORT / MMS) 판별
}
sendVO.setSubMsgType(sendType); // 실패 대체 문자 타입 설정
if ("INVALID".equals(sendType)) {
// INVALID 타입이면 길이 초과 에러 응답 리턴
statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "전송 문자 길이를 초과하였습니다.");
return kakaoSendAdvcListVO;
}
float chosenPrice = 0f;
if(StringUtils.isNotEmpty(imgFilePath)) {
chosenPrice = Math.max(picturePrice, kakaoFtPrice);
sendVO.setFilePath1(imgFilePath);
sendVO.setFileCnt("1");
}else if ("MMS".equals(sendType)) {
// MMS 타입일 경우: longPrice(장문 가격) 카카오톡 단가 값을 선택
chosenPrice = Math.max(longPrice, kakaoFtPrice);
} else {
// SHORT 타입일 경우: shortPrice(단문 가격) 카카오톡 단가 값을 선택
chosenPrice = Math.max(shortPrice, kakaoFtPrice);
}
sendVO.setEachPrice(Float.toString(chosenPrice)); // 선택된 단가 설정
}else {
// 대체문자가 없으면 카카오톡 단가 그대로 사용
sendVO.setEachPrice( Float.toString(kakaoFtPrice) );
}
// 타이틀과 버튼이 있고
if(hasButtons || StringUtils.isNotEmpty(kakaoVO.getTemplateImageUrl())) {
//
if (StringUtils.isEmpty(sharedJsonStr)) {
// 치환 데이터가 없고 아직 생성되지 않았으면 번만 생성
sharedJsonStr = kakaoApiJsonSave.kakaoApiFTJsonSave_advc(kakaoVO);
sendVO.setJsonStr(sharedJsonStr);
}
sendVO.setBizJsonName(idList.get(0));
}
kakaoSendAdvcListVO.add(sendVO);
log.info(" sendVO.toString() :: [{}]",sendVO.toString());
}
return kakaoSendAdvcListVO;
}
public static String getMsgTypeWithByteValidation(MjonFTSendVO sendVO, String p_smsTxt) throws UnsupportedEncodingException {
// // 내문자저장함에 저장 문자를 발송하는 경우 문자 타입이 숫자가 아닌 문자로 넘어와서 변경 처리함
// if ("P".equals(msgType) || "L".equals(msgType)) {
// msgType = "6";
// } else if ("S".equals(msgType)) {
// msgType = "4";
// }
int smsTxtByte = MjonCommon.getSmsTxtBytes(p_smsTxt);
String msgType = SHORT_MSG_TYPE;
// 1. 2000 Byte 초과는 에러 처리
if (smsTxtByte > 2000) {
return "INVALID";
}
// 2. 첨부파일 여부 확인 (첨부파일이 있으면 장문으로 설정)
if (StringUtils.isNotEmpty(sendVO.getFilePath1())) {
msgType = LONG_MSG_TYPE;
}
// 3. 문자 길이에 따라 메시지 타입 설정 (90 Byte 초과는 장문)
else if (smsTxtByte > 90) {
msgType = LONG_MSG_TYPE;
}
return msgType;
}
private Calendar setupBaseDate(KakaoVO kakaoVO, boolean isNotified) throws ParseException {
// baseDate 추출
Date baseDate = resolveBaseDate(kakaoVO);
// 시간 성정
Calendar calendar = Calendar.getInstance();
calendar.setTime(baseDate); // calendar에 baseDate 설정
@ -310,6 +574,31 @@ public class KakaoSendUtil {
return calendar;
}
public Date resolveBaseDate(KakaoVO kakaoVO) throws ParseException {
Date now = new Date();
if (StringUtils.isEmpty(kakaoVO.getReqDate())) {
kakaoVO.setReqDate(DATE_FORMATTER.format(now));
return now;
}
return DATE_FORMATTER.parse(kakaoVO.getReqDate());
}
// 2. 친구톡 발송 제한 시간인지 확인
public boolean isRestrictedFriendTalkTime(Date baseDate) {
Calendar cal = Calendar.getInstance();
cal.setTime(baseDate);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
// 20:50 이후 ~ 익일 08:00 이전은 제한
if ((hour == 20 && minute >= 50) || hour > 20 || hour < 8) {
return true;
}
return false;
}
/**
* @methodName : createSendVO
* @author : 이호영
@ -320,14 +609,45 @@ public class KakaoSendUtil {
* @return
*
*/
private KakaoSendAdvcVO createSendVO(KakaoVO kakaoVO) {
private KakaoSendAdvcVO createATSendVO(KakaoVO kakaoVO) {
KakaoSendAdvcVO sendVO = new KakaoSendAdvcVO();
sendVO.setMsgType("8");
sendVO.setAgentCode("04");
sendVO.setSenderKey(kakaoVO.getSenderKey());
sendVO.setTemplateCode(kakaoVO.getTemplateCode());
sendVO.setUserId(kakaoVO.getUserId());
sendVO.setCallFrom(kakaoVO.getCallFrom());
return sendVO;
}
/**
* @methodName : createFTSendVO
* @author : 이호영
* @date : 2025. 4. 23.
* @description :
* @return : KakaoSendAdvcVO
* @param kakaoVO
* @return
*
*/
private KakaoSendAdvcVO createFTSendVO(KakaoVO kakaoVO, Calendar calendar) {
KakaoSendAdvcVO sendVO = new KakaoSendAdvcVO();
sendVO.setMsgType("9"); // 알림톡 8 친구톡 9
sendVO.setAgentCode("04");
// 발송시간 : 친구톡은 분할 발송이 없어 처음 vo 생성 입력
sendVO.setReqDate(DATE_FORMATTER.format(calendar.getTime()));
sendVO.setSenderKey(kakaoVO.getSenderKey());
sendVO.setTemplateCode(kakaoVO.getTemplateCode());
sendVO.setUserId(kakaoVO.getUserId());
sendVO.setCallFrom(kakaoVO.getCallFrom());
sendVO.setSubMsgSendYn(kakaoVO.getSubMsgSendYn());
sendVO.setAdFlag(kakaoVO.getAdFlag());
return sendVO;
}
@ -389,7 +709,7 @@ public class KakaoSendUtil {
}
public Float getValidPrice(Float personalPrice, Float defaultPrice) {
public static Float getValidPrice(Float personalPrice, Float defaultPrice) {
return (personalPrice != null && personalPrice > 0) ? personalPrice : defaultPrice;
}
@ -703,6 +1023,10 @@ public class KakaoSendUtil {
//카카오 친구톡 개인 단가가 없는 경우 시스템 단가로
if(mberManageVO.getKakaoFtPrice() == 0.0f)
mberManageVO.setKakaoFtPrice(sysJoinSetVO.getKakaoFtPrice());
if(mberManageVO.getKakaoFtImgPrice() == 0.0f)
mberManageVO.setKakaoFtImgPrice(sysJoinSetVO.getKakaoFtImgPrice());
if(mberManageVO.getKakaoFtWideImgPrice() == 0.0f)
mberManageVO.setKakaoFtWideImgPrice(sysJoinSetVO.getKakaoFtWideImgPrice());
// SMS 인경우
@ -714,7 +1038,9 @@ public class KakaoSendUtil {
// 사용자 개인 단가가 없으면 시스템 단가로
if(mberManageVO.getLongPrice() == 0.0f)
mberManageVO.setLongPrice(sysJoinSetVO.getLongPrice());
if(mberManageVO.getPicturePrice() == 0.0f)
mberManageVO.setPicturePrice(sysJoinSetVO.getPicturePrice());
return mberManageVO;
}
@ -1213,4 +1539,175 @@ public class KakaoSendUtil {
statusResponse.setMessage(msg);
}
// 보유 금액이 충분한지 확인하는 메서드
public boolean isCashSufficient(String userId, List<KakaoSendAdvcVO> kakaoSendAdvcListVO) throws Exception {
String userMoney = priceAndPoint.getBefCash(userId);
// 쉼표 제거
userMoney = userMoney.replace(",", "");
// 사용자 보유 금액 BigDecimal 변환 (HALF_EVEN 적용)
BigDecimal befCash = new BigDecimal(userMoney).setScale(2, RoundingMode.HALF_EVEN);
log.info(" + userMoney :: [{}]", userMoney);
log.info(" + befCash :: [{}]", befCash);
// 메시지 금액 계산 (HALF_EVEN 적용)
BigDecimal totalEachPrice = kakaoSendAdvcListVO.stream()
.map(msg -> new BigDecimal(String.valueOf(msg.getEachPrice()))) // 변환 오류 방지
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_EVEN); // 일관성 유지
log.info(" + totalEachPrice :: [{}]", totalEachPrice);
// 비교 수행
return befCash.compareTo(totalEachPrice) >= 0;
}
/**
* @methodName : insertKakaoAtDataJsonInfo_advc
* @author : 이호영
* @date : 2025. 4. 24.
* @description : INSERT INTO BIZ_ATTACHMENTS
* @return : void
* @param kakaoSendAdvcListVO
*
*/
public void insertKakaoAtDataJsonInfo_advc(List<KakaoSendAdvcVO> kakaoSendAdvcListVO) {
List<KakaoSendAdvcVO> jsonInfoData = new ArrayList<>(kakaoSendAdvcListVO);
jsonInfoData.removeIf(t -> StringUtils.isBlank(t.getJsonStr()));
log.info(" + jsonInfoData Insert :: [{}]", jsonInfoData.size());
if(jsonInfoData.size() > 0) {
kakaoAlimTalkDAO.insertKakaoAtDataJsonInfo_advc(jsonInfoData);
}
}
/**
* @methodName : insertKakaoData_advc
* @author : 이호영
* @date : 2025. 3. 20.
* @description : 카카오 batch 발송 => mj_msg_data
* @return : int
* @param kakaoSendAdvcVOList
* @param parentLoopCount
* @param isJsonNotEmpty
* @param isJsonNameAllSame
* @return
*
*/
public int insertKakaoData_advc(List<KakaoSendAdvcVO> 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<Double> batchExecutionTimes = new ArrayList<>();
// 번째 배치에서만 삽입했는지 추적하는 플래그
for (int i = 0; i < totalSize; i += batchSize) {
// Batch 시작 시간 측정
long batchStartTime = System.currentTimeMillis();
// Batch 리스트 생성
List<KakaoSendAdvcVO> 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 데이터 처리 활용
* */
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;
}
public 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.setTemplateContent(kakaoVO.getTemplateContent());
sendVO.setMsgGroupCnt(Integer.toString(instCnt));
sendVO.setReserveYn(kakaoVO.getReserveYn());
sendVO.setBefCash(priceAndPoint.getBefCash(sendVO.getUserId()));
sendVO.setBefPoint(priceAndPoint.getBefPoint(sendVO.getUserId()));
sendVO.setAdFlag(kakaoVO.getAdFlag());
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());
sendVO.setBizKakaoImageType(kakaoVO.getImageType());
kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc(sendVO);
}
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import itn.com.cmm.MjonFTSendVO;
import itn.let.mjo.msg.service.MjonMsgVO;
import lombok.Getter;
import lombok.Setter;
@ -259,9 +260,14 @@ public class KakaoVO extends MjonMsgVO{
private String msgResendAllGroupId;
private String msgResendAllTmpKey;
private String msgResendAllYellowId;
private String bizKakaoResendType;
private String fileCnt;
private List<Map<String, String>> varListMap;
private List<MjonFTSendVO> mjonFTSendVOList = new ArrayList<>();
@Override
public String toString() {
String varListMapString = "[";
@ -286,6 +292,18 @@ public class KakaoVO extends MjonMsgVO{
}
varListMapString += "]";
StringBuilder mjonFTListSb = new StringBuilder("[");
if (mjonFTSendVOList != null && !mjonFTSendVOList.isEmpty()) {
String prefix = "";
for (MjonFTSendVO vo : mjonFTSendVOList) {
mjonFTListSb.append(prefix).append(vo == null ? "null" : vo.toString());
prefix = ", ";
}
}
mjonFTListSb.append("]");
return "KakaoSendAdvcVO[" +
"\n senderKey=[" + senderKey + "]" +
"\n , subMsgTxtReplYn=[" + subMsgTxtReplYn + "]" +
@ -312,8 +330,61 @@ public class KakaoVO extends MjonMsgVO{
"\n , varListMap=[" + varListMapString + "]" +
"\n , befCash=[" + getBefCash() + "]" +
"\n , befPoint=[" + getBefPoint() + "]" +
"\n , mjonFTSendVOList=" + mjonFTListSb.toString() +
"\n ]";
}
public String ftToString() {
StringBuilder sb = new StringBuilder("KakaoFTSendVO[");
sb.append("\n senderKey=[").append(senderKey).append("]");
sb.append("\n , imageFileName=[").append(imageFileName).append("]");
sb.append("\n , imageType=[").append(imageType).append("]");
sb.append("\n , imgTitle=[").append(imgTitle).append("]");
sb.append("\n , imgLink=[").append(imgLink).append("]");
sb.append("\n , templateContent=[").append(templateContent).append("]");
sb.append("\n , templateImageUrl=[").append(templateImageUrl).append("]");
sb.append("\n , smsTxtArea=[").append(getSubMsgTxt()).append("]");
sb.append("\n , subMsgSendYn=[").append(subMsgSendYn).append("]");
sb.append("\n , subMsgTxtReplYn=[").append(subMsgTxtReplYn).append("]");
sb.append("\n , subMsgType=[").append(subMsgType).append("]");
sb.append("\n , subMsgTxt=[").append(subMsgTxt).append("]");
sb.append("\n , reserveYn=[").append(getReserveYn()).append("]");
sb.append("\n , menuTopTab=[").append(menuTopTab).append("]");
sb.append("\n , bizJsonYn=[").append(bizJsonYn).append("]");
sb.append("\n , senderKey=[").append(senderKey).append("]");
sb.append("\n , callFrom=[").append(getCallFrom()).append("]");
sb.append("\n , kakaoFtPrice=[").append(getEachPrice()).append("]");
sb.append("\n , reqDate=[").append(getReqDate()).append("]");
sb.append("\n , spamStatus=[").append(getSpamStatus()).append("]");
sb.append("\n , txtReplYn=[").append(getTxtReplYn()).append("]");
sb.append("\n , atSmishingYn=[").append(getAtSmishingYn()).append("]");
// sb.append("\n , tmpBtnSelect=[").append(getTmpBtnSelect()).append("]");
StringBuilder btnListSb = new StringBuilder("[");
if (buttonVOList != null && !buttonVOList.isEmpty()) {
String prefix = "";
for (KakaoButtonVO btn : buttonVOList) {
btnListSb.append(prefix).append(btn == null ? "null" : btn.toString());
prefix = ", ";
}
}
btnListSb.append("]");
sb.append("\n , buttonVOList=").append(btnListSb);
// mjonFTSendVOList 내용
StringBuilder ftList = new StringBuilder("[");
if (mjonFTSendVOList != null && !mjonFTSendVOList.isEmpty()) {
String prefix = "";
for (MjonFTSendVO vo : mjonFTSendVOList) {
ftList.append(prefix).append(vo == null ? "null" : vo.toString());
prefix = ", ";
}
}
ftList.append("]");
sb.append("\n , mjonFTSendVOList=").append(ftList);
sb.append("\n]");
return sb.toString();
}
}

View File

@ -5,7 +5,10 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
@ -15,6 +18,8 @@ import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
@ -30,16 +35,21 @@ import org.apache.http.util.EntityUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import egovframework.rte.fdl.property.EgovPropertyService;
import itn.com.cmm.service.EgovFileMngService;
import itn.com.cmm.service.EgovFileMngUtil;
import itn.com.cmm.service.FileVO;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.mail.service.StatusResponse;
import itn.let.utl.fcc.service.EgovStringUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component("kakaoApiImageUpload")
public class KakaoApiImageUpload {
@ -57,7 +67,17 @@ public class KakaoApiImageUpload {
@Resource(name = "propertiesService")
protected EgovPropertyService propertyService;
/** 첨부파일 저장경로 */
@Value("#{globalSettings['Globals.file.saveDir']}")
private String fileSaveDir;
@Resource(name="EgovFileMngUtil")
private EgovFileMngUtil fileUtil;
@Resource(name="EgovFileMngService")
private EgovFileMngService fileMngService;
/**
* @Method Name : kakaoApiImageUpload
@ -219,13 +239,13 @@ public class KakaoApiImageUpload {
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", kakaoVO.getImgTitle())
.addTextBody("link", kakaoVO.getImgLink())
.addTextBody("title", "test")
.addTextBody("link", "https://maaa.com")
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath),ContentType.MULTIPART_FORM_DATA,fullFileName)
.build();
httpPost.setEntity(httpEntity);
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
@ -245,6 +265,7 @@ public class KakaoApiImageUpload {
String msg = object.get("message").toString();
String imgUrl = "";
log.info(" : code :: [{}]", code);
if(code.equals("200")) {
imgUrl = object.get("image").toString();
}
@ -273,6 +294,174 @@ public class KakaoApiImageUpload {
}
/**
* @methodName : kakaoApiImageUpload_advc
* @author : 이호영
* @date : 2025. 6. 4.
* @description : kakaoApiImageUpload 수정
* @return : StatusResponse
* @param kakaoVO
* @param files
* @param i
* @return
* @throws Exception
*
*/
public StatusResponse kakaoApiImageUpload_advc(KakaoVO kakaoVO, Map<String, MultipartFile> files, int fileKeyParam) throws Exception {
// try {
String storePathString = propertyService.getString("Globals.fileStorePath");
File saveFolder = new File(storePathString);
if (!saveFolder.exists()) saveFolder.mkdirs();
// for (MultipartFile file : files.values()) {
MultipartFile file = files.values().stream().findFirst().orElse(null);
if (file == null || file.isEmpty()) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "유효한 이미지 파일이 없습니다.", LocalDateTime.now());
}
String originalName = file.getOriginalFilename();
if (originalName == null || originalName.isEmpty()) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "파일명이 비어 있습니다.", LocalDateTime.now());
}
String ext = FilenameUtils.getExtension(originalName).toLowerCase();
if (!ext.matches("jpg|jpeg|png")) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "지원하지 않는 이미지 형식입니다.");
}
long size = file.getSize();
if (size > 5 * 1024 * 1024) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "이미지 용량은 5MB 이내여야 합니다.");
}
BufferedImage image = ImageIO.read(file.getInputStream());
if (image == null) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "이미지를 읽을 수 없습니다.");
}
int width = image.getWidth();
int height = image.getHeight();
String type = kakaoVO.getImageType();
if ("W".equals(type)) {
if (width != 800 || height != 600) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "와이드 이미지는 800x600 사이즈만 허용됩니다.");
}
} else {
float ratio = width / (float) height;
// log.info("width : [{}], ",width);
// log.info("height : [{}], ",height);
// log.info("ratio : [{}], ",ratio);
if (width < 500 || ratio < 0.75 || ratio > 2.0) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "일반 이미지는 가로 500px 이상, 비율 2:1 이상 또는 3:4 이하만 허용됩니다.");
}
}
String atchFileId = this.saveImgFile(files);
String newName = EgovStringUtil.getTimeStamp() + fileKeyParam;
String filePath = storePathString + File.separator + newName + "." + ext;
file.transferTo(new File(filePath));
// 카카오 API 호출
CloseableHttpClient httpClient = HttpClients.createDefault();
String apiUrl = mjonBizUrl + "/v3/kakao/image/upload";
HttpPost httpPost = new HttpPost(apiUrl);
/*HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", kakaoVO.getImgTitle())
.addTextBody("link", kakaoVO.getImgLink())
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath), ContentType.MULTIPART_FORM_DATA, newName + "." + ext)
.build();
*/
HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", originalName)
.addTextBody("link", StringUtils.isEmpty(kakaoVO.getImgLink()) ? "https://" : kakaoVO.getImgLink())
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath), ContentType.MULTIPART_FORM_DATA, newName + "." + ext)
.build();
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
JSONParser parser = new JSONParser();
JSONObject object = (JSONObject) parser.parse(result);
String code = object.get("code").toString();
if ("200".equals(code)) {
Map<String, Object> returnMap = new HashMap<>();
returnMap.put("imgUrl", object.get("image").toString());
returnMap.put("fileName", originalName);
returnMap.put("atchFileId", atchFileId);
return new StatusResponse(HttpStatus.OK, "이미지 등록이 완료 되었습니다.", returnMap);
} else {
return new StatusResponse(HttpStatus.BAD_REQUEST, object.get("message").toString(), LocalDateTime.now());
}
} else {
return new StatusResponse(HttpStatus.BAD_REQUEST, "카카오 API 요청 실패", LocalDateTime.now());
}
// }
// } catch (Exception e) {
// log.error("kakaoApiImageUpload_advc API Error", e);
// return new StatusResponse(HttpStatus.BAD_REQUEST, "친구톡 이미지 등록에 실패했습니다.", LocalDateTime.now());
// }
}
private String saveImgFile(Map<String, MultipartFile> files) throws Exception {
String atchFileId = "";
String isThumbFile = "";
String imagePath = "";
String KeyStr = "CANVASIMG_";
Date now = new Date();
SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");
String fdlDate = formatDate.format(now);
imagePath = fileSaveDir+"/file/MMS/" + fdlDate;
if (!files.isEmpty()) {
List<FileVO> result = fileUtil.parseImageFileInf(files, KeyStr, 0, atchFileId, imagePath, isThumbFile);
atchFileId = fileMngService.insertFileInfs(result);
}
return atchFileId;
}
/**
* @Method Name : kakaoApiTemplateImageUpload
* @작성일 : 2023. 2. 16.
@ -488,17 +677,20 @@ public class KakaoApiImageUpload {
jsonObject.put("apiKey", mjonBizKakaoApiKey);
jsonObject.put("imageUrl", kakaoVO.getTemplateImageUrl());
log.info("kakaoVO.getTemplateImageUrl() :: [{}]", kakaoVO.getTemplateImageUrl());
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(sendUrl);
httpPost.setEntity(new StringEntity(jsonObject.toString(), "UTF-8"));
httpPost.addHeader("Content-type", "application/json");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Accept", "application/json");
HttpResponse response = httpClient.execute(httpPost);
String result = "";
String statusCode = Integer.toString(response.getStatusLine().getStatusCode());
log.info(" + statusCode :: [{}]", statusCode);
if(statusCode.equals("200")) {
result = EntityUtils.toString(response.getEntity());
@ -528,5 +720,7 @@ public class KakaoApiImageUpload {
return kakaoReturnVO;
}
}

View File

@ -10,12 +10,18 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import itn.com.cmm.util.StringUtil;
import itn.let.kakao.kakaoComm.KakaoButtonVO;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
@ -208,6 +214,139 @@ public class KakaoApiJsonSave {
return jsonFileName;
}
/*
* 친구톡 발송시 이미지, 버튼 추가에 따른 Json 파일 생성
* 2025.04.18
* 우영두
* 파일은 하나만 생성해서 동일하게 사용함.
*
* */
public String kakaoApiFTJsonSave_advc(KakaoVO kakaoVO) throws JsonProcessingException {
// json파일 저장
ObjectMapper mapper = new ObjectMapper();
ObjectNode jo = mapper.createObjectNode();
// 버튼
if (kakaoVO.getButtonVOList() != null && !kakaoVO.getButtonVOList().isEmpty()) {
ArrayNode buttonList = mapper.createArrayNode();
for (KakaoButtonVO buttonInfoVO : kakaoVO.getButtonVOList()) {
ObjectNode button = mapper.createObjectNode();
button.put("name", buttonInfoVO.getName());
button.put("type", buttonInfoVO.getLinkType());
switch (buttonInfoVO.getLinkType()) {
case "WL":
button.put("url_mobile", buttonInfoVO.getLinkMo());
button.put("url_pc", buttonInfoVO.getLinkPc());
break;
case "AL":
button.put("scheme_ios", buttonInfoVO.getLinkIos());
button.put("scheme_android", buttonInfoVO.getLinkAnd());
break;
case "BC":
// 상담톡
break;
case "BT":
// 전환
break;
}
buttonList.add(button);
}
jo.set("button", buttonList);
}
// 이미지
String imageType = kakaoVO.getImageType();
if (StringUtils.isNotEmpty(imageType)) {
ObjectNode image = mapper.createObjectNode();
image.put("img_url", kakaoVO.getTemplateImageUrl());
image.put("img_link", StringUtils.isNotEmpty(kakaoVO.getImgLink()) ? kakaoVO.getImgLink() : kakaoVO.getTemplateImageUrl());
jo.set("image", image);
// wide 여부
if ("W".equals(imageType)) {
ObjectNode extra = mapper.createObjectNode();
extra.put("wide", "Y");
jo.set("extra", extra);
}
}
// 문자열로 변환 (이스케이프 없음)
return mapper.writeValueAsString(jo);
/*
// 버튼리스트 JSON 생성
JSONArray buttonList = new JSONArray();
for(KakaoButtonVO buttonInfoVO : kakaoVO.getButtonVOList()) {
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 templateImageInfo = new JSONObject();
JSONObject templateImageExtInfo = new JSONObject();
String imageType = kakaoVO.getImageType();
if(StringUtils.isNotEmpty(imageType)) {
templateImageInfo.put("img_url", kakaoVO.getTemplateImageUrl());
templateImageInfo.put("img_link", StringUtils.isNotEmpty(kakaoVO.getImgLink()) ? kakaoVO.getImgLink() : kakaoVO.getTemplateImageUrl() );
}
// wide 여부
if ("W".equals(imageType)) {
ObjectNode extra = mapper.createObjectNode();
extra.put("wide", "Y");
jo.set("extra", extra);
}
JSONObject jo = new JSONObject();
if(buttonList.size() != 0) {
jo.put("button", buttonList);
}
if(templateImageInfo.size() != 0) {
jo.put("image", templateImageInfo);
}
if(templateImageExtInfo.size() != 0) {
jo.put("extra", templateImageExtInfo);
}
// 입력 json 데이터를 파일로 변경
String jsonStr = jo.toString();
return jsonStr;*/
}
/*
* 친구톡 발송시 이미지, 버튼 추가에 따른 Json 파일 생성
* 2024.01.17
@ -298,7 +437,7 @@ public class KakaoApiJsonSave {
// 입력 json 데이터를 파일로 변경
String jsonStr = jo.toString();
System.out.println("jsonFileName : "+jsonFileName);
File outPut = new File(jsonFileName);
outPut.createNewFile();

View File

@ -230,7 +230,8 @@ public class KakaoApiProfile {
if(code.equals("200")) {
JSONObject templateProfile = (JSONObject) object.get("data");
System.out.println("templateProfile = " + templateProfile.toJSONString());
String senderKey = getStringValue(templateProfile, "senderKey"); //발신프로필키
String uuid = getStringValue(templateProfile, "uuid"); //카카오톡 채널
String name = getStringValue(templateProfile, "name"); //카카오톡 채널 발신프로필

View File

@ -30,115 +30,6 @@ public class KakaoFTJsonSave {
static String json;
@SuppressWarnings("unchecked")
public String kakaoApiJsonSave(KakaoVO kakaoVO, String[] varValInfo) {
// json파일 저장
Date nowDate = new Date();
SimpleDateFormat todayFrom = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat timeFrom = new SimpleDateFormat("HHmmss");
String jsonFileName = mjonBizJsonDir+"/"+kakaoVO.getUserId()+"/"+todayFrom.format(nowDate)+"/"+kakaoVO.getSendType(); // 아이디/날짜/타입
String fileName = timeFrom.format(nowDate)+"_"+kakaoVO.getDestPhone()+".json";
try {
File userIdFile = new File(jsonFileName);
if(!userIdFile.exists()) {
userIdFile.mkdirs(); // 없으면 하위 디렉토리 까지 생성
jsonFileName = jsonFileName +"/"+fileName;
}else {
jsonFileName = jsonFileName +"/"+fileName;
System.out.println("jsonFileName : "+jsonFileName);
File file1 = new File(jsonFileName);
if (file1.isFile()) {
return jsonFileName;
}
}
KakaoReturnVO templateDetail = kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO);
// 버튼리스트 JSON 생성
JSONArray buttonList = new JSONArray();
// 버튼 수량 체크 진행
for(KakaoButtonVO buttonInfoVO : templateDetail.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);
}
// Image JSON 생성
JSONObject imageJson = new JSONObject();
// img형과 wide 형인경우만 등록 (if문으로 제어)
imageJson.put("img_url", "등록된 이미지 URL");
imageJson.put("img_link", "이동 페이지 URL");
// Wide JSON 생성
JSONObject wideJson = new JSONObject();
// wide 형인경우만 등록(if문으로 제어)
wideJson.put("wide", "Y");
JSONObject jo = new JSONObject();
if(imageJson.size() != 0) {
jo.put("image", imageJson);
}
if(wideJson.size() != 0) {
jo.put("extra", wideJson);
}
if(buttonList.size() != 0) {
jo.put("button", buttonList);
}
// 입력 json 데이터를 파일로 변경
String jsonStr = jo.toString();
System.out.println("jsonFileName : "+jsonFileName);
File outPut = new File(jsonFileName);
outPut.createNewFile();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outPut), "euc-kr"));
bw.write(jsonStr);
bw.close();
} catch (IOException e) {
System.out.println("json 생성 실패");
e.printStackTrace();
}
return jsonFileName;
}
@SuppressWarnings("unchecked")
public String kakaoApiJsonSave(KakaoVO kakaoVO) {

View File

@ -108,4 +108,9 @@ public class KakaoAlimTalkDAO extends EgovAbstractDAO {
public void insertKakaoGroupDataTb_advc(KakaoSendAdvcVO sendVO) {
insert("kakaoAlimTalkDAO.insertKakaoGroupDataTb_advc", sendVO);
}
public KakaoVO selectBizLog(String bizUmid) {
return (KakaoVO) select("kakaoAlimTalkDAO.selectBizLog", bizUmid);
// return (KakaoVO) select("kakaoAlimTalkDAO.selectKakaoAtUmid", bizUmid);
}
}

View File

@ -29,6 +29,7 @@ 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.BizKakaoPriceVO;
import itn.let.kakao.kakaoComm.KakaoSendAdvcVO;
import itn.let.kakao.kakaoComm.KakaoSendUtil;
import itn.let.kakao.kakaoComm.KakaoVO;
@ -45,6 +46,7 @@ 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.mjo.pay.service.impl.MjonPayDAO;
import itn.let.module.base.PriceAndPoint;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.sym.site.service.impl.SiteManagerDAO;
@ -86,6 +88,9 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
/** userManageService */
@Resource(name = "userManageService")
private EgovUserManageService userManageService;
@Autowired
private MjonPayDAO mjonPayDAO;
@Autowired
KakaoSendUtil kakaoSendUtil;
@ -95,6 +100,11 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
@Autowired
private PriceAndPoint priceAndPoint;
final String KAKAO_SUCCESS_CODE = "7000";
final String RESEND_YN_YES = "Y";
final String SMS_SUCCESS_CODE = "4100"; // SMS 성공 코드
final String MMS_SUCCESS_CODE = "6600"; // MMS 성공 코드
//발신프로필 상태값 변경(삭제/복구 기능)
@Override
@ -819,45 +829,109 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
}
/*
* 카카오 친구톡 발송 실패에 따른 금액 환불 처리
* 카카오 친구톡 대체문자 선택에 대해 성공시 친구톡과 문자 금액 차액의 환불도 처리 .
* */
/**
* @ 카카오 친구톡 환불
*/
@Override
public void selectKakaoFtSentRefundList() throws Exception {
/**
* 1. 카카오 FT 전송성공 확인
* 2. 카카오 FT 전송실패, 대채문자 전송확인
* 3. 카카오 FT 전송 실패 확인
*/
List<KakaoVO> kakaoFtSentRefundList = kakaoAlimTalkDAO.selectKakaoFtSentRefundList();
for(KakaoVO vo : kakaoFtSentRefundList) {
System.out.println(vo.getMsgGroupId() +"________결과 : " +vo.getRsltCode() +" 대체문자 전송 : "+vo.getSubMsgSendYn());
for(KakaoVO kakaoVO : kakaoFtSentRefundList) {
System.out.println(kakaoVO.getMsgGroupId() +"________결과 : " +kakaoVO.getRsltCode() +" 대체문자 전송 : "+kakaoVO.getSubMsgSendYn());
if(vo.getRsltCode().equals("7000")) {//친구톡 발송 성공시
if(KAKAO_SUCCESS_CODE.equals(kakaoVO.getRsltCode())) {//친구톡 발송 성공시
kakaoAlimTalkDAO.updateKakaoFtSend(vo);
processFtSendCharge(kakaoVO);
}else if(vo.getSubMsgSendYn().equals("Y")) {//친구톡 발송 실패 했을 경우
//대체문자 발송 UMID 번호 조회 - 알림톡 쿼리 동일하게 사용
KakaoVO info = kakaoAlimTalkDAO.selectKakaoAtUmid(vo);
System.out.println("대체문자 전송 : " + info.getBizUmid());
if (info.getBizUmid() != null) {//대체문자 발송 완료인 경우
kakaoAlimTalkDAO.updateKakaoAtSubMsgSend(vo);
}else {
kakaoAlimTalkDAO.updateKakaoFtNotSend(vo);
}
}else if(RESEND_YN_YES.equals(kakaoVO.getSubMsgSendYn())) {
//친구톡 발송 실패 했고, 대체문자 발송 했을 경우
handleAlternativeMessageScenario(kakaoVO);
}else {
kakaoAlimTalkDAO.updateKakaoFtNotSend(vo);
handleRefund(kakaoVO, "카카오 친구톡 전송 실패로 인한 결재 금액 환불");
}
}
}
private void processFtSendCharge(KakaoVO kakaoVO) throws Exception {
if(RESEND_YN_YES.equals(kakaoVO.getSubMsgSendYn())) {
BizKakaoPriceVO bizKakaoPriceVO = mjonPayDAO.selectBizKakaoPrice(kakaoVO.getMsgGroupId());
BigDecimal sendPrice = null;
if(StringUtils.isEmpty(kakaoVO.getBizKakaoImageType())){
sendPrice = new BigDecimal(bizKakaoPriceVO.getBizKakaoFtPrice());
}else if("I".equals(kakaoVO.getBizKakaoImageType())){
sendPrice = new BigDecimal(bizKakaoPriceVO.getBizKakaoFtImgPrice());
}else if("W".equals(kakaoVO.getBizKakaoImageType())){
sendPrice = new BigDecimal(bizKakaoPriceVO.getBizKakaoFtWideImgPrice());
}
// 예시: 건당 가격이 이미 String 형태라면 변환
BigDecimal eachPrice = new BigDecimal(kakaoVO.getEachPrice());
// 차이 계산
BigDecimal diffPrice = eachPrice.subtract(sendPrice);
if (diffPrice.compareTo(BigDecimal.ZERO) > 0) {
String result = diffPrice.toString();
kakaoVO.setEachPrice(result);
handleRefund(kakaoVO, "카카오 친구톡 전송으로 인한 결재 차액 환불");
}
}else {
mjonMsgDAO.updateRefundY(kakaoVO);
}
// TODO Auto-generated method stub
}
private void handleAlternativeMessageScenario(KakaoVO kakaoVO) throws Exception {
KakaoVO bizLogVO = kakaoAlimTalkDAO.selectBizLog(kakaoVO.getBizUmid());
log.info("대체문자 전송 UMID: {}", kakaoVO.getBizUmid());
// 대체문자가 성공적으로 발송되었는지 확인 (SMS 또는 MMS 성공)
boolean isAlternativeMessageSuccessful = false;
if (bizLogVO != null && StringUtils.isNotEmpty(bizLogVO.getBizLogCallStatus())) {
if (SMS_SUCCESS_CODE.equals(bizLogVO.getBizLogCallStatus())
|| MMS_SUCCESS_CODE.equals(bizLogVO.getBizLogCallStatus())) {
isAlternativeMessageSuccessful = true;
}
}
log.info("bizLogVO.getBizLogCallStatus() :: [{}]", bizLogVO.getBizLogCallStatus());
log.info("isAlternativeMessageSuccessful :: [{}]", isAlternativeMessageSuccessful);
// 대체문자 성공이면 환불 완료처리면 한다.
if (isAlternativeMessageSuccessful) {
mjonMsgDAO.updateRefundY(kakaoVO);
} else {
// 대체문자 발송 실패 경우 (친구톡 비용 환불 필요)
handleRefund(kakaoVO, "카카오 친구톡 전송 실패로 인한 결재 금액 환불");
}
}
private void handleRefund(KakaoVO vo, String msg) throws Exception {
// mj_cash 테이블에 환불 내역 추가 회원 금액 업데이트
// eachPrice는 환불될 금액이므로 양수여야 합니다.
priceAndPoint.insertCashAndPoint(
vo.getUserId(),
Float.parseFloat(vo.getEachPrice()), // 환불 금액은 양수
msg,
vo.getMsgGroupId(),
vo.getUserData()
);
// 해당 row 환불 처리 (mj_msg_data.REFUND_YN = 'Y')
mjonMsgDAO.updateRefundY(vo);
}
@Override
public StatusResponse insertKakaoAtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception {
@ -921,7 +995,7 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
/** @전송금액 확인 --------------------------------------------------*/
if (!isCashSufficient(userId, kakaoSendAdvcListVO)) {
if (!kakaoSendUtil.isCashSufficient(userId, kakaoSendAdvcListVO)) {
log.error("Insufficient balance for message sending.");
return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다.", "STAT_1060");
}
@ -929,7 +1003,8 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
/** @json파일이 있을 떄 biz_attachments insert */
this.insertKakaoAtDataJsonInfo_advc(kakaoSendAdvcListVO);
kakaoSendUtil.insertKakaoAtDataJsonInfo_advc(kakaoSendAdvcListVO);
// this.insertKakaoAtDataJsonInfo_advc(kakaoSendAdvcListVO);
Map<String, List<KakaoSendAdvcVO>> priceGroupedMessages = kakaoSendAdvcListVO.stream()
@ -959,7 +1034,7 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
? apiMsgType + "," + kakaoSendAdvcListVO.get(0).getMsgType()
: kakaoSendAdvcListVO.get(0).getMsgType();
// 발송 데이터 삽입
int instCnt = this.insertKakaoData_advc(groupedMsgList);
int instCnt = kakaoSendUtil.insertKakaoData_advc(groupedMsgList);
// int instCnt = 6;
if(instCnt > 0) {
@ -969,7 +1044,7 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
KakaoSendAdvcVO sendVO = groupedMsgList.get(0);
/** @groupData 테이블 insert */
this.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, sendVO);
kakaoSendUtil.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, sendVO);
/** @biz_kakao_price에 insert (대체문자 환불관련 테이블)*/
@ -1056,8 +1131,6 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
return statusResponse;
}
private void insertKakaoAtDataJsonInfo_advc(List<KakaoSendAdvcVO> kakaoSendAdvcListVO) {
@ -1207,29 +1280,4 @@ public class KakaoAlimTalkServiceImpl extends EgovAbstractServiceImpl implements
}

View File

@ -0,0 +1,12 @@
package itn.let.kakao.user.kakaoFt.service;
import javax.servlet.http.HttpServletRequest;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.mail.service.StatusResponse;
public interface KakaoFriendsTalkService {
StatusResponse insertKakaoFtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception;
}

View File

@ -0,0 +1,249 @@
package itn.let.kakao.user.kakaoFt.service.impl;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
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.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.impl.KakaoAlimTalkDAO;
import itn.let.kakao.user.kakaoFt.service.KakaoFriendsTalkService;
import itn.let.mail.service.StatusResponse;
import itn.let.mjo.mjocommon.MjonCommon;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msg.service.impl.MjonMsgDAO;
import itn.let.module.base.PriceAndPoint;
import itn.let.uss.umt.service.EgovUserManageService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service("KakaoFriendsTalkService")
public class KakaoFriendsTalkServiceImpl extends EgovAbstractServiceImpl implements KakaoFriendsTalkService{
@Resource(name = "egovFriendstalkTemplateIdService")
private EgovIdGnrService idgenFriendTalkTmpId;
@Resource(name="kakaoFriendsTalkTemplateDAO")
private KakaoFriendsTalkTemplateDAO kakaoFriendsTalkTemplateDAO;
@Resource(name="mjonMsgDAO")
private MjonMsgDAO mjonMsgDAO;
/** userManageService */
@Resource(name = "userManageService")
private EgovUserManageService userManageService;
@Resource(name = "egovMjonMsgGroupIdGnrService")
private EgovIdGnrService idgenMjonMsgGroupId;
@Resource(name="kakaoAlimTalkDAO")
private KakaoAlimTalkDAO kakaoAlimTalkDAO;
@Autowired
KakaoSendUtil kakaoSendUtil;
@Autowired
private MjonCommon mjonCommon;
@Autowired
private PriceAndPoint priceAndPoint;
@Override
public StatusResponse insertKakaoFtSandAjax_advc(KakaoVO kakaoVO, HttpServletRequest request) throws Exception {
StatusResponse statusResponse = new StatusResponse();
log.info(" + kakaoVO.toString() :: [{}]", kakaoVO.toString());
log.info(" + kakaoVO.toString() :: [{}]", kakaoVO.ftToString());
// 측정할 메소드 호출 시간 기록
Instant start = Instant.now();
// KakaoSendAdvcVO
Map<String, Object> 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,
"현재 고객님께서는 문자온 서비스 이용이 정지된 상태로 친구톡을 발송하실 수 없습니다. 이용정지 해제를 원하시면 고객센터로 연락주시기 바랍니다.");
}
/**
* 친구톡은 발송 시간 제약이 있음
*/
if(kakaoSendUtil.isRestrictedFriendTalkTime(kakaoSendUtil.resolveBaseDate(kakaoVO))) {
// UNAUTHORIZED : 인증되지 않은 사용자가 접근하려고
return new StatusResponse(HttpStatus.BAD_REQUEST,
"친구톡은 20시 50분부터 익일 08시까지 발송이 제한됩니다.");
}
/** @isHolidayNotified
* @false : 알림 X
* @true : 알림 O */
boolean isNotified = mjonCommon.processUserAndCheckAT(kakaoVO);
/** @카카오톡 전송 list 셋팅 -------------------------------------------*/
List<KakaoSendAdvcVO> kakaoSendAdvcListVO = kakaoSendUtil.populateSendListsFT(kakaoVO, isNotified, statusResponse);
if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) {
log.error(" + populateSendLists 처리 중 오류 발생: {}", statusResponse.getMessage());
return statusResponse;
}
/** @전송금액 확인 --------------------------------------------------*/
if (!kakaoSendUtil.isCashSufficient(userId, kakaoSendAdvcListVO)) {
log.error("Insufficient balance for message sending.");
return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다.");
}
/** @json파일이 있을 떄 biz_attachments insert */
kakaoSendUtil.insertKakaoAtDataJsonInfo_advc(kakaoSendAdvcListVO);
Map<String, List<KakaoSendAdvcVO>> priceGroupedMessages = kakaoSendAdvcListVO.stream()
.collect(Collectors.groupingBy(KakaoSendAdvcVO::getEachPrice));
// instTotalCnt : 화면에서 보여줄 발송건수
int instTotalCnt = 0;
// 임시
List<String> nextMsgGroupIdA = new ArrayList<>();
// 대안: entrySet() 직접 사용
for (Map.Entry<String, List<KakaoSendAdvcVO>> entry : priceGroupedMessages.entrySet()) {
// entry 사용
List<KakaoSendAdvcVO> groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트
String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId();
groupedMsgList.forEach(t -> t.setMsgGroupId(nextMsgGroupId));
// 발송 데이터 삽입
int instCnt = kakaoSendUtil.insertKakaoData_advc(groupedMsgList);
// int instCnt = 6;
if(instCnt > 0) {
instTotalCnt += instCnt;
KakaoSendAdvcVO sendVO = groupedMsgList.get(0);
/** @groupData 테이블 insert */
kakaoSendUtil.insertKakaoGroupDataTb_advc(instCnt, kakaoVO, sendVO);
/** @biz_kakao_price에 insert (대체문자 환불관련 테이블)*/
priceAndPoint.insertBizFtKakaoPrice(kakaoVO.getUserId(), sendVO.getMsgGroupId());
priceAndPoint.insertCashAndPoint(kakaoVO.getUserId()
, -Float.parseFloat(sendVO.getTotPrice())
, "카카오 친구톡 총 "+groupedMsgList.size()+"건 중 " + instCnt + "건 발송"
, nextMsgGroupId
);
/** @SLACK발송 */
/** @발송조건이되면 발송 */
if(isNotified) {
mjonCommon.getAdminKakaoAtSendSlack(sendVO);
}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();
log.info("메소드 실행 시간 (초): {} s", seconds);
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;
}
}

View File

@ -13,9 +13,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
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.servlet.ModelAndView;
@ -29,7 +31,9 @@ import itn.let.kakao.kakaoComm.KakaoSendUtil;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.kakao.kakaoComm.kakaoApi.service.KakaoApiService;
import itn.let.kakao.user.kakaoAt.service.KakaoAlimTalkService;
import itn.let.kakao.user.kakaoFt.service.KakaoFriendsTalkService;
import itn.let.kakao.user.kakaoFt.service.KakaoFriendsTalkTemplateService;
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;
@ -68,6 +72,9 @@ public class KakaoFriendsTalkSendController {
@Resource(name = "kakaoFriendsTalkTemplateService")
private KakaoFriendsTalkTemplateService kakaoFtTemplateService;
@Resource(name = "KakaoFriendsTalkService")
private KakaoFriendsTalkService kakaoFriendsTalkService;
/** userManageService */
@Resource(name = "userManageService")
private EgovUserManageService userManageService;
@ -113,114 +120,109 @@ public class KakaoFriendsTalkSendController {
model.addAttribute("loginVO", loginVO);
try {
if(!userId.equals("") && !author.equals("ROLE_ADMIN")) {
if(!"".equals(userId) && !"ROLE_ADMIN".equals(author)) {
//사용자 등록 발신프로필 정보 조회해오기
kakaoVO.setUserId(userId);
List<KakaoVO> resultProfileList = kakaoApiService.selectKakaoProfileList(kakaoVO);
model.addAttribute("resultProfileList", resultProfileList);
//사용자 등록 발신프로필 정보 조회해오기
kakaoVO.setUserId(userId);
List<KakaoVO> resultProfileList = kakaoApiService.selectKakaoProfileList(kakaoVO);
model.addAttribute("resultProfileList", resultProfileList);
// 특수문자 리스트 불러오기
MjonSymbolVO symbolVO = new MjonSymbolVO();
List<MjonSymbolVO> symbolList = mjonSymbolService.selectMjonSymbolList(symbolVO);
model.addAttribute("symbolList", symbolList);
//아이디 발신번호 리스트 불러오기.
List<String> resultSendPhonList = mjonMsgDataService.selectSendPhonNumList(userId);
List<String> resultPhonList = new ArrayList<String>();
MJUtil mjUtil = new MJUtil();
for(String phone : resultSendPhonList) {
resultPhonList.add(mjUtil.addDash(phone));
}
model.addAttribute("resultPhonList", resultPhonList);
MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
model.addAttribute("atSmishingYn", mberManageVO.getAtSmishingYn());
//3.사용자 개인단가 정보가 0이 아니면 개인단가 사용, 없으면 시스템 기본 단가 사용
/*Float shortPrice = mberManageVO.getShortPrice();
Float longPrice = mberManageVO.getLongPrice();
Float picturePrice = mberManageVO.getPicturePrice();
Float picture2Price = mberManageVO.getPicture2Price();
Float picture3Price = mberManageVO.getPicture3Price();*/
BigDecimal userMoney = new BigDecimal(mberManageVO.getUserMoney()).setScale(2, RoundingMode.HALF_EVEN);
model.addAttribute("userMoney", userMoney);
//////////////////////////////////////////////////////////////////
//최근 전송 내역
MjonMsgDataVO searchVO = new MjonMsgDataVO();
Calendar cal = Calendar.getInstance();
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
cal.setTime(now);
cal.add(Calendar.DATE, -3);
String chkDate = format.format(cal.getTime());
searchVO.setUserId(userId);
searchVO.setMyMsgStDt(chkDate); //검색 시작일 저장 - 현재날짜로 부터 3일 이전 날짜로 시작
model.addAttribute("resultLatestMsgList", mjonMsgDataService.selectLatestMsgList(searchVO));
//자주보내는 번호
model.addAttribute("resultBookMarkMsgList", mjonMsgDataService.selectBookMarkMsgList(searchVO));
// 사용자 정의 단가 정보 불러오기(시스템 단가 혹은 협의 단가)
model.addAttribute("sendPrice", kakaoSendUtil.selectSendPriceOfKakaoAtAndSmsAndMms(userId));
//사용자 템플릿 정보 조회
String friendId = kakaoVO.getFriendId();
KakaoVO resultTemplateVO = new KakaoVO();
if(friendId != null) {
resultTemplateVO = kakaoFtTemplateService.selectKakaoFriendsTemplateDetail(kakaoVO);
}
model.addAttribute("resultTemplateVO", resultTemplateVO);
//친구톡 발송시간 체크 하기 - 20:50 ~ 익일 08:00 사이에는 발송 금지
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date nows = new Date();
String nowDate = sdf1.format(nows);
cal.setTime(nows);
int hours = cal.get(Calendar.HOUR_OF_DAY);
int minuts = cal.get(Calendar.MINUTE);
// 특수문자 리스트 불러오기
MjonSymbolVO symbolVO = new MjonSymbolVO();
List<MjonSymbolVO> symbolList = mjonSymbolService.selectMjonSymbolList(symbolVO);
model.addAttribute("symbolList", symbolList);
//아이디 발신번호 리스트 불러오기.
List<String> resultSendPhonList = mjonMsgDataService.selectSendPhonNumList(userId);
List<String> resultPhonList = new ArrayList<String>();
MJUtil mjUtil = new MJUtil();
for(String phone : resultSendPhonList) {
resultPhonList.add(mjUtil.addDash(phone));
}
model.addAttribute("resultPhonList", resultPhonList);
MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
model.addAttribute("atSmishingYn", mberManageVO.getAtSmishingYn());
//3.사용자 개인단가 정보가 0이 아니면 개인단가 사용, 없으면 시스템 기본 단가 사용
/*Float shortPrice = mberManageVO.getShortPrice();
Float longPrice = mberManageVO.getLongPrice();
Float picturePrice = mberManageVO.getPicturePrice();
Float picture2Price = mberManageVO.getPicture2Price();
Float picture3Price = mberManageVO.getPicture3Price();*/
BigDecimal userMoney = new BigDecimal(mberManageVO.getUserMoney()).setScale(2, RoundingMode.HALF_EVEN);
model.addAttribute("userMoney", userMoney);
//////////////////////////////////////////////////////////////////
//최근 전송 내역
MjonMsgDataVO searchVO = new MjonMsgDataVO();
Calendar cal = Calendar.getInstance();
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
cal.setTime(now);
cal.add(Calendar.DATE, -3);
String chkDate = format.format(cal.getTime());
searchVO.setUserId(userId);
searchVO.setMyMsgStDt(chkDate); //검색 시작일 저장 - 현재날짜로 부터 3일 이전 날짜로 시작
// model.addAttribute("resultLatestMsgList", mjonMsgDataService.selectLatestMsgList(searchVO));
//자주보내는 번호
// model.addAttribute("resultBookMarkMsgList", mjonMsgDataService.selectBookMarkMsgList(searchVO));
// 사용자 정의 단가 정보 불러오기(시스템 단가 혹은 협의 단가)
model.addAttribute("sendPrice", kakaoSendUtil.selectSendPriceOfKakaoAtAndSmsAndMms(userId));
//사용자 템플릿 정보 조회
String friendId = kakaoVO.getFriendId();
KakaoVO resultTemplateVO = new KakaoVO();
if(friendId != null) {
resultTemplateVO = kakaoFtTemplateService.selectKakaoFriendsTemplateDetail(kakaoVO);
}
model.addAttribute("resultTemplateVO", resultTemplateVO);
//친구톡 발송시간 체크 하기 - 20:50 ~ 익일 08:00 사이에는 발송 금지
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date nows = new Date();
String nowDate = sdf1.format(nows);
cal.setTime(nows);
int hours = cal.get(Calendar.HOUR_OF_DAY);
int minuts = cal.get(Calendar.MINUTE);
boolean sendStatus = true;
boolean sendStatus = true;
if(hours >= 20) {
if(hours >= 20) {
if(minuts >= 50) {
if(minuts >= 50) {
System.out.println("발송금지 시간" + hours + ":" + minuts);
sendStatus = false;
}
}
if(hours < 8) {
System.out.println("발송금지 시간" + hours + ":" + minuts);
System.out.println("발송금지 시간" + hours + ":" + minuts);
sendStatus = false;
}
System.out.println("발송상태는 ::: "+sendStatus);
model.addAttribute("sendStatus", sendStatus);
}
} catch (Exception e) {
System.out.println(" kakaoFriendsTalkMsgDataViewDataRegist Error ::: " + e);
if(hours < 8) {
System.out.println("발송금지 시간" + hours + ":" + minuts);
sendStatus = false;
}
System.out.println("발송상태는 ::: "+sendStatus);
model.addAttribute("sendStatus", sendStatus);
}
return "web/kakao/msgdata/ft/KakaoFriendsTalkMsgDataView";
@ -313,7 +315,29 @@ public class KakaoFriendsTalkSendController {
return modelAndView;
}
/**
* @methodName : sendMsgData_ft_advc
* @author : 이호영
* @date : 2025. 4. 17.
* @description : 친구톡 발송기능
* @return : ResponseEntity<StatusResponse>
* @param kakaoVO
* @param request
* @param model
* @return
* @throws Exception
*
*/
@RequestMapping(value = "/web/mjon/kakao/friendstalk/kakaoFriendsTalkMsgSendAjax_advc.do")
public ResponseEntity<StatusResponse> kakaoFriendsTalkMsgSendAjax_advc(
@RequestBody KakaoVO kakaoVO,
HttpServletRequest request
) throws Exception {
System.out.println(" :: sendMsgData_ft_advc :: ");
return ResponseEntity.ok().body(kakaoFriendsTalkService.insertKakaoFtSandAjax_advc(kakaoVO, request)) ;
}
/**
* @Method Name : kakaoFriendsTalkMsgSendAjax

View File

@ -1,5 +1,6 @@
package itn.let.kakao.user.kakaoFt.web;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -8,11 +9,16 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
@ -21,6 +27,7 @@ import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
import egovframework.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import itn.com.cmm.EgovMessageSource;
import itn.com.cmm.LoginVO;
import itn.com.cmm.RestResponse;
import itn.com.cmm.service.EgovCmmUseService;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
@ -32,10 +39,14 @@ import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate;
import itn.let.kakao.kakaoComm.kakaoApi.KakaoFTJsonSave;
import itn.let.kakao.kakaoComm.kakaoApi.service.KakaoApiService;
import itn.let.kakao.user.kakaoFt.service.KakaoFriendsTalkTemplateService;
import itn.let.mail.service.StatusResponse;
import itn.let.mjo.symbol.service.MjonSymbolService;
import itn.let.mjo.symbol.service.MjonSymbolVO;
import itn.let.uss.ion.cnt.service.CntManageVO;
import itn.let.uss.umt.service.EgovUserManageService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class KakaoFriendsTalkTemplateController {
@ -170,6 +181,63 @@ public class KakaoFriendsTalkTemplateController {
return modelAndView;
}
@RequestMapping(value="/web/pop/ft/kakaoTemplatePop.do")
public String siteContentIntro(@ModelAttribute CntManageVO cntManageVO, HttpServletRequest request, Model model) throws Exception {
return "/web/pop/kakaoFtPop";
}
@ResponseBody
@RequestMapping(value= {"/web/mjon/kakao/template/sendKakaoFriendsTemplateImageUploadAjax_advc.do"})
public ResponseEntity<StatusResponse> sendKakaoFriendsTemplateImageUploadAjax_advc(
@ModelAttribute("kakaoVO") KakaoVO kakaoVO
, final MultipartHttpServletRequest multiRequest
) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsonView");
try {
LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
if(StringUtils.isEmpty(userId)) { //KISA 보안취약점 조치 (2018-12-10, 이정은)
return ResponseEntity.ok(
new StatusResponse(HttpStatus.UNAUTHORIZED
, "로그인을 하셔야 이용 가능합니다."
, LocalDateTime.now()
)
);
}
final Map<String, MultipartFile> files = multiRequest.getFileMap();
/* if (!files.isEmpty()){
Map<String, String> resultMap = kakaoApiImageUpload.kakaoApiImageUpload(kakaoVO, files, 0);
//테스트
modelAndView.addObject("code", resultMap.get("code"));
modelAndView.addObject("msg", resultMap.get("msg"));
modelAndView.addObject("imgUrl", resultMap.get("imgUrl"));
}
modelAndView.addObject("result", "success");*/
return ResponseEntity.ok().body(kakaoApiImageUpload.kakaoApiImageUpload_advc(kakaoVO, files, 0));
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
return ResponseEntity.ok().body(new StatusResponse(
HttpStatus.BAD_REQUEST
, "오류가 발생하였습니다."
, ""
));
}
}
// 카카오 친구톡 템플릿 등록요청
@ -189,9 +257,13 @@ public class KakaoFriendsTalkTemplateController {
@ModelAttribute("kakaoVO") KakaoVO kakaoVO
, final MultipartHttpServletRequest multiRequest
) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsonView");
// log.info(" + kakaoVO.getAdFlag() :: [{}]", kakaoVO.getAdFlag());
log.info(" + ImgLink :: [{}]", kakaoVO.getImgLink());
try {
LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
@ -207,16 +279,18 @@ public class KakaoFriendsTalkTemplateController {
kakaoVO.setLastUpdusrId(userId);
kakaoVO.setSendType("FT");
/*
String imgUrl = kakaoVO.getTemplateImageUrl();
int buttonSize = kakaoVO.getButtonVOList().size();
if(!imgUrl.equals("") || buttonSize > 0) {
log.info(" + kakaoVO.getAdFlag() :: [{}]", kakaoVO.getAdFlag());
//json 파일 생성 처리
String resultJsonPath = kakaoFTJsonSave.kakaoApiJsonSave(kakaoVO);
kakaoVO.setBizJsonName(resultJsonPath);
}
}*/
int result = kakaoFtTemplateService.insertKakaoFriendsTemplateData(kakaoVO);

View File

@ -6,9 +6,11 @@ import java.util.List;
import itn.let.uss.umt.service.UserDefaultVO;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class KakaoSentVO extends UserDefaultVO{
private static final long serialVersionUID = 1L;
@ -90,7 +92,7 @@ public class KakaoSentVO extends UserDefaultVO{
private String bizKakaoFtPrice;
private String bizSmsPrice;
private String bizMmsPrice;
private int successCount;
private int waitCount;
private int failCount;
@ -112,6 +114,7 @@ public class KakaoSentVO extends UserDefaultVO{
private String successPrice;
private String kakaoResendSuccPrice;
private String bizKakaoImageType;
private String divideYn;
@ -119,4 +122,6 @@ public class KakaoSentVO extends UserDefaultVO{
private String yellowId;
private String adFlag;
}

View File

@ -39,7 +39,9 @@ import itn.let.kakao.user.sent.service.KakaoSentDetailVO;
import itn.let.kakao.user.sent.service.KakaoSentService;
import itn.let.kakao.user.sent.service.KakaoSentVO;
import itn.let.mjo.msgsent.service.MjonMsgSentVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service("KakaoSentService")
public class KakaoSentServiceImpl extends EgovAbstractServiceImpl implements KakaoSentService{
@ -140,6 +142,9 @@ public class KakaoSentServiceImpl extends EgovAbstractServiceImpl implements Ka
List<KakaoSentVO> resultList = new ArrayList<KakaoSentVO>();
resultList = kakaoSentDAO.selectAllKakaoSentList_advc(kakaoSentVO);
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
//totPrice 계산 상태코드 set
resultList = resultList.stream().map(t -> setPriceNCode(t)).collect(Collectors.toList());
@ -287,15 +292,27 @@ public class KakaoSentServiceImpl extends EgovAbstractServiceImpl implements Ka
* */
private KakaoSentVO setPriceNCode(KakaoSentVO result) {
log.info("=============================== setPriceNCode ================================");
//성공 건수 세팅
KakaoSentVO eachCnt = new KakaoSentVO();
eachCnt.setMsgGroupId(result.getMsgGroupId());
eachCnt.setBizKakaoResendYn("Y".equals(result.getBizKakaoResendYn()) ? "Y" : "N");
eachCnt.setMsgType(result.getMsgType());
eachCnt.setBizKakaoImageType(result.getBizKakaoImageType());
eachCnt.setBizKakaoResendType(result.getBizKakaoResendType());
try {
log.info("eachCnt.getMsgType() :: [{}]", eachCnt.getMsgType());
log.info("eachCnt.getBizKakaoImageType() :: [{}]", eachCnt.getBizKakaoImageType());
log.info("eachCnt.getBizKakaoResendType() :: [{}]", eachCnt.getBizKakaoResendType());
eachCnt = kakaoSentDAO.selectKakaoSentCntEachCnt_advc(eachCnt);
} catch (Exception e) {
System.out.println("setPriceNCode error!!");
}
log.info(" + eachCnt.toString() :: [{}]", eachCnt.toString());
// log.info(" + eachCnt.getSuccessPrice() :: [{}]", eachCnt.getSuccessPrice());
result.setSuccessCount(eachCnt.getSuccessCount());
result.setWaitCount(eachCnt.getWaitCount());
@ -328,9 +345,9 @@ public class KakaoSentServiceImpl extends EgovAbstractServiceImpl implements Ka
//총금액 시작
//=======================================================
// TotPrice : 성공건수에 대한 금액 곱하기
BigDecimal atPrice = new BigDecimal(successPrice);
BigDecimal kakaoResendPrice = new BigDecimal(kakaoResendSuccPrice);
// TotPrice : 성공건수에 대한 금액 곱하기 ? : null 처리
BigDecimal atPrice = successPrice != null ? new BigDecimal(successPrice) : BigDecimal.ZERO;
BigDecimal kakaoResendPrice = kakaoResendSuccPrice != null ? new BigDecimal(kakaoResendSuccPrice) : BigDecimal.ZERO;
BigDecimal totalPrice = atPrice.add(kakaoResendPrice);
// 소수점 자리로 설정 (반올림)// totalPrice 값을 소수점 자리까지 반올림하여 roundedTotalPrice에 저장
// RoundingMode.HALF_UP: 반올림 방식으로, 소수점 기준 5 이상이면 올림, 그렇지 않으면 내림

View File

@ -2,6 +2,7 @@ package itn.let.kakao.user.sent.web;
import java.io.FileReader;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import itn.com.cmm.util.DateUtils;
import java.text.SimpleDateFormat;
@ -38,6 +39,7 @@ import itn.com.cmm.LoginVO;
import itn.com.cmm.util.StringUtil;
import itn.com.cmm.util.StringUtil2;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.cmm.vo.FileInfoVO;
import itn.let.kakao.admin.kakaoAt.service.MjonKakaoATVO;
import itn.let.kakao.kakaoComm.KakaoButtonVO;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
@ -46,13 +48,20 @@ import itn.let.kakao.kakaoComm.kakaoApi.KakaoApiTemplate;
import itn.let.kakao.user.sent.service.KakaoSentDetailVO;
import itn.let.kakao.user.sent.service.KakaoSentService;
import itn.let.kakao.user.sent.service.KakaoSentVO;
import itn.let.mjo.msgsent.service.MjonMsgSentVO;
import itn.let.mjo.msgsent.service.impl.MjonMsgSentDAO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class KakaoSentController {
@Resource(name = "KakaoSentService")
private KakaoSentService kakaoSentService;
@Resource(name="MjonMsgSentDAO")
private MjonMsgSentDAO mjonMsgSentDAO;
@Autowired
KakaoApiTemplate kakaoApiTemplate;
@ -182,7 +191,7 @@ public class KakaoSentController {
//전체 발송 리스트 불러오기
List<KakaoSentVO> resultAllSentList = kakaoSentService.selectAllKakaoSentList(kakaoSentVO);
System.out.println("??");
model.addAttribute("resultAllSentList", resultAllSentList);
// model.addAttribute("resultAllSentCnt", resultAllSentList.size());
@ -890,22 +899,21 @@ public class KakaoSentController {
KakaoReturnVO returnVO = new KakaoReturnVO();
try {
String tmpContent = kakaoATVO.getSmsTxtTrans();
String jsonFilePath = kakaoATVO.getBizKakaoJsonFile();
String jsonContents = kakaoATVO.getContents();
//친구톡 이미지 또는 버튼 정보가 있다면 실행
if(jsonFilePath != null && jsonFilePath.length() > 0) {
if(jsonContents != null && jsonContents.length() > 0) {
FileReader reader = new FileReader(jsonFilePath);
/*FileReader reader = new FileReader(jsonFilePath);
int ch;
String resultStr = "";
while ((ch = reader.read()) != -1) {
resultStr = resultStr + (char)ch;
}
*/
JSONParser parser = new JSONParser();
Object obj = parser.parse(resultStr);
Object obj = parser.parse(jsonContents);
JSONObject object = (JSONObject) obj;
String image = (object.get("image") == null) ? null : object.get("image").toString();
@ -964,7 +972,7 @@ public class KakaoSentController {
}
//친구톡 내용 셋팅
returnVO.setTemplateContent(tmpContent);
returnVO.setTemplateContent(kakaoATVO.getSmsTxt());
} catch (Exception e) {
e.printStackTrace();
@ -1037,42 +1045,70 @@ public class KakaoSentController {
//발송 관리 문자발송 내용 상세보기 팝업 => 문자내용(MJ_MSG_DATA)
MjonKakaoATVO mjonKakaoATResultVO = kakaoSentService.selectKakaoSentDetailDataAjax(mjonKakaoATVO);
// 대체문자 엔터키 치환
mjonKakaoATResultVO.setSmsTxt(StringUtil2.replaceBR(mjonKakaoATResultVO.getSmsTxt()));
model.addAttribute("resultMsgDetail", mjonKakaoATResultVO);
try {
String msgType = mjonKakaoATResultVO.getMsgType();
//발송 관리 문자발송 내용 상세보기 팝업 => 문자내용(MJ_MSG_DATA)
MjonKakaoATVO mjonKakaoATResultVO = kakaoSentService.selectKakaoSentDetailDataAjax(mjonKakaoATVO);
// 대체문자 엔터키 치환
if(StringUtils.isNotEmpty(mjonKakaoATResultVO.getSmsTxt())) {
mjonKakaoATResultVO.setSmsTxt(StringUtil2.replaceBR(mjonKakaoATResultVO.getSmsTxt()));
}
model.addAttribute("resultMsgDetail", mjonKakaoATResultVO);
String msgType = mjonKakaoATResultVO.getMsgType();
if(msgType.equals("8")) {//카카오 알림톡인 경우 상세정보 처리
// 템플릿 api 가져오기
KakaoVO kakaoVO = new KakaoVO();
kakaoVO.setSenderKey(mjonKakaoATResultVO.getMsgNoticetalkSenderKey());
kakaoVO.setTemplateCode(mjonKakaoATResultVO.getMsgNoticetalkTmpKey());
KakaoReturnVO kakaoTemplateInfo =kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO);
model.addAttribute("kakaoTemplateInfo", kakaoTemplateInfo);
// //템플릿 api 가져오기
}else if(msgType.equals("9")) {//카카오 친구톡인 경우 상세정보 처리
//String smsTxt = mjonKakaoATResultVO.getSmsTxt();
KakaoReturnVO kakaoTemplateInfo = getKakaoFTSendTemplateInfo(mjonKakaoATResultVO);
model.addAttribute("kakaoTemplateInfo", kakaoTemplateInfo);
if(StringUtils.isNotEmpty( mjonKakaoATResultVO.getFilePath1() )) {
List<FileInfoVO> fileInfos = new ArrayList<>();
// 확장자 제외한 파일명
String fileId = FilenameUtils.getBaseName(mjonKakaoATResultVO.getFilePath1());
// 파일 정보 조회
MjonMsgSentVO info = mjonMsgSentDAO.selectFileInfo(fileId);
// FileInfo 객체 생성 추가
FileInfoVO fileInfo = new FileInfoVO();
fileInfo.setAtchFileId(info.getAtchFileId());
fileInfo.setFileSn(info.getFileSn());
fileInfos.add(fileInfo);
model.addAttribute("fileInfos", fileInfos);
}
//kakaoTemplateInfo.setTemplateContent(smsTxt);
}else {
model.addAttribute("kakaoTemplateInfo", "");
}
model.addAttribute("msgType", msgType);
if(msgType.equals("8")) {//카카오 알림톡인 경우 상세정보 처리
// 템플릿 api 가져오기
KakaoVO kakaoVO = new KakaoVO();
kakaoVO.setSenderKey(mjonKakaoATResultVO.getMsgNoticetalkSenderKey());
kakaoVO.setTemplateCode(mjonKakaoATResultVO.getMsgNoticetalkTmpKey());
KakaoReturnVO kakaoTemplateInfo =kakaoApiTemplate.selectKakaoApiTemplateDetail(kakaoVO);
model.addAttribute("kakaoTemplateInfo", kakaoTemplateInfo);
// //템플릿 api 가져오기
}else if(msgType.equals("9")) {//카카오 친구톡인 경우 상세정보 처리
//String smsTxt = mjonKakaoATResultVO.getSmsTxt();
KakaoReturnVO kakaoTemplateInfo = getKakaoFTSendTemplateInfo(mjonKakaoATResultVO);
//kakaoTemplateInfo.setTemplateContent(smsTxt);
model.addAttribute("kakaoTemplateInfo", kakaoTemplateInfo);
}else {
model.addAttribute("kakaoTemplateInfo", "");
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
model.addAttribute("msgType", msgType);
return "web/kakao/sent/KakaoSentDetailPopAjax";
}
}

View File

@ -7,6 +7,7 @@ import java.util.Map;
import org.springframework.http.HttpStatus;
import itn.let.mjo.pay.service.RefundVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

View File

@ -38,5 +38,5 @@ public class MjonEventVO {
private String point; //사용자 포인트 정보
private String userId; //사용자 아이디
private String frstRegisterId; //등록자 아이디
}

View File

@ -167,6 +167,7 @@ public class MjonMsgVO extends ComDefaultVO{
private float smsPrice; // sms 단가
private float mmsPrice; // mms 단가
private float picturePrice; // mms 단가
private float kakaoAtPrice; // 카카오 알림톡 단가
private float kakaoFtPrice; // 카카오 친구톡 단가
private float kakaoFtImgPrice;// 카카오 이미지 단가
@ -303,6 +304,8 @@ public class MjonMsgVO extends ComDefaultVO{
private String bizLogCallStatusCode; //다우기술 biz_log 테이블의 발송결과 코드 성공/실패/대기 코드값 변환(성공:S, 대기:W, 실패:F).
private String bizLogCallStatusTxt; //다우기술 biz_log 테이블의 발송결과 내용 텍스트.
private String bizLogStatus; //다우기술 biz_log 테이블의 전송상태값
private String bizKakaoImageType; // 비즈 발송 img
private String accessKey; // 'API Key',

View File

@ -455,6 +455,11 @@ public class MjonMsgDAO extends EgovAbstractDAO {
update("mjonMsgDAO.updateKakaoAtDelayCancelMsgDataFlag", mjonMsgVO);
}
// mj_msg_data 테이블 지연 알림톡 취소 수정
public void updateRefundY(MjonMsgVO mjonMsgVO) {
update("mjonMsgDAO.updateRefundY", mjonMsgVO);
}
// mj_msg_group_data 테이블 지연 알림톡 취소 수정
public void updateKakaoAtDelayCancelMsgGroupDataFlag(MjonMsgVO mjonMsgVO) {
update("mjonMsgDAO.updateKakaoAtDelayCancelMsgGroupDataFlag", mjonMsgVO);

View File

@ -0,0 +1,22 @@
package itn.let.mjo.msgsent.service;
import java.util.List;
import itn.let.cmm.vo.FileInfoVO;
import itn.let.uss.umt.service.UserDefaultVO;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MjonMsgDetailSentDTO extends UserDefaultVO{
private static final long serialVersionUID = 1L;
private String userId;
private String callTo;
private String statusTxt;
}

View File

@ -65,7 +65,7 @@ public interface MjonMsgSentService {
public Map<String, Object> selectAllMsgSentDetailView(MjonMsgDetailSentVO mjonMsgDetailSentVO) throws Exception;
public List<MjonMsgDetailSentVO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO);
public List<MjonMsgDetailSentDTO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO);
public void msgSentExcelDownLoad(MjonMsgSentVO mjonMsgSentVO, HttpServletResponse response) throws IOException, Exception;

View File

@ -9,6 +9,7 @@ import egovframework.rte.psl.dataaccess.EgovAbstractDAO;
import itn.let.fax.addr.service.FaxAddrGroupVO;
import itn.let.mjo.addr.service.AddrGroupVO;
import itn.let.mjo.block.service.MjonBlockVO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentDTO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentVO;
import itn.let.mjo.msgsent.service.MjonMsgSWFDTO;
import itn.let.mjo.msgsent.service.MjonMsgSentVO;
@ -182,9 +183,9 @@ public class MjonMsgSentDAO extends EgovAbstractDAO {
return (MjonMsgDetailSentVO) select("MjonMsgSentDAO.selectAllMsgSentDetailView", mjonMsgDetailSentVO);
}
public List<MjonMsgDetailSentVO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO) {
public List<MjonMsgDetailSentDTO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO) {
return (List<MjonMsgDetailSentVO>) list("MjonMsgSentDAO.findByMsgDetailListAjax", mjonMsgDetailSentVO);
return (List<MjonMsgDetailSentDTO>) list("MjonMsgSentDAO.findByMsgDetailListAjax", mjonMsgDetailSentVO);
}
public List<String> findByReqDateWhereMsgGroupId(String msgGroupId) {

View File

@ -39,6 +39,7 @@ import itn.let.cmm.vo.FileInfoVO;
import itn.let.fax.addr.service.FaxAddrGroupVO;
import itn.let.mjo.addr.service.AddrGroupVO;
import itn.let.mjo.block.service.MjonBlockVO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentDTO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentVO;
import itn.let.mjo.msgsent.service.MjonMsgSWFDTO;
import itn.let.mjo.msgsent.service.MjonMsgSentService;
@ -474,9 +475,9 @@ public class MjonMsgSentServiceImpl extends EgovAbstractServiceImpl implements
}
@Override
public List<MjonMsgDetailSentVO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO) {
public List<MjonMsgDetailSentDTO> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO) {
List<MjonMsgDetailSentVO> list = mjonMsgSentDAO.findByMsgDetailListAjax(mjonMsgDetailSentVO);
List<MjonMsgDetailSentDTO> list = mjonMsgSentDAO.findByMsgDetailListAjax(mjonMsgDetailSentVO);
list.stream().forEach(t->{
t.setCallTo(StringUtil2.formatPhone(t.getCallTo()));
});

View File

@ -50,6 +50,7 @@ import itn.let.mjo.addr.service.AddrService;
import itn.let.mjo.addr.service.AddrVO;
import itn.let.mjo.apikey.service.ApiKeyMngService;
import itn.let.mjo.apikey.service.ApiKeyVO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentDTO;
import itn.let.mjo.msgsent.service.MjonMsgDetailSentVO;
import itn.let.mjo.msgsent.service.MjonMsgSentCntVO;
import itn.let.mjo.msgsent.service.MjonMsgSentService;
@ -191,7 +192,17 @@ private static final Logger logger = LoggerFactory.getLogger(MjonMsgSentControll
public ResponseEntity<StatusResponse> findByMsgDetailListAjax(MjonMsgDetailSentVO mjonMsgDetailSentVO) throws Exception {
List<MjonMsgDetailSentVO> resultList = mjonMsgSentService.findByMsgDetailListAjax(mjonMsgDetailSentVO);
List<MjonMsgDetailSentDTO> resultList = new ArrayList<>();
try {
resultList = mjonMsgSentService.findByMsgDetailListAjax(mjonMsgDetailSentVO);
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
log.info("resultList :: [{}]", resultList.size());
// resultList = resultList.subList(0, 275000);
// log.info("resultList :: [{}]", resultList.size());
return ResponseEntity.ok().body(new StatusResponse(HttpStatus.OK, "", resultList));

View File

@ -1,9 +1,12 @@
package itn.let.mjo.pay.service;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import itn.let.mjo.msg.service.MjonMsgVO;
public interface MjonPayService {
List<MjonPayVO> selectPayList(MjonPayVO mjonPayVO) throws Exception;
@ -140,4 +143,11 @@ public interface MjonPayService {
//누적 납부금액 조회 (후불회원이 사용금액을 납부한 금액 합산 - 미납 금액 제외한 합산 금액)
public String selectTotSumPaymentAfterPay(String userId) throws Exception;
Map<String, Object> payUserSWList(MjonPayVO mjonPayVO) throws Exception;
Map<String, Object> payUserSWListAjax(MjonMsgVO mjonMsgVO) throws Exception;
//거래명세서 상세 조회
MjonPayVO selectPayDetail(MjonPayVO mjonPayVO) throws Exception;
}

View File

@ -236,8 +236,16 @@ public class MjonPayVO extends ComDefaultVO{
private int remainPoint;
private String userData;
private String totChgPay; // 간편결제분류
// 거래명세서 내용
private String bizNo; // 사업자등록번호
private String managerNm; // 담당자명
private String prePaymentYn; // 선불결제여부 N:후불제고객
private String dept; // 회원종류 p:개인 c:기업
}

View File

@ -5,6 +5,7 @@ import java.util.List;
import org.springframework.stereotype.Repository;
import egovframework.rte.psl.dataaccess.EgovAbstractDAO;
import itn.let.kakao.kakaoComm.BizKakaoPriceVO;
import itn.let.mjo.pay.service.MjonPayVO;
import itn.let.mjo.pay.service.MjonVaMsgLogVO;
import itn.let.mjo.pay.service.RefundVO;
@ -45,6 +46,10 @@ public class MjonPayDAO extends EgovAbstractDAO {
public MjonPayVO selectCashVO(MjonPayVO mjonPayVO) throws Exception{
return (MjonPayVO)select("mjonPayDAO.selectCashVO", mjonPayVO);
}
public BizKakaoPriceVO selectBizKakaoPrice(String msgGroupId) throws Exception{
return (BizKakaoPriceVO)select("mjonPayDAO.selectBizKakaoPrice", msgGroupId);
}
public void insertCash(MjonPayVO mjonPayVO) throws Exception{
@ -353,5 +358,8 @@ public class MjonPayDAO extends EgovAbstractDAO {
return result;
}
public MjonPayVO selectPayDetail(MjonPayVO mjonPayVO) throws Exception{
return (MjonPayVO)select("mjonPayDAO.selectPayDetail", mjonPayVO);
}
}

View File

@ -7,11 +7,16 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@ -25,11 +30,15 @@ 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.util.DateUtils;
import itn.com.cmm.util.MJUtil;
import itn.com.cmm.util.PayUtils;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.mjo.event.service.MjonEventVO;
import itn.let.mjo.event.service.impl.MjonEventDAO;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msgcampain.service.MjonCandidateVO;
import itn.let.mjo.msgcampain.service.impl.MjonCandidateDAO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.msgdata.service.impl.MjonMsgDataDAO;
import itn.let.mjo.pay.service.MjonPayService;
@ -94,6 +103,10 @@ public class MjonPayServiceImpl extends EgovAbstractServiceImpl implements MjonP
@Resource(name = "mberGrdService")
MberGrdService mberGrdService;
@Resource(name="mjonCandidateDAO")
private MjonCandidateDAO mjonCandidateDAO;
@Override
public List<MjonPayVO> selectPayList(MjonPayVO mjonPayVO) throws Exception {
return mjonPayDAO.selectPayList(mjonPayVO);
@ -2839,6 +2852,144 @@ public class MjonPayServiceImpl extends EgovAbstractServiceImpl implements MjonP
}
@Override
public Map<String, Object> payUserSWList(MjonPayVO mjonPayVO) throws Exception{
String userId = mjonPayVO.getUserId();
// 사용금액
List<MjonPayVO> usedCashTotList = mjonPayDAO.selectUsedCashWithKakaoTotCnt(mjonPayVO);
// 사용가능한 금액
// mberManageVO.prePaymentYn 선불 후불 회원 구분으로 인해 select함
MberManageVO mberManageVO = mjonMsgDataDAO.selectMberManageInfo(userId);
// 선거 후보자 정보 조회
MjonCandidateVO mjonCandidateVO = new MjonCandidateVO();
if("p".equals(mberManageVO.getDept())) { //개인회원 선거 후보자 정보 불러오기
mjonCandidateVO = mjonCandidateDAO.selectCandidateDataInfo(userId);
if(mjonCandidateVO != null) {
mjonCandidateVO.setRegidentNo1(egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo1()));
mjonCandidateVO.setRegidentNo2(egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo2()));
}
}
/**
* 후불제 회원 관련 사용 요금 내역 정보 조회하기
* 20231228 우영두 추가
* 누적사용금액, 누적 납부금액, 당월 납부 예상금액 정보 조회
*
* */
//누적 사용금액 조회 (캐시 테이블에서 현재까지 사용된 금액 합산 - 캐시 테이블에서 "-" 사용된 금액만 합산)
String totSumCashAfterPay = mjonPayDAO.selectTotalSumCashForAfterPay(userId);
//누적 사용 포인트 조회 (포인트 테이블에서 현재까지 사용된 포인트 합산 - 회원 포인트 정보 업데이트시 사용되는 쿼리 이용)
String totSumPointAfterPay = mjonPayDAO.selectTotalSumPointForAfterPay(userId);
//누적 납부금액 조회 (후불회원이 사용금액을 납부한 금액 합산 - 미납 금액 제외한 합산 금액)
String totSumPaymentAfterPay = mjonPayDAO.selectTotSumPaymentAfterPay(userId);
//누적 납부 포인트 조회 ( 누적 납부금액 합산에 대한 2% 포인트 정보 계산)
float p_i_re_point = 0;
JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo();
if (sysJoinSetVO != null) {
p_i_re_point = sysJoinSetVO.getPointPer();
}
int paymentPointAfterPay = Math.round((Float.parseFloat(totSumPaymentAfterPay) * p_i_re_point / 100));
//당월 납부 예상금액 (누적 사용금액 합산 - 누적 납부금액 합산 정보 계산)
float unPaymentAfterPay = Float.parseFloat(totSumCashAfterPay) - Float.parseFloat(totSumPaymentAfterPay);
//당월 납부 예상 포인트 (당월 납부 예상 금액에 대한 2% 포인트 정보 계산)
int unPaymentPointAfterPay = Math.round((unPaymentAfterPay * p_i_re_point / 100));
/*
* 2024.02.06 후불제 회원 협의단가를 사용하는 회원은 포인트 적립이 되지 않아야함.
* 후불제 협의 단가 여부 체크
* 모든 협의 단가 금액을 합산하여 0보다 크면 협의단가 있음.
* */
float shortPrice = mberManageVO.getShortPrice();
float longPrice = mberManageVO.getLongPrice();
float picturePrice = mberManageVO.getPicturePrice() + mberManageVO.getPicture2Price() + mberManageVO.getPicture3Price();
float kakaoAtPrice = mberManageVO.getKakaoAtPrice();
float kakaoFtPrice = mberManageVO.getKakaoFtPrice();
float totPrice = shortPrice + longPrice + picturePrice + kakaoAtPrice + kakaoFtPrice;
String negoPriceYn = "N";
if(totPrice > 0) {
negoPriceYn = "Y";
}
Map<String, Object> returnData = new HashMap<>();
returnData.put("usedCashTotList", usedCashTotList);
returnData.put("mberManageVO", mberManageVO);
returnData.put("mjonCandidateVO", mjonCandidateVO);
returnData.put("totSumCashAfterPay", totSumCashAfterPay);
returnData.put("totSumPointAfterPay", totSumPointAfterPay);
returnData.put("totSumPaymentAfterPay", totSumPaymentAfterPay);
returnData.put("sumPaymentPointAfterPay", paymentPointAfterPay);
returnData.put("unPaymentAfterPay", unPaymentAfterPay);
returnData.put("unPaymentPointAfterPay", unPaymentPointAfterPay);
returnData.put("negoPriceYn", negoPriceYn);
// 초기 날짜 셋팅
returnData.put("startDate", DateUtils.getDateMonthsAgo(1));
returnData.put("endDate", DateUtils.getCurrentDate());
// TODO Auto-generated method stub
return returnData;
}
@Override
public Map<String, Object> payUserSWListAjax(MjonMsgVO mjonMsgVO) throws Exception{
if("".equals(mjonMsgVO.getSearchSortCnd())){ //최초조회시 최신것 조회List
mjonMsgVO.setSearchSortCnd("regDate");
mjonMsgVO.setSearchSortOrd("desc");
}
Map<String, Object> returnData = new HashMap<>();
// 검색 데이터가 없거나
// 시작일자가 종료일자보다 이후이거나
// 기간이 365일이 넘으면 현재일부터 365일 날짜를 넣어서 검색
if(!DateUtils.dateChkAndValueChk(mjonMsgVO.getStartDate(),mjonMsgVO.getEndDate(), 12 )) {
mjonMsgVO.setStartDate(DateUtils.getDateMonthsAgo(12));
mjonMsgVO.setEndDate(DateUtils.getCurrentDate());
};
List<MjonMsgVO> payUserSWList = mjonMsgDataDAO.selectPayUserSWList(mjonMsgVO);
returnData.put("payUserSWList", payUserSWList);
returnData.put("totCnt", payUserSWList.size()> 0 ? payUserSWList.get(0).getTotCnt() : 0);
returnData.put("totSuccSendPrice", payUserSWList.size() > 0 ? PayUtils.getTrimToFirstDecimal(payUserSWList.get(0).getTotSuccSendPrice()) : 0);
return returnData;
}
@Override
public MjonPayVO selectPayDetail(MjonPayVO mjonPayVO) throws Exception {
MjonPayVO result = mjonPayDAO.selectPayDetail(mjonPayVO);
/* 후불제 고객의 사용기한 조회(결제일의 전달 1일 ~ 말일) */
if("N".equals(result.getPrePaymentYn())) {
String regDateStr = result.getRegDate();
LocalDateTime regDate = Timestamp.valueOf(regDateStr).toLocalDateTime();
LocalDate lastMonth = regDate.toLocalDate().withDayOfMonth(1).minusMonths(1);
LocalDate startDate = lastMonth.withDayOfMonth(1);
LocalDate endDate = lastMonth.withDayOfMonth(lastMonth.lengthOfMonth());
result.setStartDate(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
result.setEndDate(endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
return result;
}
}

View File

@ -2603,15 +2603,16 @@ public class MjonPayController {
* 2023.12.22 우영두
* @param mjonMsgVO
* @param model
* @return "/web/member/pay/PayUserSWList.do"
* @return "/web/member/pay/payUserSWList.do"
* @throws Exception
*/
@RequestMapping(value= {"/web/member/pay/PayUserSWList.do"})
public String PayUserSWList(@ModelAttribute("mjonMsgVO") MjonMsgVO mjonMsgVO,
@RequestMapping(value= {"/web/member/pay/payUserSWList.do"})
public String payUserSWList(@ModelAttribute("mjonMsgVO") MjonMsgVO mjonMsgVO,
MjonPayVO mjonPayVO,
MberManageVO mberManageVO, RedirectAttributes redirectAttributes,
HttpServletRequest request,
ModelMap model) throws Exception{
/*LoginVO loginVO = (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser();*/
LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
@ -2621,117 +2622,26 @@ public class MjonPayController {
return "redirect:/web/user/login/login.do";
}
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
mjonMsgVO.setUserId(userId);
/*
{ // 충전캐시
String sumPayMoney = mjonPayService.selectAgentSumPayMoney(userId);
model.addAttribute("sumPayMoney", sumPayMoney);
}
mjonPayVO.setUserId(userId);
{ // 충전포인트
String sumPoint = mjonPayService.selectSumPoint(userId);
model.addAttribute("sumPoint", sumPoint);
}
*/
{ // 사용금액
mjonPayVO.setUserId(userId);
List<MjonPayVO> usedCashTotList = mjonPayService.selectUsedCashWithKakaoTotCnt(mjonPayVO);
model.addAttribute("usedCashTotList", usedCashTotList);
}
{ // 사용가능한 금액
// mberManageVO.prePaymentYn 선불 후불 회원 구분으로 인해 select함
mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
model.addAttribute("mberManageVO", mberManageVO);
}
/*
{ // 발송건수
mjonMsgVO.setReserveYn("N");
List<MjonMsgVO> sendTotList = mjonMsgService.selectWithKakaoSendTotCnt(mjonMsgVO);
model.addAttribute("sendTotList", sendTotList);
}
{ // 예약건수
mjonMsgVO.setReserveYn("Y");
List<MjonMsgVO> reservToList = mjonMsgService.selectWithKakaoSendTotCnt(mjonMsgVO);
model.addAttribute("reservToList", reservToList);
}
*/
{// 선거 후보자 정보 조회
MjonCandidateVO mjonCandidateVO = new MjonCandidateVO();
if("p".equals(mberManageVO.getDept())) { //개인회원 선거 후보자 정보 불러오기
mjonCandidateVO = mjonCandidateService.selectCandidateDataInfo(userId);
if(mjonCandidateVO != null) {
mjonCandidateVO.setRegidentNo1(egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo1()));
mjonCandidateVO.setRegidentNo2(egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo2()));
}
}
model.addAttribute("mjonCandidateVO", mjonCandidateVO);
}
{
/**
* 후불제 회원 관련 사용 요금 내역 정보 조회하기
* 20231228 우영두 추가
* 누적사용금액, 누적 납부금액, 당월 납부 예상금액 정보 조회
*
* */
//누적 사용금액 조회 (캐시 테이블에서 현재까지 사용된 금액 합산 - 캐시 테이블에서 "-" 사용된 금액만 합산)
String totSumCashAfterPay = mjonPayService.selectTotalSumCashForAfterPay(userId);
model.addAttribute("totSumCashAfterPay", totSumCashAfterPay);
//누적 사용 포인트 조회 (포인트 테이블에서 현재까지 사용된 포인트 합산 - 회원 포인트 정보 업데이트시 사용되는 쿼리 이용)
String totSumPointAfterPay = mjonPayService.selectTotalSumPointForAfterPay(userId);
model.addAttribute("totSumPointAfterPay", totSumPointAfterPay);
//누적 납부금액 조회 (후불회원이 사용금액을 납부한 금액 합산 - 미납 금액 제외한 합산 금액)
String totSumPaymentAfterPay = mjonPayService.selectTotSumPaymentAfterPay(userId);
model.addAttribute("totSumPaymentAfterPay", totSumPaymentAfterPay);
//누적 납부 포인트 조회 ( 누적 납부금액 합산에 대한 2% 포인트 정보 계산)
float p_i_re_point = 0;
JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo();
if (sysJoinSetVO != null) {
p_i_re_point = sysJoinSetVO.getPointPer();
}
int paymentPointAfterPay = Math.round((Float.parseFloat(totSumPaymentAfterPay) * p_i_re_point / 100));
model.addAttribute("sumPaymentPointAfterPay", paymentPointAfterPay);
//당월 납부 예상금액 (누적 사용금액 합산 - 누적 납부금액 합산 정보 계산)
float unPaymentAfterPay = Float.parseFloat(totSumCashAfterPay) - Float.parseFloat(totSumPaymentAfterPay);
model.addAttribute("unPaymentAfterPay", unPaymentAfterPay);
//당월 납부 예상 포인트 (당월 납부 예상 금액에 대한 2% 포인트 정보 계산)
int unPaymentPointAfterPay = Math.round((unPaymentAfterPay * p_i_re_point / 100));
model.addAttribute("unPaymentPointAfterPay", unPaymentPointAfterPay);
/*
* 2024.02.06 후불제 회원 협의단가를 사용하는 회원은 포인트 적립이 되지 않아야함.
* 후불제 협의 단가 여부 체크
* 모든 협의 단가 금액을 합산하여 0보다 크면 협의단가 있음.
* */
float shortPrice = mberManageVO.getShortPrice();
float longPrice = mberManageVO.getLongPrice();
float picturePrice = mberManageVO.getPicturePrice() + mberManageVO.getPicture2Price() + mberManageVO.getPicture3Price();
float kakaoAtPrice = mberManageVO.getKakaoAtPrice();
float kakaoFtPrice = mberManageVO.getKakaoFtPrice();
float totPrice = shortPrice + longPrice + picturePrice + kakaoAtPrice + kakaoFtPrice;
String negoPriceYn = "N";
if(totPrice > 0) {
negoPriceYn = "Y";
}
model.addAttribute("negoPriceYn", negoPriceYn);
}
{
// 초기 날짜 셋팅
model.addAttribute("startDate", DateUtils.getDateMonthsAgo(12));
model.addAttribute("endDate", DateUtils.getCurrentDate());
}
// // 비즈니스 로직 부분
Map<String, Object> resultMap = mjonPayService.payUserSWList(mjonPayVO);
model.addAttribute("usedCashTotList", resultMap.get("usedCashTotList"));
model.addAttribute("mjonCandidateVO", resultMap.get("mjonCandidateVO"));
model.addAttribute("mberManageVO", resultMap.get("mberManageVO"));
model.addAttribute("totSumCashAfterPay", resultMap.get("totSumCashAfterPay"));
model.addAttribute("totSumPointAfterPay", resultMap.get("totSumPointAfterPay"));
model.addAttribute("totSumPaymentAfterPay", resultMap.get("totSumPaymentAfterPay"));
model.addAttribute("sumPaymentPointAfterPay", resultMap.get("sumPaymentPointAfterPay"));
model.addAttribute("unPaymentAfterPay", resultMap.get("unPaymentAfterPay"));
model.addAttribute("unPaymentPointAfterPay", resultMap.get("unPaymentPointAfterPay"));
model.addAttribute("negoPriceYn", resultMap.get("negoPriceYn"));
model.addAttribute("startDate", resultMap.get("startDate"));
model.addAttribute("endDate", resultMap.get("endDate"));
return "/web/pay/PayUserSWList";
}
@ -2749,8 +2659,8 @@ public class MjonPayController {
* @return "/web/member/pay/PayUserSWListAjax.do"
* @throws Exception
*/
@RequestMapping(value= {"/web/member/pay/PayUserSWListAjax.do"})
public String PayUserSWListAjax(@ModelAttribute("searchVO") MjonMsgVO mjonMsgVO,
@RequestMapping(value= {"/web/member/pay/payUserSWListAjax.do"})
public String payUserSWListAjax(@ModelAttribute("searchVO") MjonMsgVO mjonMsgVO,
HttpServletRequest request,
ModelMap model) throws Exception{
@ -2774,29 +2684,12 @@ public class MjonPayController {
mjonMsgVO.setLastIndex(paginationInfo.getLastRecordIndex());
mjonMsgVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
if("".equals(mjonMsgVO.getSearchSortCnd())){ //최초조회시 최신것 조회List
mjonMsgVO.setSearchSortCnd("regDate");
mjonMsgVO.setSearchSortOrd("desc");
}
Map<String, Object> resultMap = mjonPayService.payUserSWListAjax(mjonMsgVO);
// 검색 데이터가 없거나
// 시작일자가 종료일자보다 이후이거나
// 기간이 365일이 넘으면 현재일부터 365일 날짜를 넣어서 검색
if(!DateUtils.dateChkAndValueChk(mjonMsgVO.getStartDate(),mjonMsgVO.getEndDate(), 12 )) {
mjonMsgVO.setStartDate(DateUtils.getDateMonthsAgo(12));
mjonMsgVO.setEndDate(DateUtils.getCurrentDate());
};
List<MjonMsgVO> payUserSWList = mjonMsgDataService.selectPayUserSWList(mjonMsgVO);
paginationInfo.setTotalRecordCount(payUserSWList.size()> 0 ? payUserSWList.get(0).getTotCnt() : 0);
paginationInfo.setTotalRecordCount((int)resultMap.get("totCnt"));
model.addAttribute("paginationInfo", paginationInfo);
model.addAttribute("payUserSWList", payUserSWList);
model.addAttribute("totSuccSendPrice", payUserSWList.size() > 0 ? PayUtils.getTrimToFirstDecimal(payUserSWList.get(0).getTotSuccSendPrice()) : 0);
model.addAttribute("payUserSWList", resultMap.get("payUserSWList"));
model.addAttribute("totSuccSendPrice", resultMap.get("totSuccSendPrice"));
model.addAttribute("mjonMsgVO", mjonMsgVO);
@ -2878,7 +2771,7 @@ public class MjonPayController {
font.setBoldweight(Font.BOLDWEIGHT_BOLD); //글씨 bold
sheet.setColumnWidth(1, 5000); // 칼럼의 조절
sheet.setColumnWidth(4, 10000); // 칼럼의 조절
sheet.setColumnWidth(3, 10000); // 칼럼의 조절
try{
@ -2903,6 +2796,7 @@ public class MjonPayController {
sheet.addMergedRegion(new CellRangeAddress(0,1,1,1)); //셀병합
sheet.addMergedRegion(new CellRangeAddress(0,1,2,2)); //셀병합
sheet.addMergedRegion(new CellRangeAddress(0,1,3,3)); //셀병합
sheet.addMergedRegion(new CellRangeAddress(0,1,6,6)); //셀병합
cell = row.createCell(0);
@ -2910,46 +2804,29 @@ public class MjonPayController {
cell.setCellStyle(style);
cell = row.createCell(1);
cell.setCellValue("날짜");
cell.setCellValue("발송일시");
cell.setCellStyle(style);
cell = row.createCell(2);
cell.setCellValue("문자유");
cell.setCellValue("");
cell.setCellStyle(style);
cell = row.createCell(3);
cell.setCellValue("발송건수");
cell.setCellStyle(style);
cell = row.createCell(4);
cell.setCellValue("내용");
cell.setCellStyle(style);
/*cell = row.createCell(5);
cell.setCellValue("충전");
sheet.addMergedRegion(new CellRangeAddress(0,0,5,6)); //셀병합
cell = row.createCell(4);
cell.setCellValue("발송건수");
sheet.addMergedRegion(new CellRangeAddress(0,0,4,5)); //셀병합
cell.setCellStyle(style);
cell = row.createCell(6);
cell.setCellStyle(style);*/
cell = row.createCell(5);
cell.setCellValue("사용");
sheet.addMergedRegion(new CellRangeAddress(0,0,5,6)); //셀병합
cell.setCellStyle(style);
cell = row.createCell(6);
cell.setCellValue("금액(원)");
cell.setCellStyle(style);
/*cell = row.createCell(9);
cell.setCellValue("잔액");
sheet.addMergedRegion(new CellRangeAddress(0,0,9,10)); //셀병합
cell.setCellStyle(style);
cell = row.createCell(10);
cell.setCellStyle(style);*/
row = sheet.createRow(1);
cell = row.createCell(0);
@ -2965,32 +2842,16 @@ public class MjonPayController {
cell.setCellStyle(style);
cell = row.createCell(4);
cell.setCellValue("성공");
cell.setCellStyle(style);
/*cell = row.createCell(5);
cell.setCellValue("충전금");
cell.setCellStyle(style);
cell = row.createCell(6);
cell.setCellValue("포인트");
cell.setCellStyle(style);*/
cell = row.createCell(5);
cell.setCellValue("충전금");
cell.setCellValue("실패");
cell.setCellStyle(style);
cell = row.createCell(6);
cell.setCellValue("포인트");
cell.setCellStyle(style);
/*cell = row.createCell(9);
cell.setCellValue("충전금");
cell.setCellStyle(style);
cell = row.createCell(10);
cell.setCellValue("포인트");
cell.setCellStyle(style);*/
DecimalFormat formatter = new DecimalFormat("###,###.##");
String befCash = "";
String befPoint = "";
@ -3033,15 +2894,11 @@ public class MjonPayController {
if(j==0) cell.setCellValue(i+1); //번호
if(j==1) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getRegDate()); //결제일시
if(j==2) cell.setCellValue(msgType); //문자유형
if(j==3) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSuccSendCnt()); //발송건수
if(j==4) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSmsTxt()); //내용
if(j==5) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSuccSendPrice()); //충전 - 충전금
if(j==6) cell.setCellValue(0); //충전 - 포인트
/*if(j==7) cell.setCellValue(totPrice); //사용 - 충전금
if(j==8) cell.setCellValue(0); //사용 - 포인트
if(j==9) cell.setCellValue(thisPoint); //잔액 - 충전금
if(j==10) cell.setCellValue(befPoint); //잔액 - 포인트
*/ }
if(j==3) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSmsTxt()); //내용
if(j==4) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSuccSendCnt()); //성공건수
if(j==5) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getFailSendCnt()); //실패건수
if(j==6) cell.setCellValue(((MjonMsgVO)payUserList.get(i)).getSuccSendPrice()); //금액
}
}
}
response.setHeader("Set-Cookie", "fileDownload=true; path=/");
@ -5051,28 +4908,11 @@ public class MjonPayController {
model.addAttribute("resultList", payUserSumList);
// 수신자 정보
String mberNm = ""; // 회사명
String managerNm = ""; // 담당자명
String moblphonNo = ""; // 연락처
MberManageVO mberManageVO = new MberManageVO();
mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
if (mberManageVO != null) {
// 회원종류 p-개인 c-기업
if (mberManageVO.getDept().equals("c")) {
mberNm = mberManageVO.getMberNm();
managerNm = mberManageVO.getManagerNm();
moblphonNo = mberManageVO.getMoblphonNo();
}
else {
mberNm = mberManageVO.getMberNm();
managerNm = mberManageVO.getMberNm();
moblphonNo = mberManageVO.getMoblphonNo();
}
}
model.addAttribute("mberNm", mberNm);
model.addAttribute("managerNm", managerNm);
model.addAttribute("moblphonNo", moblphonNo);
MJUtil mjUtil = new MJUtil();
MberManageVO mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
mberManageVO.setMoblphonNo(mjUtil.addDash(mberManageVO.getMoblphonNo()));
mberManageVO.setBizNo(mjUtil.bizNoAddDash(mberManageVO.getBizNo()));
model.addAttribute("mberManageVO", mberManageVO);
//부가세 포함 가격 정보 계산
double addTax = Math.round(totalSumPrice * 0.1);
@ -6190,7 +6030,42 @@ public class MjonPayController {
return "/uss/ion/pay/cashPointSendList";
}
/**
* * 거래명세서 팝업
* @param searchVO
* @param model
* @return "/web/member/pay/payInvoicePopupAjax.do"
* @throws Exception
*/
@RequestMapping(value= {"/web/member/pay/payInvoicePopupAjax.do"})
public String printInvoiceAjax(
@ModelAttribute("searchVO") MjonPayVO mjonPayVO
, RedirectAttributes redirectAttributes
, ModelMap model) throws Exception {
//로그인 권한정보 불러오기
LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
if(loginVO == null) {
//redirectAttributes.addFlashAttribute("message", "문자온 서비스는 로그인 후 이용 가능합니다.");
return "redirect:/web/user/login/login.do";
}
mjonPayVO.setUserId(userId);
//결제 정보 불러오기
MJUtil mjUtil = new MJUtil();
MjonPayVO result = mjonPayService.selectPayDetail(mjonPayVO);
result.setMbtlNum(mjUtil.addDash(result.getMbtlNum()));
result.setBizNo(mjUtil.bizNoAddDash(result.getBizNo()));
model.addAttribute("result", result);
return "web/pay/payInvoicePrintPopup";
}
/**
* @param p_pattern
* @param p_mjonPayVO

View File

@ -278,6 +278,8 @@ public class MjonPayV2Controller {
try {
// 다음 결제시 결제수단 SELECT
nextPayMethod = userManageService.selectNextPayMethod(userId);
// 실제 마지막 결제 방식 -
}
catch(Exception e) {
isSuccess = false;
@ -1640,6 +1642,45 @@ public class MjonPayV2Controller {
return "web/cop/kgmV2/bankOkUrl";
}
/**
* 마지막 결제수단 SELECT
* @throws Exception
*/
@RequestMapping(value = "/web/member/pay/selectLastPayMethodAjax.do")
public ModelAndView selectLastPayMethodAjax(MjonPayVO mjonPayVO,
HttpServletRequest request ) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("jsonView");
boolean isSuccess = true;
String msg = "";
String nextPayMethod = "";
LoginVO loginVO = (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser();
String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
if(userId == null) {
isSuccess = false;
msg = "로그인이 필요합니다.";
}
try {
// 다음 결제시 결제수단 SELECT
nextPayMethod = userManageService.selectLastPayMethod(userId);
}
catch(Exception e) {
isSuccess = false;
msg = e.getMessage();
}
modelAndView.addObject("isSuccess", isSuccess);
modelAndView.addObject("msg", msg);
modelAndView.addObject("nextPayMethod", nextPayMethod);
return modelAndView;
}
// Get Server Path
public static String getKgServerPath(HttpServletRequest request) {
String kgmPath = request.getScheme() + "://" + request.getServerName() +":" + request.getServerPort();

View File

@ -5,18 +5,27 @@ import java.math.RoundingMode;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import egovframework.rte.fdl.cmmn.exception.FdlException;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
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.impl.KakaoAlimTalkDAO;
import itn.let.mjo.event.service.MjonEventService;
import itn.let.mjo.event.service.MjonEventVO;
import itn.let.mjo.event.service.impl.MjonEventDAO;
import itn.let.mjo.msg.service.MjonMsgVO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.msgdata.service.impl.MjonMsgDataDAO;
import itn.let.mjo.pay.service.MjonPayVO;
import itn.let.mjo.pay.service.impl.MjonPayDAO;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.uss.umt.service.MberManageVO;
import lombok.extern.slf4j.Slf4j;
/**
*
@ -32,6 +41,7 @@ import itn.let.uss.umt.service.MberManageVO;
*
*
*/
@Slf4j
@Component
public class PriceAndPoint {
@ -46,6 +56,11 @@ public class PriceAndPoint {
@Resource(name = "egovMjonCashIdGnrService")
private EgovIdGnrService idgenMjonCashId;
@Resource(name="kakaoAlimTalkDAO")
private KakaoAlimTalkDAO kakaoAlimTalkDAO;
/**
* @methodName : getBefCash
@ -114,19 +129,90 @@ public class PriceAndPoint {
, String msgGroupId
) throws Exception {
MjonPayVO mjonPayVO = new MjonPayVO();
mjonPayVO.setCashId(idgenMjonCashId.getNextStringId());
mjonPayVO.setUserId(userId);
System.out.println(" + totPrice :: "+ totPrice);
mjonPayVO.setCash(totPrice);
mjonPayVO.setFrstRegisterId(userId);
mjonPayVO.setMemo(memo);
mjonPayVO.setMsgGroupId(msgGroupId);
// MjonPayVO mjonPayVO = new MjonPayVO();
// mjonPayVO.setCashId(idgenMjonCashId.getNextStringId());
// mjonPayVO.setUserId(userId);
// System.out.println(" + totPrice :: "+ totPrice);
// mjonPayVO.setCash(totPrice);
// mjonPayVO.setFrstRegisterId(userId);
// mjonPayVO.setMemo(memo);
// mjonPayVO.setMsgGroupId(msgGroupId);
insertCashAndPoint(userId, totPrice, memo, msgGroupId, null);
// mjonPayDAO.insertCash(mjonPayVO); //캐시
// mjonPayDAO.updateMemberCash(mjonPayVO); //회원정보 업데이트
}
/**
* @methodName : insertCashAndPoint
* @author : 이호영
* @date : 2025. 7. 17.
* @description : insertCashAndPoint 에서 환불으로 인해 userData 추가
* @return : void
* @param userId
* @param totPrice
* @param memo
* @param msgGroupId
* @param userData
* @throws Exception
*
*/
public void insertCashAndPoint(
String userId
, float totPrice
, String memo
, String msgGroupId
, String userData
) throws Exception {
MjonPayVO mjonPayVO = buildPayVO(userId, totPrice, memo, msgGroupId);
// 환불로 인해 userData가 추후 사용될 경우 여기에 처리
if (StringUtils.isNotEmpty(userData)) { mjonPayVO.setOrderId(userData); }
mjonPayDAO.insertCash(mjonPayVO); //캐시
mjonPayDAO.updateMemberCash(mjonPayVO); //회원정보 업데이트
}
private MjonPayVO buildPayVO(String userId, float totPrice, String memo, String msgGroupId) throws FdlException {
MjonPayVO vo = new MjonPayVO();
vo.setCashId(idgenMjonCashId.getNextStringId());
vo.setUserId(userId);
vo.setCash(totPrice);
vo.setFrstRegisterId(userId);
vo.setMemo(memo);
vo.setMsgGroupId(msgGroupId);
System.out.println(" + totPrice :: " + totPrice);
return vo;
}
public void insertBizFtKakaoPrice(String userId, String msgGroupId) throws Exception {
KakaoVO kakaoVO = new KakaoVO();
System.out.println("=======================");
// 사용자 개인 단가 정보 불러오기
MberManageVO mberManageVO = mjonMsgDataDAO.selectMberManageInfo(userId);
// 시스템 기본 단가 정보 불러오기
JoinSettingVO sysJoinSetVO = mjonMsgDataDAO.selectJoinSettingInfo();
KakaoSendUtil.getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice());
// TODO Auto-generated method stub
kakaoVO.setMsgGroupId(msgGroupId);
kakaoVO.setSmsPrice(KakaoSendUtil.getValidPrice(mberManageVO.getShortPrice(), sysJoinSetVO.getShortPrice()));
kakaoVO.setMmsPrice(KakaoSendUtil.getValidPrice(mberManageVO.getLongPrice(), sysJoinSetVO.getLongPrice()));
kakaoVO.setPicturePrice(KakaoSendUtil.getValidPrice(mberManageVO.getPicturePrice(), sysJoinSetVO.getPicturePrice()));
kakaoVO.setKakaoFtPrice(KakaoSendUtil.getValidPrice(mberManageVO.getKakaoFtPrice(), sysJoinSetVO.getKakaoFtPrice()));
kakaoVO.setKakaoFtImgPrice(KakaoSendUtil.getValidPrice(mberManageVO.getKakaoFtImgPrice(), sysJoinSetVO.getKakaoFtImgPrice()));
kakaoVO.setKakaoFtWideImgPrice(KakaoSendUtil.getValidPrice(mberManageVO.getKakaoFtWideImgPrice(), sysJoinSetVO.getKakaoFtWideImgPrice()));
kakaoAlimTalkDAO.insertKakaoSendPrice(kakaoVO);
}
}

View File

@ -444,7 +444,7 @@ public class SchdlrManageServiceImpl extends EgovAbstractServiceImpl implements
kakaoAlimTalkService.selectKakaoAtSentRefundList();
// 카카오 친구톡 환불 처리
// kakaoAlimTalkService.selectKakaoFtSentRefundList();
kakaoAlimTalkService.selectKakaoFtSentRefundList();
}

View File

@ -1,5 +1,12 @@
package itn.let.sym.site.service;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
/**
* 로그인정책에 대한 VO 클래스를 정의한다.
* 로그인정책정보의 목록 항목을 관리한다.
@ -18,13 +25,18 @@ package itn.let.sym.site.service;
*
* </pre>
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class JoinSettingVO {
/**
* serialVersionUID
*/
@SuppressWarnings("unused")
private static final long serialVersionUID = 1L;
private float shortPrice; // 단문 단가
private float longPrice; //장문 단가
@ -37,6 +49,9 @@ public class JoinSettingVO {
private float customTextPrice; // 텍스트 단순수정
private float kakaoAtPrice; // 카카오 알림톡 단가
private float kakaoFtPrice; // 카카오 친구톡 단가
private float kakaoFtImgPrice; // 카카오 친구톡 이미지 단가
private float kakaoFtWideImgPrice; // 카카오 친구톡 와이드 단가
private float faxPrice; // 팩스 단가
private float refundPer; //환불 비율
@ -51,188 +66,5 @@ public class JoinSettingVO {
private String smishingNoti; //첫결제(카드제외) 스미싱의심 알림 여부
private String holiSmishingNoti; //야간 스미싱알림 여부
public String getSmishingNoti() {
return smishingNoti;
}
public void setSmishingNoti(String smishingNoti) {
this.smishingNoti = smishingNoti;
}
public float getShortPrice() {
return shortPrice;
}
public void setShortPrice(float shortPrice) {
this.shortPrice = shortPrice;
}
public float getLongPrice() {
return longPrice;
}
public void setLongPrice(float longPrice) {
this.longPrice = longPrice;
}
public float getPicturePrice() {
return picturePrice;
}
public void setPicturePrice(float picturePrice) {
this.picturePrice = picturePrice;
}
public float getPicture2Price() {
return picture2Price;
}
public void setPicture2Price(float picture2Price) {
this.picture2Price = picture2Price;
}
public float getPicture3Price() {
return picture3Price;
}
public void setPicture3Price(float picture3Price) {
this.picture3Price = picture3Price;
}
public float getCustomSamplePrice() {
return customSamplePrice;
}
public void setCustomSamplePrice(float customSamplePrice) {
this.customSamplePrice = customSamplePrice;
}
public float getCustomEditPrice() {
return customEditPrice;
}
public void setCustomEditPrice(float customEditPrice) {
this.customEditPrice = customEditPrice;
}
public float getCustomEdit3Price() {
return customEdit3Price;
}
public void setCustomEdit3Price(float customEdit3Price) {
this.customEdit3Price = customEdit3Price;
}
public float getCustomTextPrice() {
return customTextPrice;
}
public void setCustomTextPrice(float customTextPrice) {
this.customTextPrice = customTextPrice;
}
public float getRefundPer() {
return refundPer;
}
public void setRefundPer(float refundPer) {
this.refundPer = refundPer;
}
public float getJoinCash() {
return joinCash;
}
public void setJoinCash(float joinCash) {
this.joinCash = joinCash;
}
public float getPointPer() {
return pointPer;
}
public void setPointPer(float pointPer) {
this.pointPer = pointPer;
}
public String getLasUpdusrId() {
return lasUpdusrId;
}
public void setLasUpdusrId(String lasUpdusrId) {
this.lasUpdusrId = lasUpdusrId;
}
public String getLastUpdtPnttm() {
return lastUpdtPnttm;
}
public void setLastUpdtPnttm(String lastUpdtPnttm) {
this.lastUpdtPnttm = lastUpdtPnttm;
}
public String getJoinCertType() {
return joinCertType;
}
public void setJoinCertType(String joinCertType) {
this.joinCertType = joinCertType;
}
public String getSmsNoti() {
return smsNoti;
}
public void setSmsNoti(String smsNoti) {
this.smsNoti = smsNoti;
}
public String getEmailNoti() {
return emailNoti;
}
public void setEmailNoti(String emailNoti) {
this.emailNoti = emailNoti;
}
public String getSlackNoti() {
return slackNoti;
}
public void setSlackNoti(String slackNoti) {
this.slackNoti = slackNoti;
}
public float getKakaoAtPrice() {
return kakaoAtPrice;
}
public void setKakaoAtPrice(float kakaoAtPrice) {
this.kakaoAtPrice = kakaoAtPrice;
}
public float getKakaoFtPrice() {
return kakaoFtPrice;
}
public void setKakaoFtPrice(float kakaoFtPrice) {
this.kakaoFtPrice = kakaoFtPrice;
}
public float getFaxPrice() {
return faxPrice;
}
public void setFaxPrice(float faxPrice) {
this.faxPrice = faxPrice;
}
public String getHoliSmishingNoti() {
return holiSmishingNoti;
}
public void setHoliSmishingNoti(String holiSmishingNoti) {
this.holiSmishingNoti = holiSmishingNoti;
}
}

View File

@ -1,5 +1,10 @@
package itn.let.uat.uia.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import javax.annotation.Resource;
@ -11,14 +16,16 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import itn.com.cmm.util.StringUtil;
import itn.com.uss.olh.hpc.service.HackIpService;
import itn.com.uss.olh.hpc.service.HackIpVO;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.mjo.cert.service.CertVO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.msgsent.service.MjonMsgSentVO;
import itn.let.mjo.pay.service.KmcVO;
import itn.let.sec.rgm.service.AuthorGroup;
import itn.let.sec.rgm.service.EgovAuthorGroupService;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.uat.uia.service.AuthCertVO;
import itn.let.uss.umt.service.AdmProcHstryVO;
import itn.let.uss.umt.service.EgovMberManageService;
@ -82,6 +89,10 @@ public class EgovMberManageServiceImpl extends EgovAbstractServiceImpl implement
@Resource(name = "hackIpService")
private HackIpService hackIpService;
/* MjonMsgDataService */
@Resource(name = "MjonMsgDataService")
private MjonMsgDataService mjonMsgDataService;
@Override
public int insertMber(MberManageVO mberManageVO) throws Exception {
@ -621,4 +632,71 @@ public class EgovMberManageServiceImpl extends EgovAbstractServiceImpl implement
return mberManageDAO.findTopByregDateFromCertLog(authCertVO);
}
public MberManageVO selectMberHeaderInfo(String mberId) throws Exception {
//회원 단가, 이벤트 단가, 이벤트 종료일 조회
MberManageVO headerInfo = mberManageDAO.selectMberHeaderInfo(mberId);
//기본 단가 조회
JoinSettingVO sysPrice = mjonMsgDataService.selectJoinSettingInfo();
//이벤트 종료까지 남은 계산
long eventLeftDay = calculateEventLeftDay(headerInfo.getEventEndDate());
headerInfo.setEventLeftDay(String.valueOf(eventLeftDay));
//이벤트 유무에 따라 이벤트 잔액 or 잔액 사용
boolean isEventActive = eventLeftDay > 0;
double money = isEventActive ? headerInfo.getEventRemainCash() : headerInfo.getUserMoney();
//이벤트, 회원 단가가 0일 기본 단가 사용
setPrices(headerInfo, sysPrice, isEventActive);
//발송가능 건수 조회
calculateAvailableCounts(headerInfo, money);
return headerInfo;
}
private long calculateEventLeftDay(String eventEndDateStr) {
if (StringUtil.isEmpty(eventEndDateStr)) return 0;
LocalDate today = LocalDate.now();
LocalDate eventEndDate = LocalDate.parse(eventEndDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return ChronoUnit.DAYS.between(today, eventEndDate);
}
private void setPrices(MberManageVO headerInfo, JoinSettingVO sysPrice, boolean isEventActive) {
if (isEventActive) {
headerInfo.setHeaderShortPrice(priceChk(headerInfo.getEventShortPrice(), sysPrice.getShortPrice()));
headerInfo.setHeaderLongPrice(priceChk(headerInfo.getEventLongPrice(), sysPrice.getLongPrice()));
headerInfo.setHeaderPicturePrice(priceChk(headerInfo.getEventPicturePrice(), sysPrice.getPicturePrice()));
headerInfo.setHeaderPicture2Price(priceChk(headerInfo.getEventPicture2Price(), sysPrice.getPicture2Price()));
headerInfo.setHeaderPicture3Price(priceChk(headerInfo.getEventPicture3Price(), sysPrice.getPicture3Price()));
} else {
headerInfo.setHeaderShortPrice(priceChk(headerInfo.getShortPrice(), sysPrice.getShortPrice()));
headerInfo.setHeaderLongPrice(priceChk(headerInfo.getLongPrice(), sysPrice.getLongPrice()));
headerInfo.setHeaderPicturePrice(priceChk(headerInfo.getPicturePrice(), sysPrice.getPicturePrice()));
headerInfo.setHeaderPicture2Price(priceChk(headerInfo.getPicture2Price(), sysPrice.getPicture2Price()));
headerInfo.setHeaderPicture3Price(priceChk(headerInfo.getPicture3Price(), sysPrice.getPicture3Price()));
}
// 카카오, 팩스 단가는 기본 단가 고정
headerInfo.setHeaderKakaoAtPrice(sysPrice.getKakaoAtPrice());
headerInfo.setHeaderFaxPrice(sysPrice.getFaxPrice());
}
private float priceChk(float price, float sysPrice) {
return price > 0 ? price : sysPrice;
}
private void calculateAvailableCounts(MberManageVO headerInfo, double money) {
headerInfo.setHeaderShortCnt(calcCount(money, headerInfo.getHeaderShortPrice()));
headerInfo.setHeaderLongCnt(calcCount(money, headerInfo.getHeaderLongPrice()));
headerInfo.setHeaderPictureCnt(calcCount(money, headerInfo.getHeaderPicturePrice()));
headerInfo.setHeaderPicture2Cnt(calcCount(money, headerInfo.getHeaderPicture2Price()));
headerInfo.setHeaderPicture3Cnt(calcCount(money, headerInfo.getHeaderPicture3Price()));
headerInfo.setHeaderKakaoAtCnt(calcCount(money, headerInfo.getHeaderKakaoAtPrice()));
headerInfo.setHeaderFaxCnt(calcCount(money, headerInfo.getHeaderFaxPrice()));
}
private int calcCount(double money, double price) {
if (price <= 0) return 0;
return (int) Math.floor(money / price);
}
}

View File

@ -345,5 +345,8 @@ public class MberManageDAO extends EgovComAbstractDAO{
public String findTopByregDateFromCertLog(AuthCertVO authCertVO) {
return (String)select("mberManageDAO.findTopByregDateFromCertLog", authCertVO);
}
public MberManageVO selectMberHeaderInfo(String mberId) {
return (MberManageVO) select("mberManageDAO.selectMberHeaderInfo", mberId);
}
}

View File

@ -251,4 +251,6 @@ public interface EgovMberManageService {
public String findTopByregDateFromCertLog(AuthCertVO authCertVO);
//사용자 헤더 정보(단가, 이벤트 활성화 기간)
public MberManageVO selectMberHeaderInfo(String mberId) throws Exception;
}

View File

@ -220,4 +220,6 @@ public interface EgovUserManageService {
public Map<String, Object> selectFaxSendList(FaxGroupDataVO faxGroupDataVO);
// 마지막 결제수단 조회
public String selectLastPayMethod(String mberId) throws Exception;
}

View File

@ -512,6 +512,39 @@ public class MberManageVO extends UserDefaultVO{
*/
private String secuLoginFlag;
/**
* 회원 이벤트 정보
*/
private String eventEndDate; //회원 이벤트 종료일자
private double eventRemainCash; //이벤트 차감 남은 Cash
private float eventShortPrice; //이벤트 단문 가격
private float eventLongPrice; //이벤트 장문 가격
private float eventPicturePrice; //이벤트 그림 1장 가격
private float eventPicture2Price; //이벤트 그림 2장 가격
private float eventPicture3Price; //이벤트 그림 3장 가격
private String eventLeftDay; //이벤트 남은 기간
/**
* 헤더 영역 정보(단가, 발송가능 건수)
*/
private float headerShortPrice;
private float headerLongPrice;
private float headerPicturePrice;
private float headerPicture2Price;
private float headerPicture3Price;
private float headerKakaoAtPrice;
private float headerKakaoFtPrice;
private float headerFaxPrice;
private int headerShortCnt;
private int headerLongCnt;
private int headerPictureCnt;
private int headerPicture2Cnt;
private int headerPicture3Cnt;
private int headerKakaoAtCnt;
private int headerKakaoFtCnt;
private int headerFaxCnt;
public String getSmsCode() {
return smsCode;
}
@ -1804,6 +1837,150 @@ public class MberManageVO extends UserDefaultVO{
public void setSecuLoginFlag(String secuLoginFlag) {
this.secuLoginFlag = secuLoginFlag;
}
public String getEventEndDate() {
return eventEndDate;
}
public void setEventEndDate(String eventEndDate) {
this.eventEndDate = eventEndDate;
}
public double getEventRemainCash() {
return eventRemainCash;
}
public void setEventRemainCash(double eventRemainCash) {
this.eventRemainCash = eventRemainCash;
}
public float getEventShortPrice() {
return eventShortPrice;
}
public void setEventShortPrice(float eventShortPrice) {
this.eventShortPrice = eventShortPrice;
}
public float getEventLongPrice() {
return eventLongPrice;
}
public void setEventLongPrice(float eventLongPrice) {
this.eventLongPrice = eventLongPrice;
}
public float getEventPicturePrice() {
return eventPicturePrice;
}
public void setEventPicturePrice(float eventPicturePrice) {
this.eventPicturePrice = eventPicturePrice;
}
public float getEventPicture2Price() {
return eventPicture2Price;
}
public void setEventPicture2Price(float eventPicture2Price) {
this.eventPicture2Price = eventPicture2Price;
}
public float getEventPicture3Price() {
return eventPicture3Price;
}
public void setEventPicture3Price(float eventPicture3Price) {
this.eventPicture3Price = eventPicture3Price;
}
public String getEventLeftDay() {
return eventLeftDay;
}
public void setEventLeftDay(String eventLeftDay) {
this.eventLeftDay = eventLeftDay;
}
public float getHeaderShortPrice() {
return headerShortPrice;
}
public void setHeaderShortPrice(float headerShortPrice) {
this.headerShortPrice = headerShortPrice;
}
public float getHeaderLongPrice() {
return headerLongPrice;
}
public void setHeaderLongPrice(float headerLongPrice) {
this.headerLongPrice = headerLongPrice;
}
public float getHeaderPicturePrice() {
return headerPicturePrice;
}
public void setHeaderPicturePrice(float headerPicturePrice) {
this.headerPicturePrice = headerPicturePrice;
}
public float getHeaderPicture2Price() {
return headerPicture2Price;
}
public void setHeaderPicture2Price(float headerPicture2Price) {
this.headerPicture2Price = headerPicture2Price;
}
public float getHeaderPicture3Price() {
return headerPicture3Price;
}
public void setHeaderPicture3Price(float headerPicture3Price) {
this.headerPicture3Price = headerPicture3Price;
}
public int getHeaderShortCnt() {
return headerShortCnt;
}
public void setHeaderShortCnt(int headerShortCnt) {
this.headerShortCnt = headerShortCnt;
}
public int getHeaderLongCnt() {
return headerLongCnt;
}
public void setHeaderLongCnt(int headerLongCnt) {
this.headerLongCnt = headerLongCnt;
}
public int getHeaderPictureCnt() {
return headerPictureCnt;
}
public void setHeaderPictureCnt(int headerPictureCnt) {
this.headerPictureCnt = headerPictureCnt;
}
public int getHeaderPicture2Cnt() {
return headerPicture2Cnt;
}
public void setHeaderPicture2Cnt(int headerPicture2Cnt) {
this.headerPicture2Cnt = headerPicture2Cnt;
}
public int getHeaderPicture3Cnt() {
return headerPicture3Cnt;
}
public void setHeaderPicture3Cnt(int headerPicture3Cnt) {
this.headerPicture3Cnt = headerPicture3Cnt;
}
public float getHeaderKakaoAtPrice() {
return headerKakaoAtPrice;
}
public void setHeaderKakaoAtPrice(float headerKakaoAtPrice) {
this.headerKakaoAtPrice = headerKakaoAtPrice;
}
public float getHeaderKakaoFtPrice() {
return headerKakaoFtPrice;
}
public void setHeaderKakaoFtPrice(float headerKakaoFtPrice) {
this.headerKakaoFtPrice = headerKakaoFtPrice;
}
public float getHeaderFaxPrice() {
return headerFaxPrice;
}
public void setHeaderFaxPrice(float headerFaxPrice) {
this.headerFaxPrice = headerFaxPrice;
}
public int getHeaderKakaoAtCnt() {
return headerKakaoAtCnt;
}
public void setHeaderKakaoAtCnt(int headerKakaoAtCnt) {
this.headerKakaoAtCnt = headerKakaoAtCnt;
}
public int getHeaderKakaoFtCnt() {
return headerKakaoFtCnt;
}
public void setHeaderKakaoFtCnt(int headerKakaoFtCnt) {
this.headerKakaoFtCnt = headerKakaoFtCnt;
}
public int getHeaderFaxCnt() {
return headerFaxCnt;
}
public void setHeaderFaxCnt(int headerFaxCnt) {
this.headerFaxCnt = headerFaxCnt;
}
}

View File

@ -882,5 +882,11 @@ public class EgovUserManageServiceImpl extends EgovAbstractServiceImpl implement
return resultMap;
}
// 마지막 결제수단 SELECT
@Override
public String selectLastPayMethod(String mberId) throws Exception {
return userManageDAO.selectLastPayMethod(mberId);
}
}

View File

@ -320,5 +320,9 @@ public class UserManageDAO extends EgovAbstractDAO{
public int selectUserPrePaymentPGdataCount(String userId) throws Exception{
return (int) select("userManageDAO.selectUserPrePaymentPGdataCount", userId);
}
// 마지막 결제수단 SELECT
public String selectLastPayMethod(String mberId) throws Exception{
return (String) select("userManageDAO.selectLastPayMethod", mberId);
}
}

View File

@ -12,6 +12,9 @@ import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -106,6 +109,7 @@ import itn.let.lett.service.LetterVO;
import itn.let.mjo.addr.service.AddrTransHistService;
import itn.let.mjo.addr.service.AddrTransHistVO;
import itn.let.mjo.event.service.MjonEventService;
import itn.let.mjo.event.service.MjonEventVO;
import itn.let.mjo.kisa.service.KisaService;
import itn.let.mjo.kisa.service.KisaVO;
import itn.let.mjo.mjocommon.MjonForienIpChk;
@ -130,6 +134,7 @@ import itn.let.sym.mnu.mpm.service.MenuManageVO;
import itn.let.sym.prm.service.EgovProgrmManageService;
import itn.let.sym.prm.service.ProgrmManageVO;
import itn.let.sym.site.service.EgovSiteManagerService;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.sym.site.service.MetaTagVO;
import itn.let.sym.site.service.SiteManagerVO;
import itn.let.uss.umt.service.EgovMberManageService;
@ -1256,6 +1261,16 @@ public class MainController {
model.addAttribute("mberManageVO", userManageService.selectUserInfo(mberManageVO));
}
/*
* 회원별 단가, 기본 단가, 이벤트 정보 조회
* 2025.07.25 이지우 추가
* */
MberManageVO mberHeaderInfoVO = new MberManageVO();
if(loginVO != null) {
mberHeaderInfoVO = mberManageService.selectMberHeaderInfo(loginVO.getId());
}
model.addAttribute("mberHeaderInfoVO", mberHeaderInfoVO);
return "web/com/webCommonHeader";
}

View File

@ -569,10 +569,8 @@
on A.ADDR_GRP_ID = mag.ADDR_GRP_ID
WHERE
A.MBER_ID = #mberId#
AND (A.RECV_STATUS = 'Y'
or A.RECV_STATUS = 'S'
or A.RECV_STATUS is null)
AND mag.DELETE_YN = 'N'
AND (A.RECV_STATUS IN ('Y', 'S') OR A.RECV_STATUS IS NULL)
AND (A.ADDR_GRP_ID IS NULL OR MAG.DELETE_YN = 'N')
</select>
<!-- 주소록 상세 조회 -->
@ -1354,34 +1352,32 @@
, BOOKMARK
, RECV_STATUS
)
SELECT
ADDR_GRP_ID
, MBER_ID
, ADDR_NM
, ADDR_PHONE_NO
, ADDR_INFO1
, ADDR_INFO2
, ADDR_INFO3
, ADDR_INFO4
, ADDR_COMMENT
, FRST_REGIST_PNTTM
, FRST_REGISTER_ID
, LAST_UPDT_PNTTM
, LAST_UPDUSR_ID
, DELETE_YN
, BOOKMARK
, RECV_STATUS
FROM TEMP_MJ_ADDR
WHERE MBER_ID = #mberId#
AND ADDR_GRP_ID = #addrGrpId#
AND BOOKMARK = #bookmark#
AND ADDR_PHONE_NO NOT IN
(
SELECT ADDR_PHONE_NO FROM MJ_ADDR
WHERE MBER_ID = #mberId#
AND ADDR_GRP_ID = #addrGrpId#
AND BOOKMARK = #bookmark#
)
SELECT t.ADDR_GRP_ID,
t.MBER_ID,
t.ADDR_NM,
FN_GETHYPHEN(t.ADDR_PHONE_NO),
t.ADDR_INFO1,
t.ADDR_INFO2,
t.ADDR_INFO3,
t.ADDR_INFO4,
t.ADDR_COMMENT,
t.FRST_REGIST_PNTTM,
t.FRST_REGISTER_ID,
t.LAST_UPDT_PNTTM,
t.LAST_UPDUSR_ID,
t.DELETE_YN,
t.BOOKMARK,
t.RECV_STATUS
FROM TEMP_MJ_ADDR AS t
LEFT JOIN MJ_ADDR AS m
ON m.MBER_ID = t.MBER_ID
AND m.ADDR_GRP_ID = t.ADDR_GRP_ID
AND m.BOOKMARK = t.BOOKMARK
AND replace(m.ADDR_PHONE_NO, '-', '') = replace(t.ADDR_PHONE_NO, '-', '')
WHERE t.MBER_ID = #mberId#
AND t.ADDR_GRP_ID = #addrGrpId#
AND t.BOOKMARK = #bookmark#
AND m.MBER_ID IS NULL
</insert>

View File

@ -909,7 +909,7 @@
<!-- 발신 내용 상세보기 조회 (상세보기 버튼 클릭시)-->
<select id="KakaoSentDAO.selectKakaoSentDetailDataAjax" parameterClass="mjonKakaoATVO" resultClass="mjonKakaoATVO">
/* KakaoSentDAO.selectKakaoSentDetailDataAjax */
SELECT
MGD.MSG_GROUP_ID as msgGroupId
, MGD.USER_ID as userId
@ -925,9 +925,14 @@
, MD.BIZ_KAKAO_RESEND_DATA as bizKakaoResendData /* 대체 문자 (치환O) */
, MGD.BIZ_KAKAO_RESEND_ORGNL_TXT as bizKakaoResendOrgnlTxt /* 대체 문자( 치환X ) */
, MD.BIZ_KAKAO_JSON_FILE as bizKakaoJsonFile /* Json 파일 경로 */
, BA.CONTENTS as contents
, MGD.AD_FLAG as adFlag
, MD.FILE_PATH1 as filePath1
FROM MJ_MSG_GROUP_DATA MGD
INNER JOIN MJ_MSG_DATA MD
ON MGD.MSG_GROUP_ID = MD.MSG_GROUP_ID
LEFT JOIN BIZ_ATTACHMENTS BA
ON MD.BIZ_KAKAO_JSON_FILE = BA.MSG_KEY
AND MGD.USER_ID = MD.USER_ID
WHERE
MGD.USER_ID = #userId#
@ -1392,6 +1397,10 @@
B.AT_DELAY_COMPLETE_YN AS atDelayCompleteYn,
A.MSG_NOTICETALK_SENDER_KEY AS msgNoticetalkSenderKey,
A.BIZ_KAKAO_RESEND_YN AS bizKakaoResendYn,
A.BIZ_KAKAO_RESEND_DATA as bizKakaoResendData,
B.AD_FLAG as adFlag ,
B.BIZ_KAKAO_IMAGE_TYPE as bizKakaoImageType ,
B.BIZ_KAKAO_RESEND_TYPE as bizKakaoResendType ,
CASE
WHEN B.AT_DELAY_YN = 'Y' AND B.AT_DELAY_COMPLETE_YN = 'N'
THEN DATE_ADD(B.REQ_DATE, INTERVAL -30 MINUTE)
@ -1400,7 +1409,7 @@
C.YELLOW_ID AS yellowId
FROM MJ_MSG_GROUP_DATA B
INNER JOIN (
select MSG_GROUP_ID, MSG_TYPE, DEL_FLAG, MSG_NOTICETALK_SENDER_KEY, BIZ_KAKAO_RESEND_YN
select MSG_GROUP_ID, MSG_TYPE, DEL_FLAG, MSG_NOTICETALK_SENDER_KEY, BIZ_KAKAO_RESEND_YN, BIZ_KAKAO_RESEND_DATA
from MJ_MSG_DATA
where DEL_FLAG = 'N'
<isNotEmpty property="tabType">
@ -1663,23 +1672,96 @@
</select>
<select id="KakaoSentDAO.selectKakaoSentCntEachCnt_advc" parameterClass="kakaoSentVO" resultClass="kakaoSentVO">
/* KakaoSentDAO.selectKakaoSentCntEachCnt_advc */
SELECT
a.MSG_GROUP_ID AS msgGroupId
, a.successCount
, a.waitCount
, a.failCount
, a.divideYn
<isEqual property="bizKakaoResendYn" compareValue="Y">
, a.kakaoResendSuccCount
, a.kakaoResendFailCount
, a.successCount * bkp.BIZ_KAKAO_AT_PRICE AS successPrice
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE) AS kakaoResendSuccPrice
</isEqual>
<isNotEqual property="bizKakaoResendYn" compareValue="Y">
, 0 AS kakaoResendSuccCount
, 0 AS kakaoResendFailCount
, 0 AS successPrice
, 0 AS kakaoResendSuccPrice
a.MSG_GROUP_ID AS msgGroupId
, a.successCount
, a.waitCount
, a.failCount
, a.divideYn
<isEqual property="bizKakaoResendYn" compareValue="Y">
, a.kakaoResendSuccCount
, a.kakaoResendFailCount
<isEqual property="msgType" compareValue="8">
, a.successCount * bkp.BIZ_KAKAO_AT_PRICE AS successPrice
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE) AS kakaoResendSuccPrice
</isEqual>
<isEqual property="msgType" compareValue="9">
<!-- bizKakaoImageType 있음 + MMS -->
<isNotEmpty property="bizKakaoImageType">
<!-- 와이드 이미지인 경우 -->
<isEqual property="bizKakaoImageType" compareValue="W">
, a.successCount * bkp.BIZ_KAKAO_FT_WIDE_IMG_PRICE AS successPrice
</isEqual>
<!-- 일반 이미지인 경우 -->
<isEqual property="bizKakaoImageType" compareValue="I">
, a.successCount * bkp.BIZ_KAKAO_FT_IMG_PRICE AS successPrice
</isEqual>
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_PICTURE_PRICE) AS kakaoResendSuccPrice
</isNotEmpty>
<!-- 이미지 없음 -->
<isEmpty property="bizKakaoImageType">
, a.successCount * bkp.BIZ_KAKAO_FT_PRICE AS successPrice
<isEqual property="bizKakaoResendType" compareValue="MMS">
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE) AS kakaoResendSuccPrice
</isEqual>
<isEqual property="bizKakaoResendType" compareValue="SMS">
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * 0) AS kakaoResendSuccPrice
</isEqual>
<!-- 예외: bizKakaoResendType 이 MMS, SMS 둘 다 아닐 경우 -->
<isNotEqual property="bizKakaoResendType" compareValue="MMS">
<isNotEqual property="bizKakaoResendType" compareValue="SMS">
, 0 AS kakaoResendSuccPrice
</isNotEqual>
</isNotEqual>
</isEmpty>
</isEqual>
</isEqual>
<isNotEqual property="bizKakaoResendYn" compareValue="Y">
, 0 AS kakaoResendSuccCount
, 0 AS kakaoResendFailCount
<isEqual property="msgType" compareValue="8">
, a.successCount * bkp.BIZ_KAKAO_AT_PRICE AS successPrice
</isEqual>
<isEqual property="msgType" compareValue="9">
<!-- 와이드 이미지인 경우 -->
<isEqual property="bizKakaoImageType" compareValue="W">
, a.successCount * bkp.BIZ_KAKAO_FT_WIDE_IMG_PRICE AS successPrice
</isEqual>
<!-- 일반 이미지인 경우 -->
<isEqual property="bizKakaoImageType" compareValue="I">
, a.successCount * bkp.BIZ_KAKAO_FT_IMG_PRICE AS successPrice
</isEqual>
<!-- 텍스트형(이미지 없음)인 경우 -->
<isNotEqual property="bizKakaoImageType" compareValue="W">
<isNotEqual property="bizKakaoImageType" compareValue="I">
, a.successCount * bkp.BIZ_KAKAO_FT_PRICE AS successPrice
</isNotEqual>
</isNotEqual>
</isEqual>
, 0 AS kakaoResendSuccPrice
</isNotEqual>
FROM (
SELECT
@ -1738,8 +1820,19 @@
, a.failCount
, a.kakaoResendSuccCount
, a.kakaoResendFailCount
, a.successCount * bkp.BIZ_KAKAO_AT_PRICE AS successPrice
, (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE) AS kakaoResendSuccPrice
<!-- , a.successCount * bkp.BIZ_KAKAO_AT_PRICE AS successPrice -->
,case
when a.msgType = '8' then a.successCount * bkp.BIZ_KAKAO_AT_PRICE
when a.msgType = '9' and a.bizKakaoImageType = 'I' then a.successCount * bkp.BIZ_KAKAO_FT_IMG_PRICE
when a.msgType = '9' and a.bizKakaoImageType = 'W' then a.successCount * bkp.BIZ_KAKAO_FT_WIDE_IMG_PRICE
when a.msgType = '9' and a.bizKakaoImageType != 'I' and a.bizKakaoImageType != 'W' then a.successCount * bkp.BIZ_KAKAO_FT_PRICE
end successPrice
<!-- , (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE) AS kakaoResendSuccPrice -->
,case
when a.msgType = '8' then (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE)
when a.msgType = '9' and (a.bizKakaoImageType = 'I' or a.bizKakaoImageType = 'W') then a.mmsCnt * bkp.BIZ_PICTURE_PRICE
when a.msgType = '9' and a.bizKakaoImageType != 'I' and a.bizKakaoImageType != 'W' then (a.smsCnt * bkp.BIZ_SMS_PRICE) + (a.mmsCnt * bkp.BIZ_MMS_PRICE)
end kakaoResendSuccPrice
, a.divideYn
, a.bizKakaoResendYn
, MKPI.YELLOW_ID AS yellowId
@ -1865,6 +1958,7 @@
, MD.BIZ_KAKAO_RESEND_YN as bizKakaoResendYn
, MD.MSG_NOTICETALK_SENDER_KEY
, MD.MSG_NOTICETALK_TMP_KEY
, MGD.BIZ_KAKAO_IMAGE_TYPE as bizKakaoImageType
FROM MJ_MSG_DATA MD
inner join MJ_MSG_GROUP_DATA MGD on
MGD.MSG_GROUP_ID = MD.MSG_GROUP_ID
@ -1896,6 +1990,7 @@
<!-- 발신 내용 상세보기 조회 (상세보기 버튼 클릭시)-->
<select id="KakaoSentDAO.selectKakaoSentDetailViewPhoneAjax" parameterClass="mjonKakaoATVO" resultClass="mjonKakaoATVO">
/* KakaoSentDAO.selectKakaoSentDetailViewPhoneAjax */
SELECT
MGD.MSG_GROUP_ID as msgGroupId

View File

@ -72,12 +72,16 @@
, SMS_TXT
, BIZ_KAKAO_TITLE
, AD_FLAG
, FILE_PATH1
, BIZ_KAKAO_RESEND_YN
, BIZ_KAKAO_RESEND_DATA
, BIZ_KAKAO_RESEND_TYPE
, BIZ_KAKAO_JSON_FILE
, REQ_DATE
, FILE_CNT
)VALUES
<iterate conjunction=",">
(
@ -95,12 +99,16 @@
, #[].templateContent#
, #[].templateTitle#
, #[].adFlag#
, #[].filePath1#
, #[].subMsgSendYn#
, #[].subMsgTxt#
, #[].subMsgType#
, #[].bizJsonName#
, #[].reqDate#
, #[].fileCnt#
)
</iterate>
</insert>
@ -131,6 +139,7 @@
REQ_DATE,
MSG_GROUP_CNT,
MSG_TYPE,
AD_FLAG,
AGENT_CODE,
EACH_PRICE,
@ -143,7 +152,8 @@
AT_DELAY_YN,
BIZ_KAKAO_RESEND_ORGNL_TXT,
BIZ_KAKAO_RESEND_TYPE
BIZ_KAKAO_RESEND_TYPE,
BIZ_KAKAO_IMAGE_TYPE
)VALUES
(
#msgGroupId#,
@ -154,6 +164,7 @@
#reqDate#,
#msgGroupCnt#,
#msgType#,
#adFlag#,
#agentCode#,
#eachPrice#,
@ -166,7 +177,8 @@
#atDelayYn#,
#bizKakaoResendOrgnlTxt#,
#bizKakaoResendType#
#bizKakaoResendType#,
#bizKakaoImageType#
)
</insert>
@ -180,6 +192,7 @@
, BIZ_KAKAO_FT_WIDE_IMG_PRICE
, BIZ_SMS_PRICE
, BIZ_MMS_PRICE
, BIZ_PICTURE_PRICE
)
VALUES
(
@ -190,6 +203,7 @@
,#kakaoFtWideImgPrice#
,#smsPrice#
,#mmsPrice#
,#picturePrice#
)
</insert>
@ -224,6 +238,8 @@
MMD.USER_ID AS userId
, MMD.MSG_GROUP_ID AS msgGroupId
, MMD.MSG_SEQ AS msgSeq
, MMGD.BIZ_KAKAO_IMAGE_TYPE AS bizKakaoImageType
, MMGD.EACH_PRICE AS eachPrice
, MMD.USERDATA AS userData
, MMD.REFUND_YN AS refundYn
, MMD.RSLT_CODE AS rsltCode
@ -233,11 +249,14 @@
, DATE_FORMAT(MMD.RSLT_DATE,'%Y-%m-%d %T') AS rsltDate
, MMD.BIZ_KAKAO_RESEND_YN AS subMsgSendYn
, MMD.BIZ_KAKAO_RESEND_TYPE AS subMsgType
, MMD.FILE_CNT AS fileCnt
, MMD.BIZ_UMID AS bizUmid
FROM
MJ_MSG_DATA MMD
INNER JOIN LETTNGNRLMBER MB
ON MMD.USER_ID = MB.MBER_ID
INNER JOIN mj_msg_group_data MMGD
on MMD.MSG_GROUP_ID = MMGD.MSG_GROUP_ID
WHERE 1=1
AND MMD.CUR_STATE = '3'
AND MMD.REFUND_YN = 'N'
@ -254,6 +273,15 @@
AND USERDATA = #userData#
</select>
<select id="kakaoAlimTalkDAO.selectBizLog" resultClass="kakaoVO" parameterClass="String">
SELECT
CALL_STATUS AS bizLogCallStatus
FROM
BIZ_LOG
WHERE 1=1
AND CMID = #umid#
</select>
<!-- 카카오 전송 환불 프로시저 실행 (카카오 전송 성공 관련) -->
<procedure id="kakaoAlimTalkDAO.updateKakaoAtSend" parameterClass="kakaoVO">
{call kakaoAt_Send(#userId#, #msgGroupId#, #userData#)}
@ -273,7 +301,7 @@
<!-- 카카오 친구톡 전송 환불 프로시저 실행 (카카오 전송 성공 관련 - 대체문자 선택시 차액 환불 처리) -->
<procedure id="kakaoAlimTalkDAO.updateKakaoFtSend" parameterClass="kakaoVO">
{call kakaoFt_Send(#userId#, #msgGroupId#, #userData#)}
{call kakaoFt_Send(#userId#, #msgGroupId#, #userData#, #fileCnt#, #bizKakaoResendType#, #bizKakaoImageType#)}
</procedure>
<!-- 카카오 친구톡 전송 환불 프로시저 실행 (카카오 전송 실패시 대체문자 관련 - 대체문자 발송 완료 된 경우) -->

View File

@ -37,7 +37,7 @@
VALUES
( #friendId#
, #userId#
, #bizJsonName#
, #atchFileId#
, #templateName#
, #imageFileName#
, #templateImageUrl#
@ -200,6 +200,7 @@
A.IMAGE_TYPE AS imageType,
A.IMAGE_TITLE AS imgTitle,
A.IMAGE_LINK AS imgLink,
A.ATCH_FILE_ID AS atchFileId,
A.TEMPLATE_CONTENTS AS templateContent,
A.AD_FLAG AS adFlag,
DATE_FORMAT(A.FRST_REGIST_PNTTM, '%Y-%m-%d %T') AS frstRegistPnttm,
@ -215,6 +216,7 @@
KFT.IMAGE_TYPE,
KFT.IMAGE_TITLE,
KFT.IMAGE_LINK,
KFT.ATCH_FILE_ID,
KFT.TEMPLATE_CONTENTS,
KFT.AD_FLAG,
KFT.FRST_REGIST_PNTTM,

View File

@ -2151,6 +2151,8 @@
, POINT_PER AS pointPer
, KAKAO_AT_PRICE AS kakaoAtPrice
, KAKAO_FT_PRICE AS kakaoFtPrice
, KAKAO_FT_IMG_PRICE AS kakaoFtImgPrice
, KAKAO_FT_WIDE_IMG_PRICE AS kakaoFtWideImgPrice
, FAX_PRICE AS faxPrice
FROM MJ_MBER_SETTING
@ -2169,6 +2171,8 @@
, PICTURE3_PRICE AS picture3Price
, KAKAO_AT_PRICE AS kakaoAtPrice
, KAKAO_FT_PRICE AS kakaoFtPrice
, KAKAO_FT_IMG_PRICE AS kakaoFtImgPrice
, KAKAO_FT_WIDE_IMG_PRICE AS kakaoFtWideImgPrice
, FAX_PRICE AS faxPrice
, USER_MONEY AS userMoney
, USER_POINT AS userPoint
@ -2180,6 +2184,8 @@
, BLINE_CODE AS blineCode
, AT_SMISHING_YN AS atSmishingYn
, PRE_PAYMENT_YN AS prePaymentYn
, BIZ_NO AS bizNo
, MBER_EMAIL_ADRES AS mberEmailAdres
FROM LETTNGNRLMBER
WHERE MBER_ID = #userId#
@ -3170,6 +3176,7 @@
WHERE 1 = 1
AND pf.SentEA > 0
AND mjf.USER_ID = #userId#
AND mjf.RESERVE_C_YN = 'N'
) AS pay
WHERE 1=1
@ -3279,7 +3286,7 @@
, M.fileName3 AS fileName3
, M.orderByCode AS orderByCode
, M.msgId AS msgId
, M.reqDate AS reqDate
, DATE_FORMAT(M.reqDate, '%Y-%m-%d %H:%i') AS reqDate
FROM
(SELECT
DATE_FORMAT(B.REGDATE, '%Y-%m-%d %H:%i' ) AS regDate
@ -3320,7 +3327,7 @@
/*and A.DEL_FLAG = 'N'*/
AND A.USER_ID = #userId#
AND B.USER_ID = #userId#
/*AND B.RESERVE_C_YN = 'N'*/
AND B.RESERVE_C_YN = 'N'
ORDER BY 1=1
, msgGroupId DESC
, sentDate DESC
@ -3368,6 +3375,7 @@
WHERE 1 = 1
AND pf.SentEA > 0
AND mjf.USER_ID = #userId#
AND mjf.RESERVE_C_YN = 'N'
) AS pay
WHERE 1=1
@ -3593,9 +3601,9 @@
, MIN(DATE_FORMAT(M.REQ_DATE, '%Y-%m-%d' )) AS minRegDate
, M.msgTypeName
, M.orderByCode
, SUM(IF(M.msgTypeName = '단문(SMS)', 1, 0)) AS shtSendCount
, SUM(IF(M.msgTypeName = '장문(LMS)', 1, 0)) AS longSendCount
, SUM(IF(M.msgTypeName = '그림(MMS)', 1, 0)) AS pictSendCount
, SUM(IF(M.msgTypeName = '단문', 1, 0)) AS shtSendCount
, SUM(IF(M.msgTypeName = '장문', 1, 0)) AS longSendCount
, SUM(IF(M.msgTypeName = '그림', 1, 0)) AS pictSendCount
, SUM(IF(M.msgTypeName = '알림톡', 1, 0)) AS atSendCount
, SUM(IF(M.msgTypeName = '친구톡', 1, 0)) AS ftSendCount
<!-- , SUM(M.MSG_GROUP_CNT) AS sendCount -->
@ -3614,14 +3622,14 @@
, B.MSG_TYPE
, CASE
WHEN B.MSG_TYPE = '6' AND B.FILE_CNT > 0
THEN '그림(MMS)'
THEN '그림'
WHEN B.MSG_TYPE = '6' AND B.FILE_CNT = 0
THEN '장문(LMS)'
THEN '장문'
WHEN B.MSG_TYPE = '8'
THEN '알림톡'
WHEN B.MSG_TYPE = '9'
THEN '친구톡'
ELSE '단문(SMS)'
ELSE '단문'
END msgTypeName
, CASE
WHEN B.MSG_TYPE = '6' AND B.FILE_CNT > 0
@ -7433,6 +7441,17 @@
</update>
<update id="mjonMsgDAO.updateRefundY" parameterClass="mjonMsgVO">
UPDATE MJ_MSG_DATA
SET REFUND_YN = 'Y'
WHERE
USER_ID = #userId#
AND USERDATA = #userData#
AND MSG_GROUP_ID = #msgGroupId#
</update>
<update id="mjonMsgDAO.updateKakaoAtDelayCancelMsgGroupDataFlag" parameterClass="mjonMsgVO">
UPDATE

View File

@ -7,6 +7,7 @@
<sqlMap namespace="Msg">
<typeAlias alias="mjonMsgSWFDTO" type="itn.let.mjo.msgsent.service.MjonMsgSWFDTO"/>
<typeAlias alias="mjonMsgDetailSentVO" type="itn.let.mjo.msgsent.service.MjonMsgDetailSentVO"/>
<typeAlias alias="mjonMsgDetailSentDTO" type="itn.let.mjo.msgsent.service.MjonMsgDetailSentDTO"/>
<typeAlias alias="mjonMsgSentVO" type="itn.let.mjo.msgsent.service.MjonMsgSentVO"/>
<typeAlias alias="mjonMsgVO" type="itn.let.mjo.msg.service.MjonMsgVO"/>
<typeAlias alias="addrGroupVO" type="itn.let.mjo.addr.service.AddrGroupVO"/>
@ -389,7 +390,7 @@
<!-- 전체 발송결과 조회 (전송사별)-->
<select id="MjonMsgSentDAO.findByMsgDetailListAjax" parameterClass="mjonMsgDetailSentVO" resultClass="mjonMsgDetailSentVO">
<select id="MjonMsgSentDAO.findByMsgDetailListAjax" parameterClass="mjonMsgDetailSentVO" resultClass="mjonMsgDetailSentDTO">
/* MjonMsgSentDAO.findByMsgDetailListAjax*/
SELECT

View File

@ -3,10 +3,11 @@
========= ======= =================================================
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="Pay">
<typeAlias alias="mjonPayVO" type="itn.let.mjo.pay.service.MjonPayVO"/>
<typeAlias alias="stVcVO" type="itn.let.mjo.pay.service.StVcVO"/>
<typeAlias alias="bizKakaoPriceVO" type="itn.let.kakao.kakaoComm.BizKakaoPriceVO"/>
<typeAlias alias="mjonVaMsgLogVO" type="itn.let.mjo.pay.service.MjonVaMsgLogVO"/>
<!-- 공통 쿼리 부분 문자 발송 관련 -->
@ -100,6 +101,7 @@
, D.CODE_NM AS rcptTypeTxt
, E.CONFIRM_YN AS confirmYn
, E.RCPT_TYPE AS rcptType
, E.CONFIRM_DATE AS confirmDate
, IFNULL(MP.POINT, '0') AS point
, EMI.EVENT_PG_MOID AS eventMoid
, mber.SMISHING_YN AS smishingYn
@ -148,6 +150,7 @@
MOID
, CONFIRM_YN
, RCPT_TYPE
, CONFIRM_DATE
FROM
MJ_TAX
WHERE 1=1
@ -606,6 +609,7 @@
MEMO,
ORDER_ID,
MSG_GROUP_ID
)VALUES
(
#userId#,
@ -624,6 +628,22 @@
</update>
<select id="mjonPayDAO.selectBizKakaoPrice" resultClass="bizKakaoPriceVO" parameterClass="String">
SELECT
BIZ_KAKAO_PRICE_ID AS bizKakaoPriceId,
BIZ_KAKAO_AT_PRICE AS bizKakaoAtPrice,
BIZ_KAKAO_FT_PRICE AS bizKakaoFtPrice,
BIZ_KAKAO_FT_IMG_PRICE AS bizKakaoFtImgPrice,
BIZ_KAKAO_FT_WIDE_IMG_PRICE AS bizKakaoFtWideImgPrice,
BIZ_SMS_PRICE AS bizSmsPrice,
BIZ_MMS_PRICE AS bizMmsPrice,
MSG_GROUP_ID AS msgGroupId
FROM BIZ_KAKAO_PRICE
WHERE MSG_GROUP_ID = #msgGroupId#
</select>
<insert id="mjonPayDAO.insertMjPg" parameterClass="mjonPayVO">
INSERT INTO MJ_PG
(
@ -2355,4 +2375,27 @@
</select>
<select id="mjonPayDAO.selectPayDetail" parameterClass="mjonPayVO" resultClass="mjonPayVO">
SELECT
LM.BIZ_NO AS bizNo
, LM.MBER_NM AS mberNm
, LM.MANAGER_NM AS managerNm
, LM.MBTLNUM AS mbtlNum
, LM.MBER_EMAIL_ADRES AS email
, LM.PRE_PAYMENT_YN AS prePaymentYn
, LM.DEPT AS dept
, LM.USER_MONEY AS userMoney
, MP.REG_DATE AS regDate
, MP.AMT AS amt
, MP.CASH AS cash
, MP.PG_STATUS AS pgStatus
FROM LETTNGNRLMBER LM
LEFT JOIN MJ_PG MP
ON MP.USER_ID = LM.MBER_ID
WHERE LM.MBER_ID = #userId#
AND MP.MOID = #moid#
</select>
</sqlMap>

View File

@ -2142,4 +2142,38 @@
</update>
<select id="mberManageDAO.selectMberHeaderInfo" resultClass="itn.let.uss.umt.service.MberManageVO" parameterClass="String">
SELECT
L.SHORT_PRICE AS shortPrice
, L.LONG_PRICE AS longPrice
, L.PICTURE_PRICE AS picturePrice
, L.PICTURE2_PRICE AS picture2Price
, L.PICTURE3_PRICE AS picture3Price
, L.PRE_PAYMENT_YN AS prePaymentYn
, L.USER_MONEY AS userMoney
, IFNULL(MEMI.EVENT_SHORT_PRICE, 0) AS eventShortPrice
, IFNULL(MEMI.EVENT_LONG_PRICE, 0) AS eventLongPrice
, IFNULL(MEMI.EVENT_PICTURE_PRICE, 0) AS eventPicturePrice
, IFNULL(MEMI.EVENT_PICTURE2_PRICE, 0) AS eventPicture2Price
, IFNULL(MEMI.EVENT_PICTURE3_PRICE, 0) AS eventPicture3Price
, IFNULL(MEMI.EVENT_REMAIN_CASH, 0) AS eventRemainCash
, DATE_FORMAT(MEMI.EVENT_END_DATE, '%Y-%m-%d') AS eventEndDate
FROM
LETTNGNRLMBER L
LEFT JOIN
MJ_EVENT_MBER_INFO MEMI
ON L.MBER_ID = MEMI.MBER_ID
AND MEMI.EVENT_INFO_ID = (
SELECT
MAX(EVENT_INFO_ID)
FROM
MJ_EVENT_MBER_INFO
WHERE
MBER_ID = #mberID#
AND EVENT_STATUS = 'Y'
)
WHERE L.MBER_ID = #mberId#
</select>
</sqlMap>

View File

@ -1458,5 +1458,15 @@
AND MONTH(REG_DATE) = MONTH(CURRENT_DATE)
</select>
<!-- 마지막 결제수단 SELECT -->
<select id="userManageDAO.selectLastPayMethod" parameterClass="String" resultClass="String">
SELECT
IFNULL(PAY_METHOD, '') AS nextPayMethod
FROM MJ_PG
WHERE
USER_ID = #userId#
ORDER BY REG_DATE DESC LIMIT 1
</select>
</sqlMap>

View File

@ -112,16 +112,17 @@ function insertAddrAjax() {
// return;
//}
if(!checkHpNum(form.addrPhoneNo.value)){//휴대폰 유효성 검사
if(!checkNorPhoneNum(form.addrPhoneNo.value)){//일반전화 유효성 검사
if(!isValidPhoneNumber(form.addrPhoneNo.value)){//일반전화 유효성 검사
const formattedNumber =formatPhoneNumber(form.addrPhoneNo.value); // 번호 표준화
if(!isValidPhoneNumber(formattedNumber)){
alert("잘못된 휴대폰번호 또는 일반전화 번호 입니다.");
return false;
}
}
//휴대폰번호 포맷 맞추기
form.addrPhoneNo.value = formatPhoneNumber(form.addrPhoneNo.value);
var data = new FormData(form);
$.ajax({

View File

@ -1398,14 +1398,14 @@ function actionLogin_end(){
<div class="inner">
<ul class="menu_left">
<li><a href="#" id="favorite" ><i class="hdTop_fav"></i>즐겨찾기추가</a></li>
<li><a href="<c:out value='/web/user/mberInfoIndex.do'/>" ><i class="hdTop_mypage"></i>마이페이지</a></li>
<li><a href="<c:out value='/web/cop/bbs/NoticeList.do'/>" ><i class="hdTop_center"></i>고객센터</a></li>
<li><a href="<c:out value='/web/user/mberInfoChange.do'/>" ><i class="hdTop_mypage"></i>마이페이지</a></li>
<li><a href="<c:out value='/web/cop/bbs/QnaList.do'/>" ><i class="hdTop_center"></i>1:1 문의</a></li>
</ul>
<ul class="menu_right">
<li><a href="#" onclick="location.href='/web/member/pay/PayView.do'" >충전하기</a></li>
<li class="SortLine"><a href="/web/pay/PayGuide.do" >요금안내</a></li>
<li class="SortLine"><a href="/web/cop/bbs/FaqList.do" >이용안내</a></li>
<li class="SortLine"><a href="/web/cop/bbs/QnaList.do" >1:1 문의</a></li>
<li class="SortLine"><a href="/web/cop/bbs/NoticeList.do" >고객센터</a></li>
<li class="SortLine"><a href="/web/cop/bbs/SuggestList.do" >불편신고</a></li>
</ul>
</div>
@ -1638,7 +1638,9 @@ function actionLogin_end(){
</li>
<li>
<dl>
<dt><a href="<c:out value='/web/user/mberInfoIndex.do'/>" >마이페이지</a></dt>
<%-- 250724 마이페이지 대시보드 삭제 --%>
<%-- <dt><a href="<c:out value='/web/user/mberInfoIndex.do'/>" >마이페이지</a></dt> --%>
<dt><a href="<c:out value='/web/user/mberInfoChange.do'/>" >마이페이지</a></dt>
<dd>
<ul>
<li><a href="<c:out value='/web/user/mberInfoChange.do'/>" >회원정보 변경</a></li>
@ -1648,7 +1650,7 @@ function actionLogin_end(){
</c:if>
<li><a href="<c:out value='/web/user/passwordChange.do'/>" >비밀번호 변경</a></li>
<li><a href="<c:out value='/web/user/sendNumberManage.do'/>" >발신번호 관리</a></li>
<li><a href="<c:out value='/web/user/notifyManage.do'/>" >알림설정</a></li>
<%-- <li><a href="<c:out value='/web/user/notifyManage.do'/>" >알림설정</a></li> --%>
<%-- <li><a href="<c:out value='/web/user/mberSecession.do'/>" >회원탈퇴</a></li> --%>
<%-- <li><a href="<c:out value='/web/user/kisaReport.do'/>" >KISA 신고</a></li> --%>
</ul>
@ -1663,7 +1665,7 @@ function actionLogin_end(){
<li><a href="<c:out value='/web/pay/PayGuide.do'/>" >요금안내/견적내기</a></li>
<li><a href="<c:out value='/web/member/pay/PayView.do'/>" >결제하기</a></li>
<li><a href="<c:out value='/web/member/pay/PayList.do'/>" >요금 결제내역</a></li>
<li><a href="<c:out value='/web/member/pay/PayUserSWList.do'/>" >요금 사용내역</a></li>
<li><a href="<c:out value='/web/member/pay/payUserSWList.do'/>" >요금 사용내역</a></li>
<!-- 현금영수증 자동발행 주석 -->
<%-- <li><a href="<c:out value='/web/member/pay/BillPub.do'/>" >계산서/현금영수증 발행 등록</a></li> --%>
<li><a href="<c:out value='/web/member/pay/BillPub.do'/>" >세금계산서 발행</a></li>
@ -1755,8 +1757,9 @@ function actionLogin_end(){
<div class="login_left">
<div class="login_info">
<input type="hidden" id="loginId" name="loginId" value="${LoginVO.id}">
<i><img src="/publish/images/mypageIcon2.png" id="commonHeaderGradeIcon" /></i>
<!-- <i><img src="/publish/images/mypageIcon2.png" id="commonHeaderGradeIcon" /></i> -->
<div class="login2_name" onclick="location.href='/web/user/mberInfoChange.do'" style="cursor:pointer;">
<i class="icon_user"></i>
<p><c:out value="${LoginVO.name}"/></p>
<c:choose>
<c:when test="${LoginVO.dept == 'p'}">
@ -1776,8 +1779,8 @@ function actionLogin_end(){
<img src="/pb/img/common/topTimeOut.png" alt="타임아웃 아이콘">
</a> -->
</div>
<button type="button" class="btnType btnType3" onclick="location.href='/web/user/mberInfoIndex.do'">마이페이지</button>
<button type="button" class="btnType btnType2" onclick="location.href='/web/uat/uia/actionLogout.do'">로그아웃</button>
<!-- <button type="button" class="btnType btnType3" onclick="location.href='/web/user/mberInfoIndex.do'">마이페이지</button> -->
<button type="button" class="btnType btn_36 fill_gray" onclick="location.href='/web/uat/uia/actionLogout.do'">로그아웃</button>
<div class="security_box">
@ -1789,34 +1792,89 @@ function actionLogin_end(){
</div>
<div class="login_pay">
<div class="check_money">
<div class="holdingsum_box">
<div class="holdingsum_box">
<i></i>
<div class="user_money_wrap">
보유잔액
<div class="hover_content_wrap">
<i class="qmMark">?</i>
<div class="hover_content">
<p class="hover_content_title">
<img src="/publish/images/content/icon_mypage_message.png" alt=""> 나의단가 <span>(발송가능 건수)</span>
</p>
<ul class="send_available_number">
<li>
<p class="title">· 단문</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerShortPrice}" var="shortPrice" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${shortPrice}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerShortCnt}" var="shortCnt" />
(<c:out value="${shortCnt}"/>건)</p>
</li>
<li>
<p class="title">· 장문</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerLongPrice}" var="LongPrice" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${LongPrice}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerLongCnt}" var="LongCnt" />
(<c:out value="${LongCnt}"/>건)</p>
</li>
<li>
<p class="title">· 그림(1장)</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPicturePrice}" var="picturePrice" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${picturePrice}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPictureCnt}" var="pictureCnt" />
(<c:out value="${pictureCnt}"/>건)</p>
</li>
<li>
<p class="title">· 그림(2장)</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPicture2Price}" var="picture2Price" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${picture2Price}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPicture2Cnt}" var="picture2Cnt" />
(<c:out value="${picture2Cnt}"/>건)</p>
</li>
<li>
<p class="title">· 그림(3장)</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPicture3Price}" var="picture3Price" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${picture3Price}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerPicture3Cnt}" var="picture3Cnt" />
(<c:out value="${picture3Cnt}"/>건)</p>
</li>
<li>
<p class="title">· 알림톡</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerKakaoAtPrice}" var="kakaoAtPrice" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${kakaoAtPrice}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerKakaoAtCnt}" var="kakaoAtCnt" />
(<c:out value="${kakaoAtCnt}"/>건)</p>
</li>
<li>
<p class="title">· 팩스</p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerFaxPrice}" var="faxPrice" />
<p class="number"><span class="c_002c9a fwBold"><c:out value="${faxPrice}"/></span>원
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.headerFaxCnt}" var="faxCnt" />
(<c:out value="${faxCnt}"/>건)</p>
</li>
</ul>
<c:if test="${prePaymentYn eq 'Y' and mberHeaderInfoVO.eventLeftDay > 0}">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${mberHeaderInfoVO.eventRemainCash}" var="eventRemainCash" />
<div class="event_term"><p>이벤트<span class="fwBold">(D-${mberHeaderInfoVO.eventLeftDay})</span></p><p><span class="fwBold price">${eventRemainCash}</span>원</p></div>
</c:if>
<c:if test="${prePaymentYn eq 'N'}">
<div class="event_term" style="display:block">후불제(매월 1일 자동충전)</div>
</c:if>
</div>
</div>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${userMoney}" var="commaPrice" />
<p>보유잔액<!-- <em>(캐시)</em> --> <span class="fwMd" id="hdUserMoney"><c:out value="${commaPrice}"/></span>원</p>
<c:if test="${prePaymentYn eq 'N'}">
<dl>
<dd>후불제 고객의 보유잔액(캐시)은 당월 발송 가능<br>금액을 말하며 <span>매월 1일 자동으로 충전</span>됩니다.</dd>
</dl>
</c:if>
</div>
<span class="fwMd" id="hdUserMoney"><c:out value="${commaPrice}"/></span>원
</ >
</div>
<button type="button" class="btnType btnType3" onclick="location.href='/web/member/pay/PayView.do'">충전</button>
<div class="account_box">
<button type="button" class="btnType btnType3" onclick="location.href='/web/member/pay/PayView.do?tabType=2'">전용계좌</button>
<c:if test="${not empty myBankList}">
<dl>
<dt>전용계좌</dt>
<dd><c:out value="${myBankList[0].codeNm}"/> <c:out value="${myBankList[0].acctNo}"/></dd>
</dl>
</c:if>
</div>
</div>
<div class="point">
<i></i>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${userPoint}" var="commaPoint" />
<p><!-- <em>적립</em> -->포인트 <span class="fwMd"><c:out value="${commaPoint}"/></span>원</p>
<button type="button" data-tooltip="popup04" class="btnType btnType3">교환</button>
</div>
</div>
<div class="point">
<i></i>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${userPoint}" var="commaPoint" />
<p><!-- <em>적립</em> -->포인트 <span class="fwMd"><c:out value="${commaPoint}"/></span>원</p>
<button type="button" data-tooltip="popup04" class="btnType btnType3">교환</button>
</div>
<!-- <div class="event">
<span><i></i>이달의 이벤트</span>
<button type="button" class="btnType btnType2" onclick="location.href='/web/cop/bbs/EventList.do'">GO</button>

View File

@ -90,6 +90,6 @@ function fnLinkPageTab(tabInfo){
<li id="tabStep" class="tab subTab"><button type="button" onclick="javascript:fnLinkPageTab('tabStep');">사용안내</button></li>
<li id="tabProfile" class="tab subTab"><button type="button" onclick="javascript:fnLinkPageTab('tabProfile');">채널ID 등록/관리</button></li>
<li id="tabTemplate" class="tab subTab"><button type="button" onclick="javascript:fnLinkPageTab('tabTemplate');">알림톡 템플릿 등록/관리</button></li>
<li id="tabSubFt" class="tab subTab"><button type="button" onclick="javascript:fnLinkPageTab('tabSubFt');">친구톡 템플릿 등록/관리</button></li>
<li id="tabSubFt" class="tab subTab"><button type="button" onclick="javascript:fnLinkPageTab('tabSubFt');">친구톡 템플릿 관리</button></li>
</ul>

View File

@ -143,7 +143,9 @@ function cntntBtnInfo(stepInfo){
<ul class="tabType4">
<li id="tabAt" class="tab topTab"><button type="button" onclick="javascript:fnLinkPageTopTab('tabAlim');">알림톡</button></li>
<c:if test="${pageContext.request.serverName == 'localhost'
|| pageContext.request.serverName == '119.193.215.98'}">
|| pageContext.request.serverName == '119.193.215.98'
|| pageContext.request.serverName == '192.168.0.176'
}">
<li id="tabFt" class="tab topTab"><button type="button" onclick="javascript:fnLinkPageTopTab('tabFriend');">친구톡</button></li>
</c:if>
<li id="tabConf" class="tab topTab"><button type="button" onclick="javascript:fnLinkPageTopTab('tabConf');">카카오톡 설정</button></li>

View File

@ -762,7 +762,7 @@ function sendTemplateInfo(){
// $('.loading_layer').removeClass('active');
// 프로그래스 바 종료
progressComplete();;
progressComplete();
}
,error: function (e) {
console.log("ERROR : ", e);

View File

@ -0,0 +1,959 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ 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" %>
<script type="text/javascript" src="<c:url value='/publish/js/content.js'/>"></script>
<script type="text/javascript">
var $tableExcel = null; //엑셀입력 탭
var $tableError = null; //엑셀입력 탭
$(document).ready(function(){
//Tabulator AJAX Data Loading
$tableError = new Tabulator("#tabulator_error", {
height:"255px",
width:"100%",
layout:"fitColumns",
autoColumns:false,
headerHozAlign:"center",
validationMode:"highlight",
clipboard:false,
clipboardCopySelector:"table",
clipboardPasteAction:"insert", // insert, update, replace
placeholder:"등록 팝업에서 휴대폰을 선택 후 확인해주세요.", //fit columns to width of table (optional)
columns:[ //Define Table Columns
{title:"이름", field:"name", hozAlign:"center", headerHozAlign: "center", width:125},
{title:"휴대폰", field:"phone", hozAlign:"center", headerHozAlign: "center"},
{title:"미등록 결과", field:"result", hozAlign:"center", headerHozAlign: "center"}
]
});
//Tabulator AJAX Data Loading
$tableExcel = new Tabulator("#tabulator_excel", {
height:"255px",
width:"100%",
layout:"fitColumns",
autoColumns:false,
headerHozAlign:"center",
validationMode:"highlight",
clipboard:false,
clipboardCopySelector:"table",
clipboardPasteAction:"insert", // insert, update, replace
placeholder:"Excel 파일을 업로드 해주세요.", //fit columns to width of table (optional)
columns:[ //Define Table Columns
{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, headerHozAlign:"center", hozAlign:"center", headerSort:false, cellClick:function(e, cell){
cell.getRow().toggleSelect();
}
},
{formatter:"rownum", align:"center" ,title:"No", hozAlign:"center", headerHozAlign:"center", width:50},
{title:"A", field:"A", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]},
{title:"B", field:"B", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]},
{title:"C", field:"C", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]},
{title:"D", field:"D", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]},
{title:"E", field:"E", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]},
{title:"F", field:"F", hozAlign:"center", headerHozAlign: "center", width:140, validator:["maxLength:100", "string"]}
],
validationFailed:function(cell, value, parameters){ // 유효성 체크 함수
var valid = cell.isValid();
if(!valid){
alert("양식에 맞지 않는 정보가 입력되었습니다.");
//해당 셀 데이터 삭제
cell.setValue("");
}
return value % parameters.phone;
},
});
// 타뷸레이터 width값 변경 시 위에 select width 값 변경
var titleArray = ["No","A","B","C","D","E","F"];
$tableExcel.on("columnWidth",function(column){
var titleIndex = titleArray.indexOf(column._column.definition.title);
titleIndex += 1;
if(titleIndex != 0){
$('.select_adr_hd>div').eq(titleIndex).css('width', column._column.width);
}else{
$('.select_adr_hd>div').eq(0).css('width', column._column.width);
}
});
$tableExcel.on("scrollHorizontal",function(left){
$(".adr_excel").scrollLeft(left);
})
$(".adr_excel").on("scroll",function(){
$(".tabulator-tableholder").scrollLeft($(this).scrollLeft());
});
$("#excelFileC4").on("change", function(event) {
var fileInfo = event.target.files;
if(fileInfo.length > 0){
excelFileChange(fileInfo[0]);
} else {
fn_loadRemoveActive(); // 파일이 선택되지 않은 경우 로딩 상태 제거
setTimeout(() => { $(this).val(''); }, 0); // 파일 선택 초기화
}
});
$(document).on('click', '#btnAddrMassClose', function() {
$('.field-selector').each(function() { $(this).val(''); });
setAddrMassClose();
});
$(document).on('click', '#closeBtn', function() {
// 대량등록 닫기
setAddrMassClose();
});
// 엑셀등록 닫기
function setAddrMassClose() {
$tableExcel.clearData();
$("#excelRowTotCnt").text(0); //총건수 수정
$("#excelRowDupCnt").text(0); //중복건수 수정
$("#excelRowErrorCnt").text(0); //중복건수 수정
// dupliPhoneDataRealList.length = 0; // 중복 휴대폰번호 초기화
// 중복 카운트
$("#errorPopDupCnt").text(0);
// 에러 카운트
$("#errorPopErrorCnt").text(0);
//
$("#errorPopTotCnt").text(0);
// popup 영역
$tableError.clearData();
}
//#############################################################################################
//파일업로드 드래그앤 드롭
//#############################################################################################
var objDragAndDrop = $(".upload_area");
$(document).on("dragenter",".upload_area",function(e){
e.stopPropagation();
e.preventDefault();
//$(this).css('border', '2px solid #0B85A1');
});
$(document).on("dragover",".upload_area",function(e){
e.stopPropagation();
e.preventDefault();
});
$(document).on("drop",".upload_area",function(e){
fn_loadAddActive();
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
excelFileChange(files[0]);
});
$(document).on('dragenter', function (e){
e.stopPropagation();
e.preventDefault();
});
$(document).on('dragover', function (e){
e.stopPropagation();
e.preventDefault();
//objDragAndDrop.css('border', '2px dotted #0B85A1');
});
$(document).on('drop', function (e){
e.stopPropagation();
e.preventDefault();
});
//파일 드래그앤드롭 종료
// 받는사람 선택삭제 버튼 처리해주기
$('#in_select_del').click(function(){
if($tableExcel == null || $tableExcel == ""){
alert("받는사람을 추가해 주세요.");
return false;
}
var selectedData = $tableExcel.getSelectedRows();
if(selectedData == "" || selectedData == null){
alert("삭제할 연락처를 선택해주세요.");
return false;
}else{ // 선택한 Row 데이터 삭제하기
if(confirm("선택하신 받는 사람을 삭제하시겠습니까?")){
// 선택 데이터 삭제
selectedData.forEach(row => row.delete());
totRows = $tableExcel.getRows().length;
$("#excelRowTotCnt").text(totRows);
}
}
});
// 추가버튼
$('#btnAddrMassReg').click(function(){
if($tableExcel.getData().length < 1){
alert("한 개 이상의 연락처를 입력하세요");
return false;
}
// else if (selectedData.length > 20000) {
// alert("2만줄 이상의 업로드는 데이터 부하로 업로드 할수 없습니다.");
// return false;
// }
// tableExcel 그룹의 select 요소들을 확인
var columns = $tableExcel.getColumns();
var isAddrPhoneNoSelected = columns.some(column => column.getField() === 'addrPhoneNo');
if (!isAddrPhoneNoSelected) {
alert('휴대폰이 선택되지 않았습니다.');
return false;
}
var addrData = $tableExcel.getData().map((row, index) => ({
name: row.addrNm,
phone: removeDash(row.addrPhoneNo),
rep1: row.addrInfo1,
rep2: row.addrInfo2,
rep3: row.addrInfo3,
rep4: row.addrInfo4,
}));
// 기존 tableL의 데이터를 가져옵니다.
var existingData = tableL.getData();
// 기존 데이터와 새로운 데이터를 합칩니다.
var combinedData = existingData.concat(addrData);
/**
* @ phone을 기준으로 중복 제거 및 갯수 계산
* @ 결과 반환
* return {
* uniqueArray, // 중복 제거된 배열
* uniqueCount, // 중복 제거된 데이터 개수
* duplicateArray, // 중복된 데이터 배열
* duplicateCount: duplicateArray.length // 중복된 데이터 개수
* };
*/
const result = removeDuplicatesAndCount(combinedData, 'phone');
// 총 30만건이 넘으면 false
if (!validateRowLimit(result.uniqueCount)) {
return false;
}
// 6. 수량/가격 계산
setAllCntData(result);
// fn_priceClclt(result.uniqueCount);
//결제 금액 구하기
totalFtPriceSum(tableL.getRows().length);
$('#closeBtn').click();
});
//받는사람 전체삭제 버튼 처리
$('#allDel').click(function(){
var data = $tableExcel.getRows();
$tableExcel.clearData();
$("#excelRowTotCnt").text(0); //총건수 수정
$("#excelRowDupCnt").text(0); //중복건수 수정
$("#excelRowErrorCnt").text(0); //중복건수 수정
dupliPhoneDataRealList.length = 0; // 중복 휴대폰번호 초기화
$tableError.clearData();
// select box 초기화
$('.field-selector').each(function() { $(this).val(''); });
});
//치환문자 있는 엑섹불러오기 버튼 클릭시 파일 첨부 실행
$('.c3').click(function(){ // 엑셀파일 불러오기 선택 시
$("#excelFileC4").click();
});
//타이틀 select 선택 이벤트
$('.field-selector').on('change', function() {
fn_loadAddActive();
setTimeout(() => {
var selectedFields = [];
var isDuplicate = false;
if($tableExcel.getData().length < 1){
alert('데이터 입력 후 선택해 주세요.');
$(this).val("");
fn_loadRemoveActive();
return false;
}
// 중복체크
$('.field-selector').each(function() {
var selectedField = $(this).val();
if (selectedField) {
if (selectedFields.includes(selectedField)) {
alert("중복된 필드를 선택할 수 없습니다.");
$(this).val(""); // 중복 필드를 선택한 경우 빈 값으로 초기화
isDuplicate = true;
return false; // 반복문 종료
}
selectedFields.push(selectedField);
}
});
//
updateTableFields($tableExcel);
// 필드가 휴대폰이면 열 중복체크
if($(this).val() == 'addrPhoneNo'){
fn_phoneDupl($tableExcel);
}
fn_loadRemoveActive();
}, 0); // 지연 없이 즉시 실행되도록 0ms 지연을 설정
});
});
function excelFileChange(file) {
if (file) {
// 파일 크기 체크 (20MB)
const maxSize = 20 * 1024 * 1024; // 20MB in bytes
if (file.size > maxSize) {
alert('파일 크기는 20MB를 초과할 수 없습니다.');
return;
}
fn_loadAddActive();
var reader = new FileReader();
var extension = file.name.split('.').pop().toLowerCase();
reader.onload = function(e) {
setTimeout(() => { // 파일 읽기 완료 후 실행되도록 함
if (extension === 'xlsx') {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
var jsonData = XLSX.utils.sheet_to_json(firstSheet, {header: 1});
// 문제 데이터를 확인하는 함수 호출
findInvalidDBCharacters(jsonData);
processExcelData(jsonData);
} else if (extension === 'xls') {
var data = e.target.result;
var workbook = XLSX.read(data, { type: 'binary' });
var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
var jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
// 문제 데이터를 확인하는 함수 호출
findInvalidDBCharacters(jsonData);
processExcelData(jsonData);
} else if (extension === 'txt') {
var textData = e.target.result;
processTextData(textData);
} else {
alert('지원되지 않는 파일 형식입니다.');
}
fn_loadRemoveActive();
}, 0); // 지연 없이 즉시 실행되도록 0ms 지연을 설정
};
if (extension === 'xlsx') {
reader.readAsArrayBuffer(file);
} else if (extension === 'xls') {
reader.readAsBinaryString(file); // xls 파일에 적절한 read 메서드 호출
} else if (extension === 'txt') {
reader.readAsText(file);
}
}
}
//문제 데이터를 확인하는 함수
function findInvalidDBCharacters(jsonData) {
console.log('DB 입력 값 검사 중...');
const invalidCharPattern = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; // 4바이트 유니코드 문자 (이모지 등)
for (let rowIndex = 0; rowIndex < jsonData.length; rowIndex++) {
const row = jsonData[rowIndex];
if (Array.isArray(row)) {
for (let colIndex = 0; colIndex < row.length; colIndex++) {
const cell = row[colIndex];
if (typeof cell === 'string' && invalidCharPattern.test(cell)) {
console.warn('허용되지 않는 문자: row', rowIndex + 1,', col ', colIndex + 1, ', value:', cell);
// 허용되지 않는 문자를 제거 (선택 사항)
row[colIndex] = cell.replace(invalidCharPattern, '');
console.log('수정된 값:', row[colIndex]);
}
}
}
}
}
//엑셀 데이터 처리 함수
function processExcelData(data) {
var keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var tableData = [];
var totalRows = data.length - 2; // 전체 데이터 수 (1, 2행 제외)
// 3번째 행부터 입력
data.slice(0).forEach((row, index) => {
var rowData = {};
keys.forEach((key, idx) => { // index 변수명 변경 (내부와 외부에서 사용되므로 충돌 방지)
// console.log('row[idx] : ', row[idx]);
// rowData[key] = row[idx] ? row[idx].trim() : ""; // 각 컬럼에 대해 기본값을 설정
rowData[key] = (typeof row[idx] === 'string') ? row[idx].trim() : row[idx];
});
tableData.push(rowData);
});
updateTable(tableData);
}
/* function processExcelData(data) {
console.log('data : ', data);
var keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var tableData = [];
var totalRows = data.length - 2; // 전체 데이터 수 (1, 2행 제외)
console.log('data: ', data);
// 3번째 행부터 입력
data.slice(0).forEach((row, index) => {
var rowData = {};
keys.forEach((key, idx) => { // index 변수명 변경 (내부와 외부에서 사용되므로 충돌 방지)
// console.log('row[idx] : ', row[idx]);
rowData[key] = row[idx] ? row[idx].trim() : ""; // 각 컬럼에 대해 기본값을 설정
rowData[key] = (typeof row[idx] === 'string') ? row[idx].trim() : row[idx];
});
tableData.push(rowData);
});
console.log('tableData :: ', tableData);
updateTable(tableData);
} */
// 텍스트 데이터 처리 함수
function processTextData(text) {
var lines = text.split('\n'); // 각 줄을 배열로 분리
var keys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
var tableData = [];
lines.forEach(line => {
var rowData = {};
var row = line.split(','); // 쉼표로 분리
keys.forEach((key, index) => {
rowData[key] = row[index] ? row[index].trim() : ""; // 각 컬럼에 대해 기본값을 설정
});
tableData.push(rowData);
});
updateTable(tableData);
}
//공통 테이블 업데이트 함수
function updateTable(tableData) {
$tableExcel.setColumns([ //Define Table Columns
{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, headerHozAlign:"center", hozAlign:"center", headerSort:false, cellClick:function(e, cell){
cell.getRow().toggleSelect();
}
},
{formatter:"rownum", align:"center" ,title:"No", hozAlign:"center", headerHozAlign:"center", width:10},
{title:"A", field:"A", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]},
{title:"B", field:"B", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]},
{title:"C", field:"C", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]},
{title:"D", field:"D", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]},
{title:"E", field:"E", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]},
{title:"F", field:"F", hozAlign:"center", headerHozAlign: "center", width:150, validator:["maxLength:100", "string"]}
]);
$tableExcel.setData(tableData).then(() => {
// excelRowTotCnt 업데이트
document.getElementById("excelRowTotCnt").innerText = tableData.length;
});
fn_loadRemoveActive();
}
/*
* 타이틀 select 선택할때마다 실행해서
* 데이터테이블 필드값 수정
*/
function updateTableFields($objTabul) {
var currentData = $objTabul.getData();
var columns = [
{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", headerSort: false, cellClick: function(e, cell) {
cell.getRow().toggleSelect();
}}
,{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:60}
];
var fieldMapping = [];
$('.field-selector').each(function(index) {
var selectedField = $(this).val();
// ASCII 문자 코드 사용 - 65=A, 66=B ...
var field = String.fromCharCode(65 + index);
if (selectedField) {
columns.push({
title: field
, field: selectedField
, hozAlign: "center"
, headerHozAlign: "center"
// , editor: "input"
, editor: false
, width: 140
, validator: ["maxLength:100", "string"]
});
fieldMapping.push(selectedField);
} else {
columns.push({
title: field
, field: field
, hozAlign: "center"
, headerHozAlign: "center"
, editor: false
// , editor: "input"
, width: 140
, validator: ["maxLength:100", "string"]
});
fieldMapping.push(field);
}
});
var updatedData = currentData.map(row => {
console.log('row : ', row);
var newRow = {};
fieldMapping.forEach((field, index) => {
newRow[field] = row[Object.keys(row)[index]] ?? "";
});
return newRow;
});
$objTabul.setColumns(columns);
$objTabul.setData(updatedData);
}
/**
* @ 핸드폰 중복 데이터
* */
function fn_phoneDupl($objTabul) {
$tableError.clearData();
var data = $objTabul.getData();
var phoneNumberChk = false;
var existingNumbers = new Set(); // 배열에서 Set으로 변경
let errorCount = 0; // 중복 번호 개수를 저장할 변수
let duplicateCount = 0; // 중복 번호 개수를 저장할 변수
const errors = []; // 오류 데이터를 저장할 배열
const newData = []; // 유효한 데이터만 저장할 새로운 배열
data.forEach((row, index) => {
const number = row.addrPhoneNo;
// number가 null, undefined, 빈 문자열이거나 숫자인 경우 처리
if (!number || (typeof number === 'string' && !number.trim())){
console.log("number : ", number);
return;
}
const formattedNumber = formatPhoneNumber(number); // 번호 표준화
const cleanedNumber = formattedNumber.replace(/[^0-9]/g, ''); // 숫자만 남김
if (!existingNumbers.has(cleanedNumber)) { // 중복 번호 체크
if (isValidPhoneNumber(formattedNumber)) { // 유효성 검사
row.addrPhoneNo = formattedNumber;
existingNumbers.add(cleanedNumber); // 추가된 번호를 기존 목록에 추가
newData.push(row); // 유효한 데이터만 새로운 배열에 추가
} else {
// 오류: 유효성 통과 못함
errorCount++;
errors.push({
name: row.addrNm, // 이름
phone: row.addrPhoneNo, // 폰번호
result: "오류" // 결과 메시지 추가
});
}
} else {
// 중복
duplicateCount++;
errors.push({
name: row.addrNm, // 이름
phone: row.addrPhoneNo, // 폰번호
result: "중복" // 결과 메시지 추가
});
}
});
// data 배열을 newData 배열로 대체
data = newData;
// 수정된 데이터로 테이블 업데이트
$objTabul.setData(data);
// 오류 총 카운트
$("#excelRowTotCnt").text($objTabul.getDataCount());
// 중복 카운트
$("#excelRowDupCnt").text(duplicateCount);
// 에러 카운트
$("#excelRowErrorCnt").text(errorCount);
// popup 영역
$("#errorPopTotCnt").text($objTabul.getDataCount());
// 중복 카운트
$("#errorPopDupCnt").text(duplicateCount);
// 에러 카운트
$("#errorPopErrorCnt").text(errorCount);
$tableError.setData(errors);
if(errorCount > 0){
alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
}
}
function fn_dupliPopupShow(){
$("#tableExcelDupliBtn").show();
}
// 상단 설명 더보기
function popMore(e){
$(e).closest(".pop_more_cont").toggleClass("pop_more_click");
if($(e).closest(".pop_more_cont").is(".pop_more_click")){
$(e).html('숨기기');
$(e).append('<i></i>');
}else {
$(e).html('더보기');
$(e).append('<i></i>');
}
}
// excel 오류정보 테스트
$(document).on('click', '#errorExcelBtn', function() {
if($tableError.getDataCount()<1){
alert('오류 정보가 없습니다.');
return false;
}
$tableError.download("xlsx", "error_data.xlsx");
});
</script>
<!-- 중복전화번호 data-tooltip:addrMassDupli_layer -->
<div class="tooltip-wrap">
<div class="popup-com addrMassDupli_layer" tabindex="0" data-tooltip-con="addrMassDupli_layer" data-focus="addrMassDupli_layer" data-focus-prev="addrMassDupli_layer-close" style="width: 270px; height: 500px;">
<div class="popup_heading">
<p>중복 휴대폰번호</p>
<button type="button" class="tooltip-close" data-focus="addrMassDupli_layer-close" onclick="setAddrDupliClose();"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
</div>
<div class="layer_in" style="padding:20px 0px;" id="addrMassDupli_layer">
</div>
<div class="popup_btn_wrap2" style="margin-top: 0px;">
<button type="button" class="tooltip-close" data-focus="addrMassDupli_layer-close" data-focus-next="addrMassDupli_layer">닫기</button>
</div>
</div>
</div>
<!-- 주소록 상세 결과 팝업 data-tooltip:adr_popup14 -->
<div class="tooltip-wrap">
<div class="popup-com adr_layer adr_detail_result adr_popup14" tabindex="0" data-tooltip-con="adr_popup14" data-focus="adr_popup14" data-focus-prev="adr_popu14-close" style="width: 525px;z-index:125;">
<div class="popup_heading">
<p>주소록 상세 결과</p>
<button type="button" class="tooltip-close" data-focus="adr_popup14-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
</div>
<div class="layer_in" style="padding:30px 20px;">
<div class="table_top">
<p>
총 <span class="c_e40000" id="errorPopTotCnt">0</span>건
/ 중복 <span class="c_002c9a" id="errorPopDupCnt">0</span>건
/ 오류 <span class="c_002c9a" id="errorPopErrorCnt">0</span>건</p>
<button type="button" class="excel_btn btnType" id="errorExcelBtn"><i class="downroad"></i>엑셀 다운로드</button>
</div>
<div class="tb_wrap adr_list" id="tabulator_error">
<!-- $tableError 참고 -->
</div>
<ul class="cf_text_ul">
<li>*중복번호는 하나의 번호만 등록됩니다.</li>
<li>*휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.</li>
<li>ex) 발송불가 특수문자, 자릿수 오류 등</li>
</ul>
<div class="popup_btn_wrap2">
<!-- <button type="button">저장</button> -->
<button type="button" class="tooltip-close" data-focus="adr_popup14-close" data-focus-next="adr_popup14">닫기</button>
</div>
</div>
</div>
</div>
<!--// 중복전화번호 팝업 -->
<div class="popup_heading">
<p>엑셀 불러오기</p>
<button type="button" class="tooltip-close" id="closeBtn" data-focus="popup07-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
</div>
<div class="layer_in execl_upload_layer" style="padding: 25px 30px;">
<!-- <div class="list_tab_wrap2"> -->
<!-- tab button -->
<!-- <ul class="list_tab" id="tbTabl"> -->
<!-- <li class="tab active" data-tabul="tableExcel"><button type="button" onclick="popupTab(this,'1'); fn_tabToggle('1');">엑셀입력</button></li> -->
<!-- <li class="tab" data-tabul="tableClip"><button type="button" onclick="popupTab(this,'2'); fn_tabToggle('2');">붙여넣기</button></li> -->
<!-- <li class="tab" data-tabul="tableSelf"><button type="button" onclick="popupTab(this,'3'); fn_tabToggle('3');">직접입력</button></li> -->
<!-- </ul>// tab button -->
<!-- </div> -->
<!-- 엑셀입력 -->
<div class="popCont current pop_more_cont" id="popCont_1">
<div class="titBox">
<p>- 주소록은 한 번에 최대 30만건까지 등록(EXCEL파일, 최대용량 20MB) 가능합니다. </p>
<p>- 엑셀 파일에 비밀번호 설정, 제한된 보기, 수식 등이 설정되어 있는 경우 업로드가 불가합니다.</p>
<p>- 구분선(|), 역슬래시(, ₩), 큰따옴표("), 이모지(이모티콘) 등 발송불가 특수문자는 저장되지 않습니다.</p>
<p>- 이름 200byte, [*1*]~[*4*] 200byte, 메모 250byte까지 입력 가능합니다.</p>
<p>- 주소록 등록이 어려우신 경우에는 <a href="<c:url value='/web/mjon/addragency/selectAddrAgencyList.do'/>" style="font-weight: bold; color: blue;">주소록 입력대행</a> 메뉴를 이용하실 수 있습니다. </p>
</div>
<div class="pop_more_wrap">
<button type="button" class="pop_more" onclick="popMore(this);">더보기<i></i></button>
</div>
</div><!--// 엑셀입력 -->
<!-- 공통 -->
<div>
<table class="layer_tType1">
<caption>엑셀입력 표</caption>
<colgroup>
<col style="width: 95px">
<col style="width: auto">
</colgroup>
<tbody>
<tr>
<!-- <th>그룹 선택</th>
<td>
<label for="" class="label">그룹 선택</label>
<select id="addrGrpIdInfo" name="addrGrpIdInfo">
</select>
<label for="" class="label">그룹명 입력</label>
<input type="text" id="addrGrpNm" name="addrGrpNm" placeholder="새 그룹명을 입력해주세요." onfocus="this.placeholder=''" onblur="this.placeholder='새 그룹명을 입력해주세요.'"class="inputLight" style="width: 300px;">
<input type="file" id="excelFile" accept=".xls, .xlsx, .txt" style="display:none"/>
<button type="button" class="excel_btn2 btnType c3"><i class="uproad"></i>엑셀, TXT파일 업로드</button>
</td> -->
<td colspan="2" style="padding:10px 0;">
<div class="file_upload_wrap" style="width:100%;display:flex;">
<div class="file_add upload_area">
<p><img src="/publish/images/content/file_add.png" alt="파일 붙여넣기">마우스로 엑셀파일을 여기에 끌어다 놓으세요</p>
</div>
<input type="file" id="excelFileC4" accept=".xls, .xlsx, .txt" style="display:none"/>
<button type="button" class="excel_btn2 btnType c3"><i class="uproad"></i>엑셀파일 업로드</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="excel_middle2">
<p>
총 <span class="c_e40000 fwBold" id="excelRowTotCnt">0</span>건
/ 중복 <span class="c_002c9a fwBold" id="excelRowDupCnt">0</span>건
/ 오류 <span class="c_002c9a fwBold" id="excelRowErrorCnt">0</span>건
<button type="button" class="btn_list_detail" data-tooltip="adr_popup14"><img src="/publish/images/search.png"></button>
</p>
<!-- &nbsp; -->
<!-- <button type="button" class="btnType btnType6" data-tooltip="addrMassDupli_layer" id="tableExcelDupliBtn">중복번호</button> -->
<!-- &nbsp; -->
<!-- <button type="button" class="btnType btnType6" data-tooltip="addrMassSaveDupli_layer" onclick="GetAddrMassSaveDupli()" id="btnAddrMassSaveDupli">중복번호</button> -->
</p>
<!-- <button type="button" class="btnType btnType6 addCallToF">번호추가</button> -->
</div>
<div class="adr_excel" style="margin-top: 13px; overflow-x:auto;">
<!-- <div class="adr_excel" style="margin-top: 13px;"> -->
<!-- thead -->
<div class="adr_hd select_adr_hd msg" data-group="tableExcel">
<div style="width: 100px;"></div>
<div style="width: 100px;"></div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<div style="width: 140px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
</div>
</div>
<div class="drag_drop_wrap callList_includ_box" id="tabulator_excel">
<!-- <img src="/publish/images/content/excel.jpg" style="width: 100%;"> -->
</div>
<div class="excel_middle">
<div class="select_btnWrap clearfix">
<div>
<button type="button" id="allDel"><i class="remove_img"></i>전체삭제</button>
<button type="button" id="in_select_del"><i class="remove_img"></i>선택삭제</button>
</div>
</div>
</div><!--// 공통 -->
<!-- 붙여놓기 설명 -->
<!-- <div class="req_area"> -->
<!-- <div class="text_box"> -->
<!-- - 휴대폰 번호가 입력된 txt 파일을 열어 복사(Ctrl+c) + 붙여넣기(Ctrl+v)로도 입력하실 수 있습니다.<br> -->
<!-- - 휴대폰 번호는 필수입력 항목입니다.<br> -->
<!-- - 이름,휴대폰 번호,[*1*],[*2*],[*3*],[*4*],메모 순서대로 입력해주세요.(예 : 010-1234-5678,홍길동,변수1…메모)<br> -->
<!-- - 이름은 24byte, [*1*]~[*4*] 40byte, 메모는 250byte까지 입력 가능합니다.<br> -->
<!-- - '오류 검사'를 통해 등록된 데이터에 전화번호 입력 오류를 확인하실 수 있습니다. -->
<!-- </div> -->
<!-- </div> -->
<div class="popup_btn_wrap2" style="margin: 0 auto 30px auto;">
<button type="button" id="btnAddrMassReg">추가</button>
<button type="button" id="btnAddrMassClose" class="tooltip-close" data-focus="adr_popup07-close" data-focus-next="popup07">닫기</button>
</div>
</div>

View File

@ -227,9 +227,15 @@ function pageUnitChg(obj){
<span class="di">분할</span>
</c:if>
</c:if>
<a href="#none" onclick="fn_sentDetailView('${resultAllSentList.msgGroupId}');">
<%-- <a href="#none" onclick="fn_sentDetailView('${resultAllSentList.msgGroupId}');">
<c:out value="${resultAllSentList.smsTxt}"/>
</a> --%>
<a href="#none" onclick="fn_sentDetailView('${resultAllSentList.msgGroupId}');">
<c:if test="${resultAllSentList.adFlag eq 'Y'}">(광고)</c:if>
<c:out value="${resultAllSentList.smsTxt}" />
<c:if test="${resultAllSentList.adFlag eq 'Y'}">수신거부 : 홈 > 채널차단</c:if>
</a>
</div>
</td>
<td>

View File

@ -18,19 +18,17 @@
<!--// 탭스타일 -->
<!-- 카카오 알림톡 미리보기 -->
<!-- <div class="tab_phone current" id="tab_phone_1"> -->
<!-- <div class="phone_kakako friendtalk"> -->
<div class="tab_phone current kakao_wrap" id="tab_phone_1">
<div class="phone_kakako">
<div class="phone_kakako friendtalk">
<div class="phoneIn">
<p class="prev_p"><img src="/publish/images/content/kakao_prev_icon.png" alt=""><c:out value="${resultMsgDetail.yellowId}"/></p>
<p class="prev_p"><img src="/publish/images/content/kakao_prev_icon.png" alt=""><c:out value="${searchVO.yellowId}"/></p>
<!-- 텍스트 미리보기 -->
<div class="text_preview">
<div class="allimtalk_title">
<img src="/publish/images/content/icon_allimtalk.png" alt="">
<c:choose>
<c:when test="${msgType eq '8'}">알림톡 도착</c:when>
<c:when test="${msgType eq '9'}">친구톡 도착</c:when>
</c:choose>
</div>
<c:if test="${resultMsgDetail.adFlag eq 'Y'}">
<p class="friend_talk_title"><span>(광고)</span></p>
</c:if>
<div class="allimtalk_content">
<c:choose>
<c:when test="${kakaoTemplateInfo.templateEmphasizeType eq 'TEXT'}">
@ -68,6 +66,11 @@
</c:choose>
</c:forEach>
</div>
<c:if test="${resultMsgDetail.adFlag eq 'Y'}">
<p class="kakao_block_text">수신거부 : 홈 > 채널차단</p>
</c:if>
</div>
</div>
<p class="addText">※ 단말기 설정에 따라 다르게 보일 수 있습니다</p>
@ -77,36 +80,62 @@
<c:if test="${resultMsgDetail.bizKakaoResendYn eq 'Y'}">
<!-- 문자 미리보기 -->
<div class="tab_phone" id="tab_phone_2" style="display: none;position:relative;">
<!-- <div class="tab_phone" id="tab_phone_2" > -->
<div class="tab_phone" id="tab_phone_2" style="display:none" >
<!-- <div class="tab_phone" id="tab_phone_2" style="display:none" > -->
<div class="phoneIn">
<div>
<p class="prev_p"><img src="/publish/images/search.png"> 문자내용</p>
<div class="text_length2 clearfix">
<span>발송일시 : <fmt:formatDate value="${parsedDate}" pattern="yyyy-MM-dd HH:mm:ss"/></span>
<c:if test="${resultMsgDetail.bizKakaoResendYn eq 'Y'}">
<c:choose>
<c:when test="${resultMsgDetail.bizKakaoResendTypeCnt > 1}">
<span class="msg_com msg_short">단문</span>
<span class="msg_com msg_long">장문</span>
</c:when>
<c:when test="${resultMsgDetail.bizKakaoResendTypeCnt < 2
&& resultMsgDetail.bizKakaoResendType eq 'SMS'}">
<c:when test="${resultMsgDetail.bizKakaoResendType eq 'SMS'}">
<span class="msg_com msg_short">단문</span>
</c:when>
<c:otherwise>
<span class="msg_com msg_long">장문</span>
</c:otherwise>
</c:choose>
<%-- <c:choose>
<c:when test="${resultMsgDetail.bizKakaoResendTypeCnt > 1}">
<span class="msg_com msg_short" style="float:right;">단문</span>
<span class="msg_com msg_long" style="float:right;">장문</span>
</c:when>
<c:when test="${resultMsgDetail.bizKakaoResendTypeCnt < 2
&& resultMsgDetail.bizKakaoResendType eq 'SMS'}">
<span class="msg_com msg_short" style="float:right;">단문</span>
</c:when>
<c:otherwise>
<span class="msg_com msg_long" style="float:right;">장문</span>
</c:otherwise>
</c:choose> --%>
</c:if>
<div>
<!-- <div>
<span>글자크기</span>
<button type="button" onclick="changeFontSize('plus');"><img src="/publish/images/content/font_plus.png"></button>
<button type="button" onclick="changeFontSize('minus');"><img src="/publish/images/content/font_minus.png"></button>
</div>
</div> -->
</div>
<div class="text_preview">
<c:if test="${not empty fileInfos}">
<div class="preiew_img">
<c:forEach var="fileInfo" items="${fileInfos}">
<div class="img_box">
<img src="<c:url value='/cmm/fms/getImage2.do'/>?atchFileId=<c:out value="${fileInfo.atchFileId}"/>&fileSn=<c:out value="${fileInfo.fileSn}"/>" alt="발송된 그림문자 미리보기" style="width: 100%">
</div>
</c:forEach>
</div>
</c:if>
<div class="preview_auto">
<c:if test="${resultMsgDetail.adFlag eq 'Y'}">
<p class="ad_tit">(광고)</p>
</c:if>
<p class="realtime">${fn:replace(resultMsgDetail.bizKakaoResendOrgnlTxt, newLineChar, "<br/>")}</p>
<c:if test="${resultMsgDetail.adFlag eq 'Y'}">
<p class="deny_receipt">무료거부 0808800858</p>
</c:if>
</div>
</div>
</div>

View File

@ -394,20 +394,18 @@ function fnReservCancel(msgGroupId){
}
/**
* @알림톡 재전송
* @재전송
*/
function fnMjMsgReSendAll() {
function fnMjMsgReSendAll() {
var msgType = $('#msgType').val();
var form = document.reSendAllForm;
if (!confirm("알림톡 발송 화면으로 이동합니다.")) {
return;
}
// msgKind에 따른 action 설정
form.action = "/web/mjon/alimtalk/kakaoAlimtalkMsgDataView.do";
form.submit();
if (confirm((msgType == '8' ? '알림톡' : '친구톡') + " 발송 화면으로 이동합니다.")) {
form.action = msgType == '8'
? '/web/mjon/alimtalk/kakaoAlimtalkMsgDataView.do'
: '/web/mjon/kakao/friendstalk/kakaoFriendsTalkMsgDataView.do';
form.submit();
}
}
@ -649,7 +647,11 @@ function previewPhone(){
<div class="res_info_in">
<div class="res_info_top clearfix">
<p>발송정보</p>
<p><button type="button" class="btnType btnType3" onclick="fnMjMsgReSendAll();">재전송</button></p>
<p>
<%-- <c:if test="${result.msgType eq '8'}"> --%>
<button type="button" class="btnType btnType3" onclick="fnMjMsgReSendAll();">재전송</button>
<%-- </c:if> --%>
</p>
</div>
<div class="res_info_btm">
<dl>
@ -667,6 +669,7 @@ function previewPhone(){
<dd>
<c:if test="${result.msgType eq '8'}">알림톡</c:if>
<c:if test="${result.msgType eq '9'}">친구톡</c:if>
<input type="hidden" id="msgType" value="${result.msgType }"/>
</dd>
</dl>
<dl>
@ -750,41 +753,50 @@ function previewPhone(){
<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.successCount + result.kakaoResendSuccCount}" 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.waitCount}" type="number" groupingUsed="true" /></span>건(${result.waitingPct})</dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>실패건수</dt>
<%-- 대체문자 기능 on
카카오톡 실패 + 대체문자 실패 = 실패
대체문자 기능 off
카카오톡 실패 = 실패
*카카오톡 실패임에도 대체문자로 발송이 성공한 경우 실패로 체크하지 않음 --%>
<dd><span class="c_e40000_g"><fmt:formatNumber value="${result.failCount - result.kakaoResendSuccCount}" type="number" groupingUsed="true" /></span>건(${result.failedPct})</dd>
</dl>
</div>
</div>
<p class="table_bottom_txt">* 전체건수를 클릭하면 받는 사람 상세정보를 확인하실 수 있습니다.</p>
<p class="table_bottom_txt">* 대체문자 발송 성공 시, 성공건수로 집계됩니다.</p>
<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.successCount + result.kakaoResendSuccCount}" 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.waitCount}" type="number" groupingUsed="true" /></span>건(${result.waitingPct})</dd>
</dl>
</div>
<div class="res_info_btm1">
<dl>
<dt>실패건수</dt>
<%-- 대체문자 기능 on
카카오톡 실패 + 대체문자 실패 = 실패
대체문자 기능 off
카카오톡 실패 = 실패
*카카오톡 실패임에도 대체문자로 발송이 성공한 경우 실패로 체크하지 않음 --%>
<dd><span class="c_e40000_g"><fmt:formatNumber value="${result.failCount - result.kakaoResendSuccCount}" type="number" groupingUsed="true" /></span>건(${result.failedPct})</dd>
</dl>
</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> -->
<p class="table_bottom_txt">* 전체건수를 클릭하면 받는 사람 상세정보를 확인하실 수 있습니다.</p>
<p class="table_bottom_txt" style="padding:5px 0 0 0;">* 대체문자 발송 성공 시, 성공건수로 집계됩니다.</p>
</div>
<div class="table_btn_right">
</div>
</div>
</div>
</div>
<!--// 상세결과-->
@ -925,6 +937,7 @@ function previewPhone(){
<form id="resPopForm" name="resPopForm" method="post">
<input type="hidden" id="msgGroupId" name="msgGroupId" value="${result.msgGroupId}"/>
<input type="hidden" name="yellowId" value="${result.yellowId}"/>
<!-- <input type="hidden" id="msgId" name="msgId" value=""/> -->
</form>

View File

@ -364,6 +364,7 @@ function cntSet(){
cntView('allCnt', response.allCnt);
cntView('atCnt', response.atCnt);
cntView('ftCnt', response.ftCnt);
//cntView('ftCnt', response.ftCnt);
},
error: function(error) {
@ -564,6 +565,15 @@ function fn_sentDetailView(msgGroupId) {
<table class="tType4"><tbody><tr><td>LOADING...</td></tr></tbody></table>
</div>
</div>
<div class="rev_admin_in">
<div class="rev_admin_top clearfix">
<p>친구톡</p>
<p></p>
</div>
<div class="rev_admin_btm admin_btm">
<table class="tType4"><tbody><tr><td>LOADING...</td></tr></tbody></table>
</div>
</div>
</div>
<div class="rev_admin" id="lodingAfter" style="display:none;">
@ -607,37 +617,39 @@ function fn_sentDetailView(msgGroupId) {
</dl>
</div>
</div>
<%-- <div class="rev_admin_in" id="ftCnt">
<div class="rev_admin_in" id="ftCnt">
<div class="rev_admin_top clearfix">
<p>친구톡</p>
<p><span><fmt:formatNumber value="${totFtCnt}" pattern="#,###"/></span> 건</p>
<p><span name="allCnt">0</span> 건</p>
</div>
<div class="rev_admin_btm">
<dl>
<dt>대기</dt>
<dd><span class="c_002c9a" name="waitCnt"><fmt:formatNumber value="${waitFtCnt}" pattern="#,###"/></span>건</dd>
<dd><span class="c_002c9a" name="waitCnt">0</span>건</dd>
</dl>
<dl>
<dt>성공</dt>
<dd><span class="c_002c9a" name="succCnt"><fmt:formatNumber value="${succFtCnt}" pattern="#,###"/></span>건</dd>
<dd><span class="c_002c9a" name="succCnt">0</span>건</dd>
</dl>
<dl>
<dt>실패</dt>
<dd><span class="c_e40000" name="failCnt"><fmt:formatNumber value="${failFtCnt}" pattern="#,###"/></span>건</dd>
<dd><span class="c_e40000" name="failCnt">0</span>건</dd>
</dl>
</div>
</div> --%>
</div>
</div>
<div class="list_tab_wrap2 type4">
<!-- tab button -->
<ul class="list_tab">
<li class="tab <c:if test="${searchVO.tabType eq '' || searchVO.tabType eq 'all' || empty searchVO.tabType}">active</c:if>"><button type="button" onclick="fnTabLoad('',0); return false;">전체</button></li>
<li class="tab <c:if test="${searchVO.tabType eq 'at'}">active</c:if>"><button type="button" onclick="fnTabLoad('at', 1); return false;">알림톡</button></li>
<%-- <c:if test="${pageContext.request.serverName == 'localhost'
|| pageContext.request.serverName == '119.193.215.98'}">
<li class="tab <c:if test="${searchVO.tabType eq 'ft'}">active</c:if>"><button type="button" onclick="fnTabLoad('ft', 2); return false;">친구톡</button></li>
</c:if> --%>
<li class="tab active"><button type="button" onclick="fnTabLoad('',0); return false;">전체</button></li>
<li class="tab"><button type="button" onclick="fnTabLoad('at', 1); return false;">알림톡</button></li>
<c:if test="${pageContext.request.serverName == 'localhost'
|| pageContext.request.serverName == '119.193.215.98'
|| pageContext.request.serverName == '192.168.0.176'
}">
<li class="tab"><button type="button" onclick="fnTabLoad('ft', 2); return false;">친구톡</button></li>
</c:if>
</ul><!--// tab button -->
</div>
<!-- 예약관리 > 전체 -->

View File

@ -400,7 +400,8 @@ function fnGoSampleTemplate(){
<div class="top_content kakaotalkset_cont current pay_tab_wrap">
<div class="heading">
<h2>카카오톡 설정</h2>
<button type="button" class="button info" onclick="window.open('popup_kakaoset_template.html','_blank','width=790, height=300, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=yes')">사용안내</button>
<button type="button" class="button info" onclick="window.open('/web/pop/ft/kakaoTemplatePop.do','_blank','width=850, height=240, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=yes')">사용안내</button>
<!-- <button type="button" class="button info" onclick="window.open('popup_kakaoset_template.html','_blank','width=790, height=300, top=100, left=100, fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=yes')">사용안내</button> -->
</div>
<div class="list_tab_wrap2 type2 ">
<!-- tab button -->
@ -436,7 +437,7 @@ function fnGoSampleTemplate(){
<!-- //검색조건 -->
<div class="list_info">
<div class="btn_wrap left">
<button type="button" class="btnType btnType2 template_add" onclick="location.href='/web/mjon/kakao/template/selectKakaoFriendsTemplateDataRegist.do'">템플릿 등록</button>
<!-- <button type="button" class="btnType btnType2 template_add" onclick="location.href='/web/mjon/kakao/template/selectKakaoFriendsTemplateDataRegist.do'">템플릿 등록</button> -->
<button type="button" class="btnType btnType3 btn_list"><i></i>리스트</button>
<button type="button" class="btnType btnType3 btn_thumbnail"><i></i>썸네일</button>
</div>

View File

@ -132,7 +132,7 @@ $(function(){
<dt>등록일</dt>
<dd><c:out value="${templatInfoList.frstRegistPnttm}"/>
<div class="btn_wrap">
<button type="button" class="btn_template_edit" title="템플릿 수정" onclick="javascript:fnTemplateDetail('<c:out value="${templatInfoList.friendId}"/>'); return false;"><img src="/publish/images/content/btn_template_edit.png" alt=""></button>
<%-- <button type="button" class="btn_template_edit" title="템플릿 수정" onclick="javascript:fnTemplateDetail('<c:out value="${templatInfoList.friendId}"/>'); return false;"><img src="/publish/images/content/btn_template_edit.png" alt=""></button> --%>
<button type="button" class="btn_template_delete" title="템플릿 삭제" onclick="javascript:fnTemplateDelBtn('<c:out value="${templatInfoList.friendId}"/>'); return false;"><img src="/publish/images/content/btn_template_delete.png" alt=""></button>
</div>
</dd>

View File

@ -273,7 +273,7 @@ $(document).ready(function(){
</div>
<!-- 관리자가 문자 상세에서 이용정지 처리 시 내용(문자 내용 안내) -->
<c:if test="${not empty spamMemberInfoVO.msgGroupId}">
<%-- <c:if test="${not empty spamMemberInfoVO.msgGroupId}">
<div class="input_list listType2">
<div class="input_list_item">
<div class="input_left">회원님의 아이디로 발송된 <strong>정보통신망법 제50조 위반</strong> 문자내용</div>
@ -323,7 +323,7 @@ $(document).ready(function(){
</div>
</div>
</div>
</c:if>
</c:if> --%>
<!-- 관리자가 사용자 상세에서 이용정지 처리 시 내용(관리자가 작성한 사유 안내) -->
<c:if test="${not empty spamMemberInfoVO.smiMemo}">

View File

@ -943,19 +943,6 @@ $(document).on('click', '#errorExcelBtn', function() {
<!-- <option value="addrComment">메모</option> -->
</select>
</div>
<!-- <div style="width: 125px;">
<label for="" class="label"></label>
<select class="field-selector">
<option value="">선택하기</option>
<option value="addrNm">이름</option>
<option value="addrPhoneNo">휴대폰</option>
<option value="addrInfo1">[*1*]</option>
<option value="addrInfo2">[*2*]</option>
<option value="addrInfo3">[*3*]</option>
<option value="addrInfo4">[*4*]</option>
<option value="addrComment">메모</option>
</select>
</div> -->
</div>
</div>

View File

@ -495,7 +495,7 @@
<li class="tab"><button type="button" onclick="location.href='/web/pay/PayGuide.do'">요금안내/견적내기</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayView.do'">결제하기</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayList.do'">요금 결제내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayUserSWList.do'">요금 사용내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/payUserSWList.do'">요금 사용내역</button></li>
<!-- <li class="tab active"><button type="button">계산서/현금영수증 발행 등록</button></li> -->
<li class="tab active"><button type="button">세금계산서 발행 등록</button></li>
</ul><!--// tab button -->

View File

@ -68,22 +68,60 @@ function f_print(){
</colgroup>
<tbody>
<tr>
<th>수<span class="blank"></span>신</th>
<td>${mberNm}</td>
<th>등록번호</th>
<td>
<c:choose>
<c:when test="${mberManageVO.dept eq'c'}">
<c:out value="${mberManageVO.bizNo}"/>
</c:when>
<c:otherwise>
-
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th>참<span class="blank"></span>조</th>
<td>담당자 ${managerNm} 님</td>
<th>상<span class="blank"></span>호</th>
<td>
<c:choose>
<c:when test="${mberManageVO.dept eq'c'}">
<c:out value="${mberManageVO.mberNm}"/>
</c:when>
<c:otherwise>
-
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th>거래일자</th>
<td>${startDate}~${endDate}</td>
<th>성<span class="blank"></span>명</th>
<td>
<c:choose>
<c:when test="${mberManageVO.dept eq'c'}">
<c:out value="${mberManageVO.managerNm}"/>
</c:when>
<c:otherwise>
<c:out value="${mberManageVO.mberNm}"/>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th>전화번호</th>
<td><c:out value="${mberManageVO.moblphonNo}"/></td>
</tr>
<tr>
<th style="letter-spacing:-0.85px;">이&ensp;메&ensp;일</th>
<td><c:out value="${mberManageVO.mberEmailAdres}"/></td>
</tr>
<tr>
<td colspan="2" style="text-align:center;"><span><c:out value="${mberManageVO.mberNm}"/></span>님의 사용내역(<c:out value="${startDate}"/>~<c:out value="${endDate}"/>)을 아래와 같이 확인합니다.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="cont2 clearfix">
<%-- <div class="cont2 clearfix">
<p>총 사용금액</p>
<c:choose>
<c:when test="${searchVO.addVatType eq 'N'}">
@ -93,24 +131,22 @@ function f_print(){
<p><span>${addTaxSumPrice}</span> 원(VAT 포함)</p>
</c:otherwise>
</c:choose>
</div>
</div> --%>
<div class="cont3">
<p>(단위 : 원, 건)</p>
<div class="est_table2_wrap">
<table class="est_table2">
<caption>품목, 발송건수, 공급가액, 부가세, 금액 정보를 제공하는 표</caption>
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:30%;">
<col style="width:30%;">
<col style="width:auto;">
</colgroup>
<thead>
<tr>
<th scope="col">품목</th>
<th scope="col">문자유형</th>
<th scope="col">발송건수</th>
<th scope="col">공급가액</th>
<th scope="col">금액</th>
<th scope="col">사용금액</th>
</tr>
</thead>
<tbody>
@ -120,15 +156,15 @@ function f_print(){
<td>${result.msgTypeName}</td>
<td>
<c:choose>
<c:when test="${result.msgTypeName eq '단문(SMS)'}">
<c:when test="${result.msgTypeName eq '단문'}">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.shtSendCount}" var="shtSendCount" />
<c:out value="${shtSendCount}"/>
</c:when>
<c:when test="${result.msgTypeName eq '장문(LMS)'}">
<c:when test="${result.msgTypeName eq '장문'}">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.longSendCount}" var="longSendCount" />
<c:out value="${longSendCount}"/>
</c:when>
<c:when test="${result.msgTypeName eq '그림(MMS)'}">
<c:when test="${result.msgTypeName eq '그림'}">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.pictSendCount}" var="pictSendCount" />
<c:out value="${pictSendCount}"/>
</c:when>
@ -144,10 +180,6 @@ function f_print(){
<%-- <fmt:formatNumber type="number" maxFractionDigits="3" value="${result.sendCount}" var="sendCount" />
<c:out value="${sendCount}"/> --%>
</td>
<td>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.supplyPrice}" var="supplyPrice" />
<c:out value="${supplyPrice}"/>
</td>
<td>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.totalPrice}" var="totalPrice" />
<c:out value="${totalPrice}"/>
@ -188,52 +220,13 @@ function f_print(){
</div>
</div>
<div class="cont4">
<table class="est_table">
<caption>공급가액, 총 결제금액에 대한 표</caption>
<colgroup>
<col style="width: 100px;">
<col style="width: auto;">
</colgroup>
<tbody>
<tr>
<th>공급가액</th>
<td><span>${supplySumPrice}</span></td>
</tr>
<c:choose>
<c:when test="${not empty resultList || not empty payUserSumFaxList}">
<c:choose>
<c:when test="${searchVO.addVatType eq 'N'}">
<tr class="total_price">
<th>총 사용금액</th>
<td><span>${totalSumPrice}</span></td>
</tr>
</c:when>
<c:otherwise>
<tr>
<th>세액(부가세)</th>
<td>${addTax}</td>
</tr>
<tr class="total_price">
<th>총 사용금액</th>
<td><span>${addTaxSumPrice}</span></td>
</tr>
</c:otherwise>
</c:choose>
</c:when>
<c:otherwise>
<c:if test="${ empty resultList && empty payUserSumFaxList}">
<tr>
<td colspan="5">
사용내역이 없습니다.
</td>
</tr>
</c:if>
</c:otherwise>
</c:choose>
</tbody>
</table>
<div class="cont2 clearfix">
<p>총 사용금액 <span>(VAT 별도)</span></p>
<p><span>
<c:out value="${totalSumPrice}"/>
</span>원</p>
</div>
<div class="cont5">
<p><span>${year} 년&nbsp;&nbsp;<span>${month}</span> 월&nbsp;&nbsp;<span>${day}</span> 일</p>
<div>

File diff suppressed because it is too large Load Diff

View File

@ -141,21 +141,11 @@ function fnShowPointPrintPopup(){
}
//환불요청 내역 프린트 출력 팝업
function fnShowRefundPrintPopup(){
//날자 체크
if( $('#startDate').val() != '' && $('#endDate').val() != '' ){
var iChkBeginDe = Number($('#startDate').val().replaceAll("/", ""));
var iChkEndDe = Number($('#endDate').val().replaceAll("/", ""));
if(iChkBeginDe > iChkEndDe || iChkEndDe < iChkBeginDe ){
alert("기간설정의 시작일자는 종료일자 보다 클수 없습니다.");
return;
}
}
function fnShowRefundPrintPopup(moid){
//만들려는 팝업의 크기
var popup_wid = '840';
var popup_ht = '900';
var popup_wid = '790';
var popup_ht = '800';
var popup_left = (window.screen.width / 2) - (popup_wid / 2);
var popup_top =(window.screen.height / 2) - (popup_ht / 2);
@ -165,6 +155,23 @@ function fnShowRefundPrintPopup(){
$("#listForm").attr({"action":"/web/member/pay/PayPrintRefundListPopUpAjax.do", "method":"post"}).submit();
}
//거래명세서 팝업
function fnShowPayInvoicePrintPopup(moid){
//만들려는 팝업의 크기
var popup_wid = '790';
var popup_ht = '800';
var popup_left = (window.screen.width / 2) - (popup_wid / 2);
var popup_top =(window.screen.height / 2) - (popup_ht / 2);
document.invoiceForm.moid.value = moid;
$("#invoiceForm").attr("target","invoicePrint");
window.open('', 'invoicePrint', 'width='+ popup_wid +', height='+ popup_ht +', left=' + popup_left + ', top='+ popup_top +',scrollbars=1');
$("#invoiceForm").attr({"action":"/web/member/pay/payInvoicePopupAjax.do", "method":"post"}).submit();
}
</script>
<!-- content 영역 -->
@ -176,7 +183,7 @@ function fnShowRefundPrintPopup(){
<li class="tab"><button type="button" onclick="location.href='/web/pay/PayGuide.do'">요금안내/견적내기</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayView.do'">결제하기</button></li>
<li class="tab active"><button type="button" >요금 결제내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayUserSWList.do'">요금 사용내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/payUserSWList.do'">요금 사용내역</button></li>
<!-- 현금영수증 자동발행 주석 -->
<!-- <li class="tab"><button type="button" onclick="location.href='/web/member/pay/BillPub.do'">계산서/현금영수증 발행 등록</button></li> -->
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/BillPub.do'">세금계산서 발행 등록</button></li>

View File

@ -409,13 +409,13 @@ function getMberGrdChk() {
</tbody>
</table>
<div class="excel_middle">
<div class="select_btnWrap clearfix">
<div class="select_btnWrap">
<div class="add_text2" style="line-height: 1.3em;">
※ 요금 결제내역은 결제일을 기준으로 최대 6개월까지만 조회가능합니다.
<br />
<c:choose>
<c:when test="${prePaymentYn eq 'Y'}">
※ 간편결제 영수증은 결제하신 서비스를 통해 제공됩니다.
※ 간편결제 영수증은 결제하신 서비스를 통해 제공됩니다.<br />
</c:when>
<c:otherwise>
※ 후불제 고객의 사용금액 결제수단은 계좌이체만 가능합니다. <br />
@ -423,6 +423,7 @@ function getMberGrdChk() {
<p class="accountinfo"><span>-입금은행:</span>우리은행<span>-입금계좌:</span>1005-904-154328<span>-받는사람:</span>주식회사 아이티앤</p>
</c:otherwise>
</c:choose>
※ 거래명세서는 세금계산서 발행일로부터 30일 이내에만 출력 가능합니다.
</div>
<div style="padding-top: 10px;">
<button type="button" class="level_btn" data-tooltip="level_check_popup01" id="levelIconBtn" style="display: none;">
@ -447,15 +448,13 @@ function getMberGrdChk() {
<div class="tb_wrap pay3_list">
<table class="tType4">
<colgroup>
<%-- <col style="width: 40px;"> --%>
<col style="width: 5%;">
<col style="width: 18%;">
<col style="width: 20%;">
<col style="width: 15%;">
<col style="width: 15%;">
<col style="width: 15%;">
<%-- <col style="width: 30%;"> --%>
<col style="width: 20%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
@ -506,7 +505,25 @@ function getMberGrdChk() {
<tbody>
<c:choose>
<c:when test="${not empty resultList}">
<!-- 오늘날짜 - 거래명세서 버튼 조건으로 사용 -->
<c:set var="now" value="<%=new java.util.Date()%>" />
<c:forEach var="result" items="${resultList}" varStatus="status">
<!-- 거래명세서 버튼 조건(250723)
1.전용계좌 or 즉시이체
2.세금계산서 발행 완료 이후 30일간 노출
3.발행 최대 횟수 2회 -->
<c:set var="invoiceYn" value="N"/>
<c:if test="${(result.payMethod eq 'BANK' or result.payMethod eq 'VBANK' or result.payMethod eq 'AFTERPAY')
and (result.confirmYn eq 'Y' and result.rcptType eq '9')}">
<c:set var="confirmDateStr" value="${fn:substring(result.confirmDate,0,10)}" />
<fmt:parseDate value="${confirmDateStr}" pattern="yyyy-MM-dd" var="confirmDateObj" />
<c:set var="dayDiff" value="${(now.time - confirmDateObj.time) / (1000*60*60*24)}" />
<c:if test="${dayDiff <= 31}">
<c:set var="invoiceYn" value="Y"/>
</c:if>
</c:if>
<tr class="tType3_bd">
<%-- <td>
<label for="" class="label">한 줄 전체 선택</label> <input type="checkbox" name="eachChk">
@ -628,7 +645,7 @@ function getMberGrdChk() {
</c:if>
<!-- 발행완료 -->
<c:if test="${result.confirmYn eq 'Y'}">
<c:if test="${result.rcptType eq '9'}">
<c:if test="${result.rcptType eq '9' and invoiceYn eq 'N'}">
<p class="fwRg c_002c9a">세금계산서 발행완료</p>
</c:if>
<c:if test="${result.rcptType eq '1' || result.rcptType eq '2'}">
@ -694,7 +711,7 @@ function getMberGrdChk() {
</c:if>
<!-- 발행완료 -->
<c:if test="${result.confirmYn eq 'Y'}">
<c:if test="${result.rcptType eq '9'}">
<c:if test="${result.rcptType eq '9' and invoiceYn eq 'N'}">
<p class="fwRg c_002c9a">세금계산서 발행완료</p>
</c:if>
<c:if test="${result.rcptType eq '1' || result.rcptType eq '2'}">
@ -712,7 +729,13 @@ function getMberGrdChk() {
</c:if>
</c:if>
</c:otherwise>
</c:choose>
</c:choose>
<c:if test="${invoiceYn eq 'Y'}">
<!-- <button class="btnType btnType20 btn_use_status" onclick="window.open('/publish/transaction_statement.html','','width=790,height=800')">거래명세서</button> -->
<button class="btnType btnType20 btn_use_status" onclick="fnShowPayInvoicePrintPopup('<c:out value="${result.moid}"/>'); return false;">거래명세서</button>
</c:if>
</td>
</tr>
</c:forEach>
@ -1065,4 +1088,8 @@ function getMberGrdChk() {
</div>
</div>
</div>
<!-- 거래명세서 팝업 -->
<form id="invoiceForm" name="invoiceForm" method="post">
<input type="hidden" id="moid" name="moid" value=""/>
</form>
<!-- 등급 및 누적결제액 확인 팝업 data-tooltip:level_check_popup01 끝 -->

View File

@ -24,6 +24,9 @@ var lastfulstday = "";
var lastfuledday = "";
var thisfulstlday = "";
var thisfuledtlday = "";
var threefulstday = "";
var threefuledday = "";
$(document).ready(function(){
payUserListAjax(1);
var date = new Date() ;
@ -47,8 +50,34 @@ $(document).ready(function(){
thisYearStart = date.getFullYear() + "/01/01" ;
thisYearEnd = date.getFullYear() + "/12/31" ;
//시작일 3개월 / 종료일 현재 조회
var threeMonthAgo = new Date(date);
threeMonthAgo.setMonth(threeMonthAgo.getMonth() - 3);
threeMonthAgo.setDate(threeMonthAgo.getDate() + 1); //하루 더하기
threefulstday = threeMonthAgo.getFullYear() + "/";
threefulstday += (threeMonthAgo.getMonth() + 1) < 10 ? "0" + (threeMonthAgo.getMonth() + 1) : (threeMonthAgo.getMonth() + 1) + "";
threefulstday += "/";
threefulstday += threeMonthAgo.getDate() < 10 ? "0" + threeMonthAgo.getDate() : threeMonthAgo.getDate();
threefuledday = date.getFullYear() + "/";
threefuledday += (date.getMonth() + 1) < 10 ? "0" + (date.getMonth() + 1) : (date.getMonth() + 1) + "";
threefuledday += "/";
threefuledday += date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
$(document).on('change','#pageUnitS', function(){
setPageUnit($(this).val());
payUserListAjax(1);
});
});
function setPageUnit(val){
$('#pageUnit').val(val);
}
// 기간 요일 지정
function setCalVal(val,targetObj){
$('input[name='+targetObj+']').val(val) ;
@ -61,10 +90,16 @@ function payUserListAjax(pageNo){
return;
};
if(!fn_G_limitDateChk("startDate", 3)){
return;
};
document.listForm.pageIndex.value = pageNo;
var sendData= $(document.listForm).serializeArray();
$("#payUserListLoad").load("/web/member/pay/PayUserSWListAjax.do", sendData ,function(response, status, xhr){
//조회 완료 인지를 위하여 hide show로 화면 변화 추가
$("#payUserListLoad").hide();
$("#payUserListLoad").load("/web/member/pay/payUserSWListAjax.do", sendData ,function(response, status, xhr){
$("#payUserListLoad").show();
});
}
@ -74,7 +109,7 @@ function payUserListTabMoveAjax(pageNo){
document.listForm.pageIndex.value = pageNo;
var sendData= $(document.listForm).serializeArray();
$("#payUserListLoad").load("/web/member/pay/PayUserSWListAjax.do", sendData ,function(response, status, xhr){
$("#payUserListLoad").load("/web/member/pay/payUserSWListAjax.do", sendData ,function(response, status, xhr){
});
}
@ -92,42 +127,6 @@ function payUserTab(obj, pageType){
}
function getUsedCashTotList(){
var sendData = {
"startDate" : $("#startDate").val(),
"endDate" : $("#endDate").val()
};
console.log('sendData : ', sendData);
// url: '/web/member/pay/getUsedCashTotList.do',
$.ajax({
type:"POST",
url:"<c:url value='/web/member/pay/getUsedCashTotList.do' />",
data: sendData,
dataType:'json',
success:function(data){
console.log('data :: ', data);
if(data.status == 'OK') {
// 성공 처리
} else {
// 오류 처리
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.error("AJAX Error:", textStatus, errorThrown);
console.error("Response:", jqXHR.responseText);
}
});
}
/* 윈도우팝업 열기 */
function infoPop(pageUrl){
document.infoPopForm.pageType.value = pageUrl;
@ -534,6 +533,7 @@ function fnRevDetailPop03(msgGroupId){
<form id="listForm" name="listForm" method="post">
<input type="hidden" id="pageType" name="pageType" value="<c:out value='${searchVO.pageType}'/>"/>
<input type="hidden" id="pageIndex" name="pageIndex" value="<c:out value='${searchVO.pageIndex}'/>"/>
<input type="hidden" id="pageUnit" name="pageUnit" value="10"/>
<div class="excel_middle">
<div class="select_btnWrap clearfix">
<div class="btn_left">
@ -543,9 +543,9 @@ function fnRevDetailPop03(msgGroupId){
<span class="dateEtc">~</span>
<input type="text" class="endDate inp calendar" title="검색 종료일" id="endDate" name="endDate" value="${endDate }" data-datecontrol="true">
</div>
<button type="button" onclick="setCalVal(thisYearStart,'startDate');setCalVal( thisYearEnd,'endDate'); return false;" class="btnType btnType19">이번년도</button>
<button type="button" onclick="setCalVal(lastfulstday,'startDate');setCalVal( lastfuledday,'endDate'); return false;" class="btnType btnType19">전월</button>
<button type="button" onclick="setCalVal(thisfulstlday,'startDate');setCalVal( thisfuledtlday,'endDate'); return false;" class="btnType btnType19">당월</button>
<button type="button" onclick="setCalVal(threefulstday,'startDate');setCalVal( threefuledday,'endDate'); return false;" class="btnType btnType19">3개월</button>
<button type="button" class="btnType6" onclick="payUserListAjax(1); return false;">조회</button>
<span class="reqTxt4">
<span class="vMiddle">*</span> 조회기간의 사용내역만 보여집니다.

View File

@ -91,8 +91,39 @@ $(document).ready(function(){
});
/* 사용내역서 클릭 시 내역서 새창 팝업 오픈 */
/* 250530 - 거래명세서, 사용내역서 분리 */
function fnShowPrintPopup() {
//만들려는 팝업의 크기
var url = "printMsgUsageDetailsAjax.do";
var popup_wid = '790';
var popup_ht = '800';
var popup_left = (window.screen.width/2)-(popup_wid/2);
var popup_top =(window.screen.height/2)-(popup_ht/2);
//날짜 체크
if(($('#startDate').val() != '' && $('#endDate').val() == '') || ($('#startDate').val() == '' && $('#endDate').val() != '')){
alert("기간설정을 정상적으로 선택해 주세요.");
return;
}
if( $('#startDate').val() != '' && $('#endDate').val() != '' ){
var iChkBeginDe = Number($('#startDate').val().replaceAll("/", ""));
var iChkEndDe = Number($('#endDate').val().replaceAll("/", ""));
if(iChkBeginDe > iChkEndDe || iChkEndDe < iChkBeginDe ){
alert("기간설정의 시작일자는 종료일자 보다 클수 없습니다.");
return;
}
}
document.listForm.action = url;
document.listForm.method = "post";
window.open("about:blank", 'printPop', 'width='+ popup_wid +', height='+ popup_ht +', left=' + popup_left + ', top='+ popup_top + ', fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=1');
document.listForm.target = "printPop";
document.listForm.submit();
}
/* 사용내역서 클릭 시 내역서 새창 팝업 오픈 */
/* function fnShowPrintPopup() {
//만들려는 팝업의 크기
var url = "";
var popup_wid = '830';
@ -131,7 +162,7 @@ function fnShowPrintPopup() {
window.open("about:blank", 'printPop', 'width='+ popup_wid +', height='+ popup_ht +', left=' + popup_left + ', top='+ popup_top + ', fullscreen=no, menubar=no, status=no, toolbar=no, titlebar=yes, location=no, scrollbars=1');
document.listForm.target = "printPop";
document.listForm.submit();
}
} */
/* 사용내역서 클릭 시 내역서 새창 팝업 오픈 */
function fnShowPrintPopup_OLD() {
@ -214,41 +245,48 @@ function fnShowPdfPrintPopup(){
<div class="pay_cont current" id="listTab2_1">
<input type="hidden" id="searchSortCnd" name="searchSortCnd" value="<c:out value="${searchVO.searchSortCnd}" />" />
<input type="hidden" id="searchSortOrd" name="searchSortOrd" value="<c:out value="${searchVO.searchSortOrd}" />" />
<input type="hidden" id="addVatType" name="addVatType" value="N" />
<div class="list_info">
<p>총 <span>${paginationInfo.totalRecordCount}</span>건 &nbsp; (<fmt:formatNumber value="${totSuccSendPrice}" pattern="" /> 원)</p>
<div>
<button type="button" class="print_btn" onclick="javascript:fnPayUserPrintPopup();">
<!-- <button type="button" class="print_btn" onclick="javascript:fnPayUserPrintPopup();">
<i class="print_img"></i>인쇄하기
</button>
<button type="button" class="pdf_btn" onclick="javascript:fnShowPdfPrintPopup();">
<i class="pdf_img"></i>PDF저장
</button>
</button> -->
<c:choose>
<c:when test="${not empty payUserSWList}">
<button type="button" class="btnType btn_36 border_gray btnType12" onclick="fnShowPrintPopup(); return false;">사용내역서</button>
</c:when>
<c:otherwise>
<button type="button" class="btnType btn_36 border_gray btnType12" onclick="alert('선택한 조회기간의 요금사용내역이 없습니다.');">사용내역서</button>
</c:otherwise>
</c:choose>
<button type="button" class="excel_btn">
<i class="downroad"></i>엑셀 다운로드
</button>
<label for="pageUnitS" class="label">검색조건 선택</label>
<select id="pageUnitS" class="selType2">
<option value="10" <c:if test="${paginationInfo.recordCountPerPage == '10'}">selected</c:if> >10줄</option>
<option value="20" <c:if test="${paginationInfo.recordCountPerPage == '20'}">selected</c:if> >20줄</option>
<option value="30" <c:if test="${paginationInfo.recordCountPerPage == '30'}">selected</c:if> >30줄</option>
<option value="100" <c:if test="${paginationInfo.recordCountPerPage == '100'}">selected</c:if> >100줄</option>
</select>
</div>
</div>
<div class="tb_wrap">
<table class="tType4">
<colgroup>
<%-- <col style="width: 5%;"> --%>
<col style="width: *%;">
<col style="width: 15%;">
<col style="width: 15%;">
<col style="width: 15%;">
<col style="width: 20%;">
<%-- <col style="width: 20%;"> --%>
<%-- <col style="width: 10%;">
<col style="width: auto;">
<col style="width: 9%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;"> --%>
<col style="width: 12%;">
<col style="width: 12%;">
<col style="width: 16%;">
</colgroup>
<thead>
<tr>
<%-- <th rowspan="2">
<label for="" class="label">전체 선택</label>
<input type="checkbox" id="chkAll">
</th> --%>
<th rowspan="2">
발송일시
<div class="sort_wrap">
@ -256,28 +294,18 @@ function fnShowPdfPrintPopup(){
</div>
</th>
<th rowspan="2">
문자유
<div class="sort_wrap">
<input type="button" class="sort sortBtn" id="sort_orderByCode">
</div>
</th>
<th rowspan="2">내용</th>
<th rowspan="2">발송건수</th>
<!-- <th colspan="2">충전</th>
<th colspan="2">사용</th>
<th colspan="2">잔액</th> -->
<!-- <th colspan="2">사용</th> -->
<th>사용</th>
<!-- <th>반환(실패)</th> -->
<!-- <th colspan="2">잔액</th> -->
<th colspan="2">발송건수</th>
<th rowspan="2">금액(원)</th>
</tr>
<tr>
<th>충전금</th>
<!-- <th>포인트</th> -->
<!-- <th>캐시</th> -->
<!-- <th>포인트</th> -->
<!-- <th>충전금</th>
<th>포인트</th> -->
<th>성공</th>
<th style="border-right:1px solid #ccc;">실패</th>
</tr>
</thead>
<tbody>
@ -285,10 +313,6 @@ function fnShowPdfPrintPopup(){
<c:when test="${not empty payUserSWList}">
<c:forEach var="payUserInfo" items="${payUserSWList}" varStatus="status">
<tr>
<%-- <td>
<label for="" class="label">선택</label>
<input type="checkbox" name="eachChk">
</td> --%>
<td>
<p><c:out value="${payUserInfo.reqDate}"/></p>
</td>
@ -339,11 +363,11 @@ function fnShowPdfPrintPopup(){
<c:if test="${payUserInfo.msgTypeTxt eq 'fax'}">
(<c:out value="${payUserInfo.fileCnt}"/>매)
</c:if>
/ <c:out value="${payUserInfo.failSendCnt}"/>
<%-- <c:out value="${payUserInfo.sendCount}"/>
<c:if test="${payUserInfo.msgTypeTxt eq 'fax'}">
(<c:out value="${payUserInfo.fileCnt}"/>)
</c:if> --%>
</p>
</td>
<td>
<p class="fwRg c_222">
<c:out value="${payUserInfo.failSendCnt}"/>
</p>
</td>
<td>
@ -352,58 +376,12 @@ function fnShowPdfPrintPopup(){
<c:out value="${succCash}"/>
</p>
</td>
<%-- <td>
<p class="fwRg c_002c9a">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.failSendPrice}" var="failPrice" />
<c:out value="${failPrice}"/>
</p>
</td> --%>
<!-- <td>
<p class="fwRg c_002c9a">
0
</p>
</td> -->
<%-- <td>
<p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.befCash}" var="befCash" />
<c:out value="${befCash}"/>
</p>
</td>
<td>
<p>
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.befPoint}" var="befPoint" />
<c:out value="${befPoint}"/>
</p>
</td>
<td>
<p class="fwRg c_002c9a">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.totPrice}" var="totPrice" />
<c:out value="${totPrice}"/>
</p>
</td>
<td>
<p class="fwRg c_002c9a">
0
</p>
</td> --%>
<%-- <td>
<p class="fwRg c_222">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.thisPoint}" var="thisPoint" />
<c:out value="${thisPoint}"/>
</p>
</td>
<td>
<p class="fwRg c_222">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${payUserInfo.befPoint}" var="befPoint" />
<c:out value="${befPoint}"/>
</p>
</td> --%>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr>
<td colspan="5">
<td colspan="6">
검색 결과가 없습니다.
</td>
</tr>
@ -412,7 +390,9 @@ function fnShowPdfPrintPopup(){
</tbody>
</table>
</div>
<div class="publish_btn clearfix">
<!-- 250530 - 거래명세서, 사용내역서 분리 -->
<%-- <div class="publish_btn clearfix">
<div>
<input type="radio" name="publish" id="publish1" value="statement">
<label for="publish1">거래명세서</label>
@ -434,7 +414,7 @@ function fnShowPdfPrintPopup(){
</c:otherwise>
</c:choose>
</div>
</div>
</div> --%>
<!-- pagination -->
<c:if test="${!empty payUserSWList}">

View File

@ -41,7 +41,7 @@ function getNextPayMethod() {
var nextPayMethod = "";
$.ajax({
type: "POST",
url: "/web/member/pay/selectNextPayMethodAjax.do",
url: "/web/member/pay/selectLastPayMethodAjax.do",
data: {},
dataType:'json',
async: false,
@ -817,7 +817,7 @@ function fnShowVaViewPrintPopup() {
<li class="tab"><button type="button" onclick="location.href='/web/pay/PayGuide.do'">요금안내/견적내기</button></li>
<li class="tab active"><button type="button">결제하기</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayList.do'">요금 결제내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/PayUserSWList.do'">요금 사용내역</button></li>
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/payUserSWList.do'">요금 사용내역</button></li>
<!-- 현금영수증 자동발행 주석 -->
<!-- <li class="tab"><button type="button" onclick="location.href='/web/member/pay/BillPub.do'">계산서/현금영수증 발행 등록</button></li> -->
<li class="tab"><button type="button" onclick="location.href='/web/member/pay/BillPub.do'">세금계산서 발행 등록</button></li>

View File

@ -0,0 +1,384 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ 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" %>
<%@ page import="itn.com.cmm.LoginVO" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>거래명세서</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/publish/css/reset.css">
<link rel="stylesheet" href="/publish/css/common.css">
<link rel="stylesheet" href="/publish/css/estimate.css">
<link rel="stylesheet" href="/publish/css/font.css">
<link rel="stylesheet" href="/publish/css/button.css">
</head>
<script type="text/javascript">
function f_print(){
document.getElementById('est_btn_wrap').style.display = 'none';
var initBody = document.body.innerHTML;
window.onbeforeprint = function(){
// print_area는 인쇄하고자 하는 영역의 ID를 말합니다.( 필수 )
// document.body.innerHTML = document.getElementById("print_area").innerHTML;
}
window.onafterprint = function(){
document.body.innerHTML = initBody;
}
window.print();
document.getElementById('est_btn_wrap').style.display = '';
}
</script>
<body>
<!-- 견적서 -->
<div class="estimate_wrap">
<div class="estimate">
<div class="est_head clearfix">
<img src="/publish/images/CI.png" alt="문자온 CI">
<div class="clearfix">
<p>(12248) 경기도 남양주시 다산순환로 20, A동 735호(다산동, 현대프리미어캠퍼스)</p>
<p>TEL 1551-8011</p>
</div>
</div>
<div class="est_body">
<h2>거래명세서<span style="font-size:20px;font-weight:400;">(공급받는자 보관용)</span></h2>
<div class="cont1 tb_ver2" style="display:flex;">
<div style="width:calc((100% - 40px)/2);">
<p>공급받는 자</p>
<table class="est_table">
<caption>등록번호, 상호, 성명, 전화번호, 이메일 정보 제공</caption>
<colgroup>
<col style="width: 60px;">
<col style="width: auto;">
</colgroup>
<tbody>
<tr>
<th>등록번호</th>
<td>
<c:choose>
<c:when test="${result.dept eq 'c'}">
<c:out value="${result.bizNo}"/>
</c:when>
<c:otherwise>
-
</c:otherwise>
</c:choose>
<!--(개인회원인 경우 하이픈(-) 처리)-->
</td>
</tr>
<tr>
<th style="letter-spacing:-0.69px;">상&ensp;&ensp;&ensp;&nbsp;&nbsp;호</th>
<td>
<c:choose>
<c:when test="${result.dept eq 'c'}">
<c:out value="${result.mberNm}"/>
</c:when>
<c:otherwise>
-
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th style="letter-spacing:-0.69px;">성&ensp;&ensp;&ensp;&nbsp;&nbsp;명</th>
<td>
<c:choose>
<c:when test="${result.dept eq 'c'}">
<c:out value="${result.managerNm}"/>
</c:when>
<c:otherwise>
<c:out value="${result.mberNm}"/>
</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<th>전화번호</th>
<td>
<c:out value="${result.mbtlNum}"/>
</td>
</tr>
<tr>
<th style="letter-spacing:-0.85px;">이&ensp;메&ensp;일</th>
<td>
<c:out value="${result.email}"/>
</td>
</tr>
</tbody>
</table>
</div>
<div style="width:calc((100% - 40px)/2);">
<p>공급자</p>
<img src="/publish/images/content/stamp.png" alt="도장" class="stamp mCS_img_loaded">
<table class="est_table">
<caption>등록번호, 상호, 성명, 전화번호, 이메일 정보 제공</caption>
<colgroup>
<col style="width: 60px;">
<col style="width: auto;">
</colgroup>
<tbody>
<tr>
<th>등록번호</th>
<td>653-87-00858</td>
</tr>
<tr>
<th style="letter-spacing:-0.69px;">상&ensp;&ensp;&ensp;&nbsp;&nbsp;호</th>
<td>주식회사 아이티앤</td>
</tr>
<tr>
<th style="letter-spacing:-0.69px;">성&ensp;&ensp;&ensp;&nbsp;&nbsp;명</th>
<td>유인식</td>
</tr>
<tr>
<th>전화번호</th>
<td>1551-8011</td>
</tr>
<tr>
<th style="letter-spacing:-0.85px;">이&ensp;메&ensp;일</th>
<td>help@iten.co.kr</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="cont3">
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.amt}" var="commaAmt" />
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.cash}" var="commaCash" />
<fmt:formatNumber type="number" maxFractionDigits="3" value="${result.amt - result.cash}" var="commaETC" />
<div class="est_table2_wrap">
<table class="est_table2">
<caption>작성일자, 공급가액, 세액, 비고 정보를 제공하는 표</caption>
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th scope="col">작성일자</th>
<th scope="col">공급가액</th>
<th scope="col">세액</th>
</tr>
</thead>
<tbody>
<fmt:parseDate value="${result.regDate}" pattern="yyyy-MM-dd HH:mm:ss.S" var="parsedDate"/>
<tr>
<td><fmt:formatDate value="${parsedDate}" pattern="yyyy-MM-dd"/></td>
<td><c:out value="${commaCash}"/></td>
<td><c:out value="${commaETC}"/></td>
</tr>
</tbody>
<tfoot>
<tr>
<th>비고</th>
<td style="padding:0 0 0 20px;">
<c:choose>
<c:when test="${result.prePaymentYn eq 'N'}">
사용기간(${result.startDate} ~ ${result.endDate})
</c:when>
<c:otherwise>
-
</c:otherwise>
</c:choose>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="est_table2_wrap" style="margin:20px 0 0 0;">
<table class="est_table2">
<caption>월, 일, 품목, 규격, 수량, 단가, 공급가액, 세액, 비고 정보를 제공하는 표</caption>
<colgroup>
<col style="width: 60px;">
<col style="width: 60px;">
<col style="width: auto;">
<col style="width: 60px;">
<col style="width: 60px;">
<col style="width: 60px;">
<col style="width: 100px;">
<col style="width: 60px;">
<col style="width: 70px;">
</colgroup>
<thead>
<tr>
<th scope="col">월</th>
<th scope="col">일</th>
<th scope="col">품목</th>
<th scope="col">규격</th>
<th scope="col">수량</th>
<th scope="col">단가</th>
<th scope="col">공급가액</th>
<th scope="col">세액</th>
<th scope="col">비고</th>
</tr>
</thead>
<tbody>
<tr>
<td><fmt:formatDate value="${parsedDate}" pattern="M"/></td>
<td><fmt:formatDate value="${parsedDate}" pattern="d"/></td>
<td>문자온 메시징 서비스 이용료</td>
<td></td>
<td></td>
<td></td>
<td><c:out value="${commaCash}"/></td>
<td><c:out value="${commaETC}"/></td>
<td>-</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
<!-- 후불제 -->
<!-- <tfoot>
<tr>
<th colspan="2">합계금액</th>
<th>전잔액</th>
<th colspan="2">입금액</th>
<th colspan="2">현잔액</th>
<th colspan="2" rowspan="2" style="background:#fff;vertical-align:middle;">이 금액을 [<span>청&ensp;구</span>]함</th>
</tr>
<tr>
<td style="text-align:center;" colspan="2">550,000</td>
<td style="text-align:center;">-</td>
<td style="text-align:center;" colspan="2">-</td>
<td style="text-align:center;" colspan="2">550,000</td>
</tr>
</tfoot> -->
<!-- //후불제 -->
<!-- 일반회원(선불제) -->
<tfoot>
<tr>
<th colspan="2">합계금액</th>
<th>전잔액</th>
<th colspan="2">입금액</th>
<th colspan="2">현잔액</th>
<th colspan="2" rowspan="2" style="background:#fff;vertical-align:middle;">
<c:choose>
<c:when test="${result.prePaymentYn eq 'N' and result.pgStatus ne '1'}">
이 금액을 [<span>청&ensp;구</span>]함
</c:when>
<c:otherwise>
이 금액을 [<span>영&ensp;수</span>]함
</c:otherwise>
</c:choose>
</th>
</tr>
<tr>
<td style="text-align:center;" colspan="2">
<c:out value="${commaAmt}"/>
</td>
<td style="text-align:center;">-</td>
<td style="text-align:center;" colspan="2">-</td>
<td style="text-align:center;" colspan="2">
<c:out value="${commaAmt}"/>
</td>
</tr>
</tfoot>
<!-- //일반회원(선불제) -->
</table>
</div>
</div>
<!-- <div class="cont5">
<p><span>2021</span> 년&nbsp;&nbsp;<span>6</span> 월&nbsp;&nbsp;<span>17</span> 일</p>
<div>
<span></span>
<span>주식회사 아이티앤</span>
<span>유&nbsp;&nbsp;인&nbsp;&nbsp;식&nbsp;&nbsp;(인)</span>
</div>
</div> -->
</div>
<div class="est_btn_wrap">
<button type="button" class="btnType" onclick="window.print();"><i class="print_img"></i>인쇄하기</button>
</div>
</div>
</div>
<!--// 견적서 -->
</body>
</html>

View File

@ -0,0 +1,30 @@
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="ec" uri="/WEB-INF/tld/ecnet_tld.tld"%>
<!-- 카톡발송 > 친구톡 -->
<div class="info_popup" id="friendTalkSend">
<div class="popup_heading">
<p>사용안내</p>
</div>
<div class="layer_in layer_info_wrap">
<ul class="info_list">
<!-- <li>친구톡 텍스트형은 최대 1,000자까지 작성 가능 (이미지형 400자, 와이드 이미지형 76자)</li>
<li>변수는 [*이름*], [*1*]~[*4*]까지 입력하실 수 있습니다.</li>
<li>광고성 정보 포함 시, 자동으로 (광고) 표시와 080무료수신거부번호가 메시지 내용에 표시됩니다.</li>
<li>(광고) 표기 사용 여부는 선택 가능하나, (광고) 표기 해제에 따른 법규 의무사항 미준수 시, 메시지 발송이 중단될 수 있습니다.</li>
<li>예약 메시지는 수정 가능하며, 예약 발송시간 5분전까지만 취소·삭제 가능합니다.</li>
-->
<li>친구톡은 알림톡과 달리 별도의 템플릿 심사가 필요하지 않습니다.</li>
<li>등록된 템플릿은 자유롭게 삭제가 가능합니다.</li>
<li>문자온이 제공하지 않는 이모티콘, 이모지를 포함하여 템플릿을 등록할 경우, 친구톡 발송이 불가합니다.</li>
</ul>
</div>
</div>
<!-- // 카톡발송 > 친구톡 -->

View File

@ -242,25 +242,17 @@ function updateUserInfo(){
$("#receivemail").val("N");
}
if($("#emailId").val() == ""){
alert("이메일을 입력해주세요.");
if($("#emailId").val().trim() == "" || $("#emailAdd").val().trim() == ""){
alert("이메일은 필수 입력 항목입니다.")
return false;
}
if($("#emailId").val() != ""|| $("#emailAdd").val() != ""){
if($("#emailAdd").val() != ""){
var email = $("#emailId").val() + "@" + $("#emailAdd").val();
var taxExptext = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
if(taxExptext.test(email)==false){
alert("이메일주소 형식이 올바르지 않습니다.");
return false;
}
$("#mberEmailAdres").val(email);
}else{
alert("이메일 주소를 확인해 주세요");
}else {
var email = $("#emailId").val() + "@" + $("#emailAdd").val();
var taxExptext = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
if(taxExptext.test(email)==false){
alert("이메일주소 형식이 올바르지 않습니다.");
return false;
}
$("#mberEmailAdres").val(email);
}
if("${cmpPhoneChangeManageVO.hstSttus}" == '03'){
@ -678,7 +670,7 @@ function changeValueWork(obj){
</c:if>
<div class="input_list_item emailWrap">
<div>
<div class="input_left"><span class="essential">*</span>이메일</div>
<div class="input_left">이메일</div>
<div class="input_right">
<div class="email">
<label for="" class="label">이메일 주소 앞자리</label>

View File

@ -149,21 +149,17 @@ function updateUserInfo(){
$("#receivemail").val("N");
}
if($("#emailId").val() != ""|| $("#emailAdd").val() != ""){
if($("#emailAdd").val() != ""){
var email = $("#emailId").val() + "@" + $("#emailAdd").val();
var taxExptext = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
if(taxExptext.test(email)==false){
alert("이메일주소 형식이 올바르지 않습니다.");
return false;
}
$("#mberEmailAdres").val(email);
}else{
alert("이메일 주소를 확인해 주세요");
if($("#emailId").val().trim() == "" || $("#emailAdd").val().trim() == ""){
alert("이메일은 필수 입력 항목입니다.")
return false;
}else {
var email = $("#emailId").val() + "@" + $("#emailAdd").val();
var taxExptext = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;
if(taxExptext.test(email)==false){
alert("이메일주소 형식이 올바르지 않습니다.");
return false;
}
$("#mberEmailAdres").val(email);
}
if("${userInfo.moblphonNo}" != $("#moblphonNo").val()){

View File

@ -671,7 +671,7 @@ function callTo() {
</c:otherwise>
</c:choose>
<button type="button" onclick="location.href='/web/member/pay/PayUserSWList.do';">
<button type="button" onclick="location.href='/web/member/pay/payUserSWList.do';">
<img src="/publish/images/content/mypage_plus.png" alt="더보기">
</button>
<div class="table_wrap" id="send_reserv">

Some files were not shown because too many files have changed in this diff Show More