--- pom.xml
+++ pom.xml
... | ... | @@ -111,6 +111,7 @@ |
| 111 | 111 |
<groupId>egovframework.rte</groupId> |
| 112 | 112 |
<artifactId>egovframework.rte.fdl.idgnr</artifactId> |
| 113 | 113 |
<version>${egovframework.rte.version}</version>
|
| 114 |
+ <!--<version>4.2.0</version>--> |
|
| 114 | 115 |
</dependency> |
| 115 | 116 |
<dependency> |
| 116 | 117 |
<groupId>egovframework.rte</groupId> |
+++ src/main/java/egovframework/com/idgen/CustomIdGnrService.java
... | ... | @@ -0,0 +1,10 @@ |
| 1 | +package egovframework.com.idgen; | |
| 2 | + | |
| 3 | +import java.util.List; | |
| 4 | + | |
| 5 | +import egovframework.rte.fdl.cmmn.exception.FdlException; | |
| 6 | +import egovframework.rte.fdl.idgnr.EgovIdGnrService; | |
| 7 | + | |
| 8 | +public interface CustomIdGnrService extends EgovIdGnrService { | |
| 9 | + List<String> getNextStringId(int count) throws FdlException; | |
| 10 | +} |
+++ src/main/java/egovframework/com/idgen/impl/CustomTableIdGnrServiceImpl.java
... | ... | @@ -0,0 +1,196 @@ |
| 1 | +package egovframework.com.idgen.impl; | |
| 2 | + | |
| 3 | +import java.math.BigDecimal; | |
| 4 | +import java.sql.Connection; | |
| 5 | +import java.sql.PreparedStatement; // java.sql.PreparedStatement로 임포트 | |
| 6 | +import java.sql.ResultSet; | |
| 7 | +import java.sql.SQLException; | |
| 8 | +import java.text.SimpleDateFormat; | |
| 9 | +import java.util.ArrayList; | |
| 10 | +import java.util.Date; | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +import javax.sql.DataSource; | |
| 14 | + | |
| 15 | +import org.springframework.jdbc.datasource.DataSourceUtils; | |
| 16 | + | |
| 17 | +import egovframework.com.idgen.CustomIdGnrService; | |
| 18 | +import egovframework.rte.fdl.cmmn.exception.FdlException; | |
| 19 | +import egovframework.rte.fdl.idgnr.EgovIdGnrStrategy; | |
| 20 | + | |
| 21 | +public class CustomTableIdGnrServiceImpl implements CustomIdGnrService { | |
| 22 | + | |
| 23 | + private long allocatedId; | |
| 24 | + private long allocatedMaxId; | |
| 25 | + private int blockSize = 10; // 기본값, 필요에 따라 변경 | |
| 26 | + private DataSource dataSource; | |
| 27 | + private String table; // 실제 테이블 이름 (예: IDS) | |
| 28 | + private String tableName; // TABLE_NAME 컬럼에서 사용할 값 (예: MSG_ID) | |
| 29 | + private String columnName = "NEXT_ID"; // NEXT_ID 컬럼명 | |
| 30 | + private String prefix; | |
| 31 | + private String fillChar = "0"; // 채울 문자 (예: 0) | |
| 32 | + private int cipers = 14; // 자리수 (예: 14) | |
| 33 | + private boolean applyYear; | |
| 34 | + private boolean useBigDecimals = false; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public synchronized List<String> getNextStringId(int count) throws FdlException { | |
| 38 | + List<String> idList = new ArrayList<>(count); | |
| 39 | + try { | |
| 40 | + for (int i = 0; i < count; i++) { | |
| 41 | + if (allocatedId >= allocatedMaxId) { | |
| 42 | + allocateIdBlock(count); | |
| 43 | + } | |
| 44 | + long id = allocatedId++; | |
| 45 | + idList.add(createStringId(id)); | |
| 46 | + } | |
| 47 | + } catch (Exception e) { | |
| 48 | + throw new FdlException("ID Generation Error", e); | |
| 49 | + } | |
| 50 | + return idList; | |
| 51 | + } | |
| 52 | + | |
| 53 | + private void allocateIdBlock(int requiredCount) throws SQLException, FdlException { | |
| 54 | + Connection conn = DataSourceUtils.getConnection(dataSource); | |
| 55 | + try { | |
| 56 | + conn.setAutoCommit(false); | |
| 57 | + | |
| 58 | + int newBlockSize = Math.max(this.blockSize, requiredCount); | |
| 59 | + | |
| 60 | + // SELECT 쿼리 수정 | |
| 61 | + String query = "SELECT " + columnName + " FROM " + table + " WHERE TABLE_NAME = ? FOR UPDATE"; | |
| 62 | + try (PreparedStatement stmt = conn.prepareStatement(query)) { | |
| 63 | + stmt.setString(1, tableName); | |
| 64 | + try (ResultSet rs = stmt.executeQuery()) { | |
| 65 | + long oldId = 0; | |
| 66 | + if (rs.next()) { | |
| 67 | + oldId = rs.getLong(1); | |
| 68 | + } else { | |
| 69 | + throw new FdlException( | |
| 70 | + "ID Generation Error: No record found in " + table + " for TABLE_NAME = " + tableName); | |
| 71 | + } | |
| 72 | + | |
| 73 | + long newId = oldId + newBlockSize; | |
| 74 | + | |
| 75 | + // UPDATE 쿼리 수정 | |
| 76 | + String update = "UPDATE " + table + " SET " + columnName + " = ? WHERE TABLE_NAME = ? AND " | |
| 77 | + + columnName + " = ?"; | |
| 78 | + try (PreparedStatement updateStmt = conn.prepareStatement(update)) { | |
| 79 | + updateStmt.setLong(1, newId); | |
| 80 | + updateStmt.setString(2, tableName); | |
| 81 | + updateStmt.setLong(3, oldId); | |
| 82 | + int row = updateStmt.executeUpdate(); | |
| 83 | + | |
| 84 | + if (row == 0) { | |
| 85 | + throw new FdlException( | |
| 86 | + "ID Generation Error: Failed to update ID. Possible concurrent modification."); | |
| 87 | + } | |
| 88 | + } | |
| 89 | + | |
| 90 | + conn.commit(); | |
| 91 | + | |
| 92 | + allocatedId = oldId; | |
| 93 | + allocatedMaxId = newId; | |
| 94 | + } | |
| 95 | + } catch (SQLException e) { | |
| 96 | + conn.rollback(); | |
| 97 | + throw e; | |
| 98 | + } | |
| 99 | + } catch (SQLException e) { | |
| 100 | + throw new FdlException("ID Generation Error", e); | |
| 101 | + } finally { | |
| 102 | + DataSourceUtils.releaseConnection(conn, dataSource); | |
| 103 | + } | |
| 104 | + } | |
| 105 | + | |
| 106 | + private String createStringId(long id) { | |
| 107 | + StringBuilder sb = new StringBuilder(); | |
| 108 | + if (prefix != null) { | |
| 109 | + sb.append(prefix); | |
| 110 | + } | |
| 111 | + if (applyYear) { | |
| 112 | + sb.append(new SimpleDateFormat("yyyy").format(new Date())); | |
| 113 | + } | |
| 114 | + String idStr = String.format("%0" + cipers + "d", id); | |
| 115 | + sb.append(idStr); | |
| 116 | + return sb.toString(); | |
| 117 | + } | |
| 118 | + | |
| 119 | + // 인터페이스의 다른 메서드 구현 (필요에 따라 UnsupportedOperationException 또는 직접 구현) | |
| 120 | + @Override | |
| 121 | + public BigDecimal getNextBigDecimalId() throws FdlException { | |
| 122 | + throw new UnsupportedOperationException("getNextBigDecimalId is not supported"); | |
| 123 | + } | |
| 124 | + | |
| 125 | + @Override | |
| 126 | + public long getNextLongId() throws FdlException { | |
| 127 | + throw new UnsupportedOperationException("getNextLongId is not supported"); | |
| 128 | + } | |
| 129 | + | |
| 130 | + @Override | |
| 131 | + public int getNextIntegerId() throws FdlException { | |
| 132 | + throw new UnsupportedOperationException("getNextIntegerId is not supported"); | |
| 133 | + } | |
| 134 | + | |
| 135 | + @Override | |
| 136 | + public short getNextShortId() throws FdlException { | |
| 137 | + throw new UnsupportedOperationException("getNextShortId is not supported"); | |
| 138 | + } | |
| 139 | + | |
| 140 | + @Override | |
| 141 | + public byte getNextByteId() throws FdlException { | |
| 142 | + throw new UnsupportedOperationException("getNextByteId is not supported"); | |
| 143 | + } | |
| 144 | + | |
| 145 | + @Override | |
| 146 | + public String getNextStringId() throws FdlException { | |
| 147 | + throw new UnsupportedOperationException("getNextStringId is not supported"); | |
| 148 | + } | |
| 149 | + | |
| 150 | + @Override | |
| 151 | + public String getNextStringId(String strategyId) throws FdlException { | |
| 152 | + throw new UnsupportedOperationException("getNextStringId(String strategyId) is not supported"); | |
| 153 | + } | |
| 154 | + | |
| 155 | + @Override | |
| 156 | + public String getNextStringId(EgovIdGnrStrategy strategy) throws FdlException { | |
| 157 | + throw new UnsupportedOperationException("getNextStringId(EgovIdGnrStrategy strategy) is not supported"); | |
| 158 | + } | |
| 159 | + | |
| 160 | + // 필요한 setter 메서드들 추가 | |
| 161 | + public void setDataSource(DataSource dataSource) { | |
| 162 | + this.dataSource = dataSource; | |
| 163 | + } | |
| 164 | + | |
| 165 | + public void setTable(String table) { | |
| 166 | + this.table = table; | |
| 167 | + } | |
| 168 | + | |
| 169 | + public void setTableName(String tableName) { | |
| 170 | + this.tableName = tableName; | |
| 171 | + } | |
| 172 | + | |
| 173 | + public void setColumnName(String columnName) { | |
| 174 | + this.columnName = columnName; | |
| 175 | + } | |
| 176 | + | |
| 177 | + public void setPrefix(String prefix) { | |
| 178 | + this.prefix = prefix; | |
| 179 | + } | |
| 180 | + | |
| 181 | + public void setFillChar(String fillChar) { | |
| 182 | + this.fillChar = fillChar; | |
| 183 | + } | |
| 184 | + | |
| 185 | + public void setCipers(int cipers) { | |
| 186 | + this.cipers = cipers; | |
| 187 | + } | |
| 188 | + | |
| 189 | + public void setApplyYear(boolean applyYear) { | |
| 190 | + this.applyYear = applyYear; | |
| 191 | + } | |
| 192 | + | |
| 193 | + public void setBlockSize(int blockSize) { | |
| 194 | + this.blockSize = blockSize; | |
| 195 | + } | |
| 196 | +} |
+++ src/main/java/itn/com/cmm/OptimalMsgResultDTO.java
... | ... | @@ -0,0 +1,37 @@ |
| 1 | +package itn.com.cmm; | |
| 2 | + | |
| 3 | +import java.util.List; | |
| 4 | + | |
| 5 | +import itn.let.mjo.event.service.MjonEventVO; | |
| 6 | +import lombok.Builder; | |
| 7 | +import lombok.Getter; | |
| 8 | +import lombok.Setter; | |
| 9 | +import lombok.ToString; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * | |
| 13 | + * @author : 이호영 | |
| 14 | + * @fileName : OptimalMsgResultDTO.java | |
| 15 | + * @date : 2024.11.26 | |
| 16 | + * @description : 이벤트 vo 생성 및 종료 vo 생성 | |
| 17 | + * =========================================================== | |
| 18 | + * DATE AUTHOR NOTE | |
| 19 | + * ----------------------------------------------------------- * | |
| 20 | + * 2024.11.26 이호영 최초 생성 | |
| 21 | + * | |
| 22 | + * | |
| 23 | + * | |
| 24 | + */ | |
| 25 | +@Getter | |
| 26 | +@Setter | |
| 27 | +@ToString | |
| 28 | +@Builder | |
| 29 | +public class OptimalMsgResultDTO{ | |
| 30 | + | |
| 31 | + private List<MjonMsgSendVO> optimalMsgList; | |
| 32 | + private MjonEventVO eventInfo; | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | +} |
--- src/main/java/itn/com/cmm/util/MJUtil.java
+++ src/main/java/itn/com/cmm/util/MJUtil.java
... | ... | @@ -144,7 +144,6 @@ |
| 144 | 144 |
date = date.replaceAll("-", "/");//날짜에 하이픈(-)을 슬러쉬(/)로 변환
|
| 145 | 145 |
|
| 146 | 146 |
SimpleDateFormat sdformat = new SimpleDateFormat("yyyy/MM/dd");
|
| 147 |
- System.out.println(getRealTime()); |
|
| 148 | 147 |
|
| 149 | 148 |
Date nowDate = sdformat.parse(getRealTime()); |
| 150 | 149 |
Date endDate = sdformat.parse(date); |
--- src/main/java/itn/com/cmm/util/MsgSendUtils.java
+++ src/main/java/itn/com/cmm/util/MsgSendUtils.java
... | ... | @@ -1,10 +1,9 @@ |
| 1 | 1 |
package itn.com.cmm.util; |
| 2 | 2 |
|
| 3 | 3 |
import java.io.UnsupportedEncodingException; |
| 4 |
-import java.math.BigDecimal; |
|
| 5 |
-import java.math.RoundingMode; |
|
| 6 | 4 |
import java.text.SimpleDateFormat; |
| 7 | 5 |
import java.util.ArrayList; |
| 6 |
+import java.util.Arrays; |
|
| 8 | 7 |
import java.util.Calendar; |
| 9 | 8 |
import java.util.Date; |
| 10 | 9 |
import java.util.HashMap; |
... | ... | @@ -18,14 +17,15 @@ |
| 18 | 17 |
import java.util.stream.Stream; |
| 19 | 18 |
|
| 20 | 19 |
import org.apache.commons.lang3.StringUtils; |
| 21 |
-import org.springframework.beans.factory.annotation.Autowired; |
|
| 22 | 20 |
import org.springframework.http.HttpStatus; |
| 23 | 21 |
|
| 24 | 22 |
import itn.com.cmm.MjonMsgSendVO; |
| 23 |
+import itn.com.cmm.OptimalMsgResultDTO; |
|
| 25 | 24 |
import itn.let.mail.service.StatusResponse; |
| 25 |
+import itn.let.mjo.event.service.MjonEventVO; |
|
| 26 | 26 |
import itn.let.mjo.msg.service.MjonMsgVO; |
| 27 |
+import itn.let.mjo.msgagent.service.MjonMsgAgentStsVO; |
|
| 27 | 28 |
import itn.let.mjo.spammsg.web.ComGetSpamStringParser; |
| 28 |
-import itn.let.module.base.PriceAndPoint; |
|
| 29 | 29 |
import itn.let.sym.site.service.JoinSettingVO; |
| 30 | 30 |
import itn.let.uss.umt.service.MberManageVO; |
| 31 | 31 |
import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -47,6 +47,12 @@ |
| 47 | 47 |
@Slf4j |
| 48 | 48 |
public final class MsgSendUtils {
|
| 49 | 49 |
|
| 50 |
+ // 단문 메세지 타입 |
|
| 51 |
+ public static final String SHORT_MSG_TYPE = "4"; |
|
| 52 |
+ // 장문 메세지 타입 |
|
| 53 |
+ public static final String LONG_MSG_TYPE = "6"; |
|
| 54 |
+ // 이벤트 최저 잔액 |
|
| 55 |
+ public static final double MIN_EVENT_REMAIN_CASH = 7.5; // 이벤트 최소 잔액 |
|
| 50 | 56 |
|
| 51 | 57 |
/** |
| 52 | 58 |
* @methodName : getSmsTxtBytes |
... | ... | @@ -81,28 +87,30 @@ |
| 81 | 87 |
*/ |
| 82 | 88 |
public static String getMsgTypeWithByteValidation(MjonMsgSendVO sendVO, String p_smsTxt) throws UnsupportedEncodingException {
|
| 83 | 89 |
|
| 84 |
- |
|
| 90 |
+ |
|
| 91 |
+ // // 내문자저장함에 저장 후 문자를 발송하는 경우 문자 타입이 숫자가 아닌 문자로 넘어와서 변경 처리함 |
|
| 92 |
+ // if ("P".equals(msgType) || "L".equals(msgType)) {
|
|
| 93 |
+ // msgType = "6"; |
|
| 94 |
+ // } else if ("S".equals(msgType)) {
|
|
| 95 |
+ // msgType = "4"; |
|
| 96 |
+ // } |
|
| 97 |
+ |
|
| 85 | 98 |
int smsTxtByte = getSmsTxtBytes(p_smsTxt); |
| 86 |
- String msgType = "4"; |
|
| 99 |
+ String msgType = SHORT_MSG_TYPE; |
|
| 87 | 100 |
|
| 88 |
- // // 내문자저장함에 저장 후 문자를 발송하는 경우 문자 타입이 숫자가 아닌 문자로 넘어와서 변경 처리함 |
|
| 89 |
- // if ("P".equals(msgType) || "L".equals(msgType)) {
|
|
| 90 |
- // msgType = "6"; |
|
| 91 |
- // } else if ("S".equals(msgType)) {
|
|
| 92 |
- // msgType = "4"; |
|
| 93 |
- // } |
|
| 94 |
- |
|
| 95 |
- // 그림 이미지가 첨부된 경우 장문으로 설정 |
|
| 96 |
- if (StringUtils.isNotEmpty(sendVO.getFilePath1())) {
|
|
| 97 |
- msgType = "6"; |
|
| 98 |
- } else if (smsTxtByte > 2000) {
|
|
| 99 |
- // 2000 Byte를 초과할 경우 에러 처리 (이 부분은 호출부에서 검사하도록 유지할 수도 있음) |
|
| 100 |
- return "INVALID"; // 이 값은 호출부에서 에러 처리를 하도록 활용할 수 있습니다. |
|
| 101 |
- } else if (smsTxtByte > 90) {
|
|
| 102 |
- // 90Byte 초과 시 장문으로 설정 |
|
| 103 |
- msgType = "6"; |
|
| 101 |
+ // 1. 2000 Byte 초과는 에러 처리 |
|
| 102 |
+ if (smsTxtByte > 2000) {
|
|
| 103 |
+ return "INVALID"; |
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 |
+ // 2. 첨부파일 여부 확인 (첨부파일이 있으면 장문으로 설정) |
|
| 107 |
+ if (StringUtils.isNotEmpty(sendVO.getFilePath1())) {
|
|
| 108 |
+ msgType = LONG_MSG_TYPE; |
|
| 109 |
+ } |
|
| 110 |
+ // 3. 문자 길이에 따라 메시지 타입 설정 (90 Byte 초과는 장문) |
|
| 111 |
+ else if (smsTxtByte > 90) {
|
|
| 112 |
+ msgType = LONG_MSG_TYPE; |
|
| 113 |
+ } |
|
| 106 | 114 |
return msgType; |
| 107 | 115 |
} |
| 108 | 116 |
|
... | ... | @@ -129,9 +137,9 @@ |
| 129 | 137 |
float price = 0; |
| 130 | 138 |
String msgType = mjonMsgVO.getMsgType(); |
| 131 | 139 |
|
| 132 |
- if ("4".equals(msgType)) {
|
|
| 140 |
+ if (SHORT_MSG_TYPE.equals(msgType)) {
|
|
| 133 | 141 |
price = shortPrice; |
| 134 |
- } else if ("6".equals(msgType)) {
|
|
| 142 |
+ } else if (LONG_MSG_TYPE.equals(msgType)) {
|
|
| 135 | 143 |
// 파일 첨부 여부에 따라 장문 단가 설정 |
| 136 | 144 |
if (mjonMsgVO.getFileName3() != null) {
|
| 137 | 145 |
price = picture3Price; |
... | ... | @@ -181,19 +189,18 @@ |
| 181 | 189 |
* @param mjonMsgVO |
| 182 | 190 |
* @param lists |
| 183 | 191 |
* @param statusResponse |
| 192 |
+ * @param agentSendCounts |
|
| 193 |
+ * @param sendRateList |
|
| 184 | 194 |
* @return |
| 185 | 195 |
* @throws Exception |
| 186 | 196 |
*/ |
| 187 |
- public static Boolean populateSendLists(MjonMsgVO mjonMsgVO, List<MjonMsgSendVO> mjonMsgSendListVO, StatusResponse statusResponse, List<String> resultSpamTxt) throws Exception{
|
|
| 197 |
+ public static Boolean populateSendLists(MjonMsgVO mjonMsgVO, List<MjonMsgSendVO> mjonMsgSendListVO |
|
| 198 |
+ , StatusResponse statusResponse, List<String> resultSpamTxt |
|
| 199 |
+ , Map<String, Integer> agentSendCounts, List<MjonMsgVO> sendRateList, String nextMsgGroupId) throws Exception{
|
|
| 188 | 200 |
|
| 189 | 201 |
log.info(" :: populateSendLists :: ");
|
| 190 | 202 |
|
| 191 | 203 |
|
| 192 |
- log.info(" + 예약여부 [{}]", mjonMsgVO.getReserveYn()); // 예약 여부
|
|
| 193 |
- log.info(" + 시간 [{}]", mjonMsgVO.getReqDate()); // 시간
|
|
| 194 |
- log.info(" + 분할체크 [{}]", mjonMsgVO.getDivideChk()); // 분할체크
|
|
| 195 |
- log.info(" + 간격(분) [{}]", mjonMsgVO.getDivideTime()); // 간격
|
|
| 196 |
- log.info(" + 몇 건씩 [{}]", mjonMsgVO.getDivideCnt()); // 몇 건식
|
|
| 197 | 204 |
|
| 198 | 205 |
|
| 199 | 206 |
// 예약 시간 기본값 설정 |
... | ... | @@ -230,12 +237,17 @@ |
| 230 | 237 |
boolean hasPerformedSpamCheck = false; // 치환 문자가 없는 경우, 스팸 체크가 한 번만 수행되도록 제어 |
| 231 | 238 |
boolean hasPerformedMsgType = false; // 치환 문자가 없는 경우, 스팸 체크가 한 번만 수행되도록 제어 |
| 232 | 239 |
|
| 240 |
+ String msgKind = mjonMsgVO.getMsgKind(); |
|
| 233 | 241 |
String smsTxtTemp = mjonMsgVO.getSmsTxt(); |
| 234 | 242 |
Boolean replaceYN = getReplaceYN(smsTxtTemp); |
| 235 | 243 |
|
| 236 | 244 |
String msgTypeResult = null; |
| 237 | 245 |
|
| 238 | 246 |
for (MjonMsgSendVO sendVO : mjonMsgSendListVO) {
|
| 247 |
+ |
|
| 248 |
+ sendVO.setCallFrom(mjonMsgVO.getCallFrom()); |
|
| 249 |
+ sendVO.setCallTo(sendVO.getPhone()); |
|
| 250 |
+ sendVO.setUserId(mjonMsgVO.getUserId()); |
|
| 239 | 251 |
|
| 240 | 252 |
String smsTxt = smsTxtTemp; |
| 241 | 253 |
// 치환 문자면 |
... | ... | @@ -255,46 +267,51 @@ |
| 255 | 267 |
} |
| 256 | 268 |
} |
| 257 | 269 |
|
| 258 |
- String smsSpamChkTxt = mjonMsgVO.getSmsTxt().replaceAll(String.valueOf((char) 13), ""); |
|
| 259 |
- // 스팸문자 체크 |
|
| 260 |
- // 치환문자가 아닐 경우 |
|
| 261 |
- if (!replaceYN && !hasPerformedSpamCheck) {
|
|
| 262 |
- checkSpamAndSetStatus(mjonMsgVO, smsSpamChkTxt, resultSpamTxt); |
|
| 263 |
- hasPerformedSpamCheck = true; // 스팸 체크가 한 번만 수행되도록 설정 |
|
| 264 |
- // 치환 문자가 있는 경우에는 spamChkSize 카운트까지만 수행 |
|
| 265 |
- } else if (replaceYN && sampleCounter < spamChkSize && !"Y".equals(mjonMsgVO.getSpamStatus())) {
|
|
| 266 |
- checkSpamAndSetStatus(mjonMsgVO, smsSpamChkTxt, resultSpamTxt); |
|
| 267 |
- sampleCounter++; |
|
| 270 |
+ String smsSpamChkTxt = smsTxt.replaceAll(String.valueOf((char) 13), ""); |
|
| 271 |
+ |
|
| 272 |
+ // == 치환 여부에 따라 처리 로직 분기 == |
|
| 273 |
+ // 치환 문자가 아닌 경우 |
|
| 274 |
+ if (!replaceYN) {
|
|
| 275 |
+ // 스팸 체크와 메시지 타입 체크 각각 한 번만 수행 |
|
| 276 |
+ if (!hasPerformedSpamCheck) {
|
|
| 277 |
+ checkSpamAndSetStatus(mjonMsgVO, smsSpamChkTxt, resultSpamTxt); |
|
| 278 |
+ hasPerformedSpamCheck = true; |
|
| 279 |
+ } |
|
| 280 |
+ if (!hasPerformedMsgType) {
|
|
| 281 |
+ msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 282 |
+ if ("INVALID".equals(msgTypeResult)) {
|
|
| 283 |
+ statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 284 |
+ return false; |
|
| 285 |
+ } |
|
| 286 |
+ hasPerformedMsgType = true; |
|
| 287 |
+ } |
|
| 288 |
+ } |
|
| 289 |
+ else |
|
| 290 |
+ {// 치환 문자인 경우
|
|
| 291 |
+ // 스팸 체크는 `spamChkSize`만큼 반복 수행 |
|
| 292 |
+ if (sampleCounter < spamChkSize && !"Y".equals(mjonMsgVO.getSpamStatus())) {
|
|
| 293 |
+ checkSpamAndSetStatus(mjonMsgVO, smsSpamChkTxt, resultSpamTxt); |
|
| 294 |
+ sampleCounter++; |
|
| 295 |
+ } |
|
| 296 |
+ |
|
| 297 |
+ // 메시지 타입 체크는 매번 수행 |
|
| 298 |
+ msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 299 |
+ if ("INVALID".equals(msgTypeResult)) {
|
|
| 300 |
+ statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 301 |
+ return false; |
|
| 302 |
+ } |
|
| 268 | 303 |
} |
| 304 |
+ |
|
| 305 |
+ |
|
| 269 | 306 |
sendVO.setSmsTxt(smsTxt); |
| 270 |
- |
|
| 271 |
- // 이미지 셋팅 |
|
| 272 |
- setImagePathsForMsgSendVO(mjonMsgVO, sendVO); |
|
| 273 |
- |
|
| 274 |
- |
|
| 275 |
- // msgType 셋팅 및 문자열 체크 |
|
| 276 |
- if (!replaceYN && !hasPerformedMsgType) {
|
|
| 277 |
- log.info(" 치환 X ");
|
|
| 278 |
- // byte 체크와 msgType 구하기 |
|
| 279 |
- msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 280 |
- if ("INVALID".equals(msgTypeResult)) {
|
|
| 281 |
- statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 282 |
- return false; |
|
| 283 |
- } |
|
| 284 |
- hasPerformedMsgType = true; // 스팸 체크가 한 번만 수행되도록 설정 |
|
| 285 |
- }else if(replaceYN){
|
|
| 286 |
- log.info(" 치환 O ");
|
|
| 287 |
- // byte 체크와 msgType 구하기 |
|
| 288 |
- msgTypeResult = getMsgTypeWithByteValidation(sendVO, smsTxt); |
|
| 289 |
- if ("INVALID".equals(msgTypeResult)) {
|
|
| 290 |
- statusResponseSet(statusResponse, HttpStatus.BAD_REQUEST, "문자 치환 후 전송 문자 길이를 초과하였습니다."); |
|
| 291 |
- return false; |
|
| 292 |
- } |
|
| 293 |
- } |
|
| 294 |
- |
|
| 295 | 307 |
sendVO.setMsgType(msgTypeResult); |
| 296 | 308 |
|
| 309 |
+ // 제목 셋팅 |
|
| 297 | 310 |
|
| 311 |
+ |
|
| 312 |
+ |
|
| 313 |
+ // 이미지 셋팅 |
|
| 314 |
+ setImagePathsForMsgSendVO(mjonMsgVO, sendVO); |
|
| 298 | 315 |
|
| 299 | 316 |
|
| 300 | 317 |
// 예약 여부 확인 |
... | ... | @@ -315,6 +332,16 @@ |
| 315 | 332 |
} |
| 316 | 333 |
|
| 317 | 334 |
|
| 335 |
+ // 전송사 코드 셋팅 |
|
| 336 |
+ String agentCode = "00".equals(mjonMsgVO.getAgentCode()) |
|
| 337 |
+ ? MsgSendUtils.assignAgentBasedOnCount(agentSendCounts, sendRateList) |
|
| 338 |
+ : mjonMsgVO.getAgentCode(); |
|
| 339 |
+ sendVO.setAgentCode(agentCode); |
|
| 340 |
+ |
|
| 341 |
+ sendVO.setMsgGroupId(nextMsgGroupId); |
|
| 342 |
+ |
|
| 343 |
+ |
|
| 344 |
+ |
|
| 318 | 345 |
|
| 319 | 346 |
|
| 320 | 347 |
|
... | ... | @@ -324,6 +351,14 @@ |
| 324 | 351 |
|
| 325 | 352 |
} |
| 326 | 353 |
|
| 354 |
+ /** |
|
| 355 |
+ * @methodName : setImagePathsForMsgSendVO |
|
| 356 |
+ * @author : 이호영 |
|
| 357 |
+ * @date : 2024.11.26 |
|
| 358 |
+ * @description : vo에 이미지 셋팅 |
|
| 359 |
+ * @param mjonMsgVO |
|
| 360 |
+ * @param sendVO |
|
| 361 |
+ */ |
|
| 327 | 362 |
private static void setImagePathsForMsgSendVO(MjonMsgVO mjonMsgVO, MjonMsgSendVO sendVO) {
|
| 328 | 363 |
int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt()); |
| 329 | 364 |
|
... | ... | @@ -493,6 +528,7 @@ |
| 493 | 528 |
float picture2Price = MsgSendUtils.getValidPrice(mberManageVO.getPicture2Price(), sysJoinSetVO.getPicture2Price()); |
| 494 | 529 |
float picture3Price = MsgSendUtils.getValidPrice(mberManageVO.getPicture3Price(), sysJoinSetVO.getPicture3Price()); |
| 495 | 530 |
|
| 531 |
+ |
|
| 496 | 532 |
// 각 메시지 타입에 따라 사용자 단가 설정 및 총 단가 계산 |
| 497 | 533 |
float totalPrice = 0.0f; |
| 498 | 534 |
|
... | ... | @@ -501,18 +537,17 @@ |
| 501 | 537 |
String eachPrice; |
| 502 | 538 |
|
| 503 | 539 |
switch (msgType) {
|
| 504 |
- case "4": // 단문 메시지 타입 |
|
| 540 |
+ case SHORT_MSG_TYPE: // 단문 메시지 타입 |
|
| 505 | 541 |
eachPrice = Float.toString(shortPrice); |
| 506 | 542 |
break; |
| 507 | 543 |
|
| 508 |
- case "6": // 장문 또는 이미지 메시지 타입 |
|
| 544 |
+ case LONG_MSG_TYPE: // 장문 또는 이미지 메시지 타입 |
|
| 509 | 545 |
eachPrice = getPicturePrice(sendVO, longPrice, picturePrice, picture2Price, picture3Price); |
| 510 | 546 |
break; |
| 511 | 547 |
|
| 512 | 548 |
default: |
| 513 | 549 |
// 기본값이 필요하다면 추가 가능 |
| 514 |
- eachPrice = "0"; |
|
| 515 |
- break; |
|
| 550 |
+ throw new IllegalArgumentException("setPriceforVO :: type Exception ");
|
|
| 516 | 551 |
} |
| 517 | 552 |
|
| 518 | 553 |
sendVO.setEachPrice(eachPrice); |
... | ... | @@ -531,46 +566,271 @@ |
| 531 | 566 |
* 이미지 파일 경로를 기준으로 적절한 가격을 반환하는 헬퍼 메소드. |
| 532 | 567 |
*/ |
| 533 | 568 |
private static String getPicturePrice(MjonMsgSendVO sendVO, float longPrice, float picturePrice, float picture2Price, float picture3Price) {
|
| 534 |
- if (StringUtils.isNotEmpty(sendVO.getFilePath3())) {
|
|
| 569 |
+ |
|
| 570 |
+ switch (sendVO.getFilePath3() != null ? "FILE3" : |
|
| 571 |
+ sendVO.getFilePath2() != null ? "FILE2" : |
|
| 572 |
+ sendVO.getFilePath1() != null ? "FILE1" : "NONE") {
|
|
| 573 |
+ case "FILE3": |
|
| 535 | 574 |
return Float.toString(picture3Price); |
| 536 |
- } else if (StringUtils.isNotEmpty(sendVO.getFilePath2())) {
|
|
| 575 |
+ case "FILE2": |
|
| 537 | 576 |
return Float.toString(picture2Price); |
| 538 |
- } else if (StringUtils.isNotEmpty(sendVO.getFilePath1())) {
|
|
| 577 |
+ case "FILE1": |
|
| 539 | 578 |
return Float.toString(picturePrice); |
| 540 |
- } else {
|
|
| 579 |
+ default: |
|
| 541 | 580 |
return Float.toString(longPrice); |
| 581 |
+ } |
|
| 582 |
+ |
|
| 583 |
+ } |
|
| 584 |
+ |
|
| 585 |
+ /** |
|
| 586 |
+ * @methodName : getOptimalMsgList |
|
| 587 |
+ * @author : 이호영 |
|
| 588 |
+ * @date : 2024.11.26 |
|
| 589 |
+ * @description : 주어진 이벤트 정보와 메시지 리스트를 기반으로, 잔액 내에서 최적의 메시지 리스트를 생성하고 결과를 반환합니다. |
|
| 590 |
+ * 만약 잔액이 부족하거나 이벤트가 종료된 상태라면, 이벤트 종료 정보를 포함하여 반환합니다. |
|
| 591 |
+ * |
|
| 592 |
+ * @param eventMberInfo 이벤트 정보 객체 (MjonEventVO). 이벤트 상태 및 잔액 정보를 포함. |
|
| 593 |
+ * @param mjonMsgSendVOList 최적화를 수행할 메시지 리스트 (List<MjonMsgSendVO>). |
|
| 594 |
+ * @return OptimalMsgResultDTO 최적 메시지 리스트와 이벤트 상태 정보를 포함한 DTO 객체. |
|
| 595 |
+ * @throws Exception 메시지 단가 계산 오류 또는 기타 처리 중 발생한 예외를 상위로 전달. |
|
| 596 |
+ */ |
|
| 597 |
+ public static OptimalMsgResultDTO getOptimalMsgList( |
|
| 598 |
+ MjonEventVO eventMberInfo, |
|
| 599 |
+ List<MjonMsgSendVO> mjonMsgSendVOList) throws Exception {
|
|
| 600 |
+ |
|
| 601 |
+ // 최적의 메시지 리스트를 담을 리스트 |
|
| 602 |
+ List<MjonMsgSendVO> optimalList = new ArrayList<>(); |
|
| 603 |
+ |
|
| 604 |
+ // 이벤트 정보가 없는 경우 |
|
| 605 |
+ if (eventMberInfo == null) {
|
|
| 606 |
+ return OptimalMsgResultDTO.builder() |
|
| 607 |
+ .optimalMsgList(optimalList) |
|
| 608 |
+ .eventInfo(null) |
|
| 609 |
+ .build(); |
|
| 610 |
+ } |
|
| 611 |
+ |
|
| 612 |
+ // 이벤트 잔액과 종료 조건 확인 |
|
| 613 |
+ double targetCash = eventMberInfo.getEventRemainCash(); |
|
| 614 |
+ String eventEndDate = eventMberInfo.getEventEndDate(); |
|
| 615 |
+ |
|
| 616 |
+ if (isEventExpired(targetCash, eventEndDate)) {
|
|
| 617 |
+ MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, targetCash); |
|
| 618 |
+ return OptimalMsgResultDTO.builder() |
|
| 619 |
+ .optimalMsgList(optimalList) |
|
| 620 |
+ .eventInfo(returnEventMberInfo) |
|
| 621 |
+ .build(); |
|
| 622 |
+ } |
|
| 623 |
+ |
|
| 624 |
+ // 단가 설정 |
|
| 625 |
+ float shortPrice = Float.parseFloat(eventMberInfo.getEventShortPrice()); |
|
| 626 |
+ float longPrice = Float.parseFloat(eventMberInfo.getEventLongPrice()); |
|
| 627 |
+ float picturePrice = Float.parseFloat(eventMberInfo.getEventPicturePrice()); |
|
| 628 |
+ float picture2Price = Float.parseFloat(eventMberInfo.getEventPicture2Price()); |
|
| 629 |
+ float picture3Price = Float.parseFloat(eventMberInfo.getEventPicture3Price()); |
|
| 630 |
+ |
|
| 631 |
+ // 최적의 메시지 리스트 생성 |
|
| 632 |
+ double sum = 0.0; |
|
| 633 |
+ Iterator<MjonMsgSendVO> iterator = mjonMsgSendVOList.iterator(); |
|
| 634 |
+ |
|
| 635 |
+ while (iterator.hasNext()) {
|
|
| 636 |
+ MjonMsgSendVO msg = iterator.next(); |
|
| 637 |
+ |
|
| 638 |
+ // 단가 계산 및 예외 처리 |
|
| 639 |
+ String eachPrice = getEachPriceOrThrow(msg, shortPrice, longPrice, picturePrice, picture2Price, picture3Price); |
|
| 640 |
+ |
|
| 641 |
+ float floatEachPrice = Float.parseFloat(eachPrice); |
|
| 642 |
+ |
|
| 643 |
+ // 최적의 메시지 리스트에 추가 |
|
| 644 |
+ if (sum + floatEachPrice <= targetCash) {
|
|
| 645 |
+ sum += floatEachPrice; |
|
| 646 |
+ msg.setEachPrice(eachPrice); |
|
| 647 |
+ optimalList.add(msg); |
|
| 648 |
+ iterator.remove(); |
|
| 649 |
+ } else {
|
|
| 650 |
+ break; // 예산 초과로 추가 불가능 |
|
| 651 |
+ } |
|
| 652 |
+ } |
|
| 653 |
+ |
|
| 654 |
+ // 잔액 부족 시 이벤트 종료 처리하는 VO 생성 |
|
| 655 |
+ double remainAmt = targetCash - sum; |
|
| 656 |
+ log.info("remainAmt :: [{}]", remainAmt);
|
|
| 657 |
+ if (remainAmt < MIN_EVENT_REMAIN_CASH) {
|
|
| 658 |
+ MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, remainAmt); |
|
| 659 |
+ return OptimalMsgResultDTO.builder() |
|
| 660 |
+ .optimalMsgList(optimalList) |
|
| 661 |
+ .eventInfo(returnEventMberInfo) |
|
| 662 |
+ .build(); |
|
| 663 |
+ } |
|
| 664 |
+ |
|
| 665 |
+ // 결과 반환 |
|
| 666 |
+ return OptimalMsgResultDTO.builder() |
|
| 667 |
+ .optimalMsgList(optimalList) |
|
| 668 |
+ .eventInfo(null) |
|
| 669 |
+ .build(); |
|
| 670 |
+ } |
|
| 671 |
+ |
|
| 672 |
+ /** |
|
| 673 |
+ * @methodName : getEachPriceOrThrow |
|
| 674 |
+ * @author : 이호영 |
|
| 675 |
+ * @date : 2024.11.26 |
|
| 676 |
+ * @description : |
|
| 677 |
+ * @param msg |
|
| 678 |
+ * @param shortPrice |
|
| 679 |
+ * @param longPrice |
|
| 680 |
+ * @param picturePrice |
|
| 681 |
+ * @param picture2Price |
|
| 682 |
+ * @param picture3Price |
|
| 683 |
+ * @return |
|
| 684 |
+ */ |
|
| 685 |
+ private static String getEachPriceOrThrow( |
|
| 686 |
+ MjonMsgSendVO msg, |
|
| 687 |
+ float shortPrice, |
|
| 688 |
+ float longPrice, |
|
| 689 |
+ float picturePrice, |
|
| 690 |
+ float picture2Price, |
|
| 691 |
+ float picture3Price) {
|
|
| 692 |
+ |
|
| 693 |
+ switch (msg.getMsgType()) {
|
|
| 694 |
+ case SHORT_MSG_TYPE: |
|
| 695 |
+ return Float.toString(shortPrice); |
|
| 696 |
+ case LONG_MSG_TYPE: |
|
| 697 |
+ return getPicturePrice(msg, longPrice, picturePrice, picture2Price, picture3Price); |
|
| 698 |
+ default: |
|
| 699 |
+ throw new IllegalArgumentException("Unsupported message type: " + msg.getMsgType());
|
|
| 542 | 700 |
} |
| 543 | 701 |
} |
| 544 | 702 |
|
| 545 |
- public static List<MjonMsgSendVO> getOptimalMsgList(double totalPrice, double eventRemainCash, |
|
| 546 |
- List<MjonMsgSendVO> mjonMsgSendVOList) {
|
|
| 547 |
- |
|
| 548 |
- double targetCash = eventRemainCash; |
|
| 549 |
- |
|
| 550 |
- // 최적의 리스트를 구성하기 위한 빈 리스트 생성 |
|
| 551 |
- List<MjonMsgSendVO> optimalList = new ArrayList<>(); |
|
| 552 |
- double sum = 0.0; |
|
| 703 |
+ private static boolean isEventExpired(double targetCash, String eventEndDate) throws Exception {
|
|
| 704 |
+ return !MJUtil.getCompareDate(eventEndDate) || targetCash < MIN_EVENT_REMAIN_CASH; |
|
| 705 |
+ } |
|
| 553 | 706 |
|
| 554 |
- // 원본 리스트의 요소를 순회하며 조건에 맞는 항목을 최적 리스트에 추가 |
|
| 555 |
- Iterator<MjonMsgSendVO> iterator = mjonMsgSendVOList.iterator(); |
|
| 556 |
- while (iterator.hasNext()) {
|
|
| 557 |
- MjonMsgSendVO msg = iterator.next(); |
|
| 558 |
- double eachPrice = Double.parseDouble(msg.getEachPrice()); |
|
| 559 |
- |
|
| 560 |
- // sum + eachPrice가 정확히 targetCash와 같거나 작을 때만 추가하고 원본에서 제거 |
|
| 561 |
- if (sum + eachPrice <= targetCash) {
|
|
| 562 |
- sum += eachPrice; |
|
| 563 |
- optimalList.add(msg); |
|
| 564 |
- iterator.remove(); // 원본 리스트에서 해당 요소 제거 |
|
| 565 |
- } else {
|
|
| 566 |
- break; // 초과하지 않도록, 더 이상 추가할 수 없는 경우 종료 |
|
| 707 |
+ /** |
|
| 708 |
+ * @methodName : terminateEvent |
|
| 709 |
+ * @author : 이호영 |
|
| 710 |
+ * @date : 2024.11.26 |
|
| 711 |
+ * @description : 이벤트 종료 VO 생성 |
|
| 712 |
+ * @param eventMberInfo |
|
| 713 |
+ * @param targetCash |
|
| 714 |
+ * @return |
|
| 715 |
+ */ |
|
| 716 |
+ private static MjonEventVO terminateEvent(MjonEventVO eventMberInfo, double targetCash) {
|
|
| 717 |
+ // TODO Auto-generated method stub |
|
| 718 |
+ |
|
| 719 |
+ // 이벤트 상태를 종료로 변경 |
|
| 720 |
+ MjonEventVO returnEventMberInfo = new MjonEventVO(); |
|
| 721 |
+ returnEventMberInfo.setEventInfoId(eventMberInfo.getEventInfoId()); |
|
| 722 |
+ returnEventMberInfo.setEventStatus("E");
|
|
| 723 |
+ returnEventMberInfo.setEventRemainCash(targetCash); |
|
| 724 |
+ returnEventMberInfo.setEventMemo("발송 최소 금액("+ MIN_EVENT_REMAIN_CASH +") 부족 혹은 이벤트 종료일 초과되어 이벤트 종료 시킴");
|
|
| 725 |
+ return returnEventMberInfo; |
|
| 726 |
+ } |
|
| 727 |
+ |
|
| 728 |
+ /** |
|
| 729 |
+ * @methodName : handleHotlineAgentRate |
|
| 730 |
+ * @author : 이호영 |
|
| 731 |
+ * @date : 2024.11.26 |
|
| 732 |
+ * @description : 전용 전송사 비율이 0이면 대표 전송사로 수정 |
|
| 733 |
+ * @param userInfo |
|
| 734 |
+ * @param tmp |
|
| 735 |
+ * @param hotlineAgentCode |
|
| 736 |
+ * @return |
|
| 737 |
+ */ |
|
| 738 |
+ public static String handleHotlineAgentRate(MberManageVO userInfo, MjonMsgAgentStsVO tmp, String hotlineAgentCode) {
|
|
| 739 |
+ String sendRate = tmp.getSendRate(); |
|
| 740 |
+ String repAgent = tmp.getRepAgent(); |
|
| 741 |
+ String useYn = tmp.getUseYn(); |
|
| 742 |
+ |
|
| 743 |
+ // 블라인드 코드가 'N'인 경우 전송 비율 및 사용 가능 여부 확인 |
|
| 744 |
+ if ("N".equals(userInfo.getBlineCode())) {
|
|
| 745 |
+ // 전송 비율이 0이거나 사용 불가인 경우 대표 전송사로 변경 |
|
| 746 |
+ if ("0".equals(sendRate) || "N".equals(useYn)) {
|
|
| 747 |
+ hotlineAgentCode = repAgent; |
|
| 567 | 748 |
} |
| 568 | 749 |
} |
| 569 |
- log.info(" + targetCash :: [{}]", targetCash);
|
|
| 570 |
- log.info(" + sum :: [{}]", sum);
|
|
| 571 |
- |
|
| 572 |
- // 최적 리스트 반환 |
|
| 573 |
- return optimalList; |
|
| 574 |
- |
|
| 750 |
+ |
|
| 751 |
+ return hotlineAgentCode; // 변경된 hotlineAgentCode 반환 |
|
| 575 | 752 |
} |
| 753 |
+ |
|
| 754 |
+ |
|
| 755 |
+ /** |
|
| 756 |
+ * @methodName : initializeAgentSendCounts |
|
| 757 |
+ * @author : 이호영 |
|
| 758 |
+ * @date : 2024.11.26 |
|
| 759 |
+ * @description : 전송사별 코드로 map 초기화 하기 |
|
| 760 |
+ * @return |
|
| 761 |
+ */ |
|
| 762 |
+ public static Map<String, Integer> initializeAgentSendCounts() {
|
|
| 763 |
+ Map<String, Integer> agentSendCounts = new HashMap<>(); |
|
| 764 |
+ agentSendCounts.put("01", 0); // 아이하트
|
|
| 765 |
+ agentSendCounts.put("02", 0); // 현대 퓨쳐넷
|
|
| 766 |
+ agentSendCounts.put("03", 0); // 아이엠오
|
|
| 767 |
+ agentSendCounts.put("04", 0); // 비즈뿌리오
|
|
| 768 |
+ agentSendCounts.put("05", 0); // 제이제이
|
|
| 769 |
+ agentSendCounts.put("07", 0); // 인비토
|
|
| 770 |
+ return agentSendCounts; |
|
| 771 |
+ } |
|
| 772 |
+ |
|
| 773 |
+ |
|
| 774 |
+ /** |
|
| 775 |
+ * @methodName : calculateSendCounts |
|
| 776 |
+ * @author : 이호영 |
|
| 777 |
+ * @date : 2024.11.26 |
|
| 778 |
+ * @description : agentSendCounts에 있는 에이젼트 map에 전송사 비율에 따라 카운트 put 하기 |
|
| 779 |
+ * @param agentSendCounts |
|
| 780 |
+ * @param sendRate |
|
| 781 |
+ * @param finalSize |
|
| 782 |
+ */ |
|
| 783 |
+ public static void calculateSendCounts(Map<String, Integer> agentSendCounts, MjonMsgVO sendRate, int finalSize) {
|
|
| 784 |
+ String agentCode = sendRate.getAgentCode(); |
|
| 785 |
+ float sendRatePercentage = Float.parseFloat(sendRate.getSendRate()); |
|
| 786 |
+ |
|
| 787 |
+ int sendCount = Math.round(finalSize * sendRatePercentage); |
|
| 788 |
+ |
|
| 789 |
+ if (agentSendCounts.containsKey(agentCode)) {
|
|
| 790 |
+ agentSendCounts.put(agentCode, sendCount); |
|
| 791 |
+ } |
|
| 792 |
+ } |
|
| 793 |
+ |
|
| 794 |
+ /** |
|
| 795 |
+ * @methodName : assignAgentBasedOnCount |
|
| 796 |
+ * @author : 이호영 |
|
| 797 |
+ * @date : 2024.11.26 |
|
| 798 |
+ * @description : initializeAgentSendCounts()에서 만든 map으로 발송 agent 데이터 Set |
|
| 799 |
+ * @param agentSendCounts |
|
| 800 |
+ * @param sendRateList |
|
| 801 |
+ * @return |
|
| 802 |
+ */ |
|
| 803 |
+ public static String assignAgentBasedOnCount(Map<String, Integer> agentSendCounts, List<MjonMsgVO> sendRateList) {
|
|
| 804 |
+ // 전송사 코드 순서대로 확인 :: initializeAgentSendCounts 메소드와 맞춰야함 |
|
| 805 |
+ List<String> agentCodes = Arrays.asList("01", "02", "03", "04", "05", "07");
|
|
| 806 |
+ |
|
| 807 |
+ // 전송 가능한 코드 찾기 |
|
| 808 |
+ for (String agentCode : agentCodes) {
|
|
| 809 |
+ if (agentSendCounts.get(agentCode) > 0) {
|
|
| 810 |
+ agentSendCounts.put(agentCode, agentSendCounts.get(agentCode) - 1); |
|
| 811 |
+ return agentCode; |
|
| 812 |
+ } |
|
| 813 |
+ } |
|
| 814 |
+ |
|
| 815 |
+ // 모든 코드의 전송 가능 횟수가 0이면 대표 전송사로 할당 |
|
| 816 |
+ return sendRateList.get(0).getRepAgent(); |
|
| 817 |
+ } |
|
| 818 |
+ |
|
| 819 |
+ |
|
| 820 |
+ |
|
| 821 |
+ |
|
| 822 |
+ |
|
| 823 |
+ |
|
| 824 |
+ |
|
| 825 |
+ |
|
| 826 |
+ |
|
| 827 |
+ |
|
| 828 |
+ |
|
| 829 |
+ |
|
| 830 |
+ |
|
| 831 |
+ |
|
| 832 |
+ |
|
| 833 |
+ |
|
| 834 |
+ |
|
| 835 |
+ |
|
| 576 | 836 |
} |
--- src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataDAO.java
+++ src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataDAO.java
... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 |
import org.springframework.stereotype.Repository; |
| 6 | 6 |
|
| 7 | 7 |
import egovframework.rte.psl.dataaccess.EgovAbstractDAO; |
| 8 |
+import itn.com.cmm.MjonMsgSendVO; |
|
| 8 | 9 |
import itn.let.lett.service.LetterVO; |
| 9 | 10 |
import itn.let.mjo.addr.service.AddrVO; |
| 10 | 11 |
import itn.let.mjo.msg.service.MjonMsgVO; |
... | ... | @@ -371,5 +372,12 @@ |
| 371 | 372 |
public List<MjonMsgVO> selectPayUserSumFaxList(MjonMsgVO mjonMsgVO) throws Exception{
|
| 372 | 373 |
return (List<MjonMsgVO>) list("mjonMsgDAO.selectPayUserSumFaxList",mjonMsgVO);
|
| 373 | 374 |
} |
| 375 |
+ |
|
| 376 |
+ |
|
| 377 |
+ public int insertMsgDataInfo_advc(List<MjonMsgSendVO> mjonMsgSendVOList) {
|
|
| 378 |
+ //단문 전송 |
|
| 379 |
+ int result = update("mjonMsgDAO.insertMsgData_advc", mjonMsgSendVOList);
|
|
| 380 |
+ return result; |
|
| 381 |
+ } |
|
| 374 | 382 |
|
| 375 | 383 |
} |
--- src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
+++ src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
... | ... | @@ -22,12 +22,15 @@ |
| 22 | 22 |
import org.springframework.stereotype.Service; |
| 23 | 23 |
import org.springframework.web.servlet.ModelAndView; |
| 24 | 24 |
|
| 25 |
+import egovframework.com.idgen.CustomIdGnrService; |
|
| 25 | 26 |
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl; |
| 27 |
+import egovframework.rte.fdl.cmmn.exception.FdlException; |
|
| 26 | 28 |
import egovframework.rte.fdl.idgnr.EgovIdGnrService; |
| 27 | 29 |
import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper; |
| 28 | 30 |
import egovframework.rte.psl.dataaccess.util.EgovMap; |
| 29 | 31 |
import itn.com.cmm.LoginVO; |
| 30 | 32 |
import itn.com.cmm.MjonMsgSendVO; |
| 33 |
+import itn.com.cmm.OptimalMsgResultDTO; |
|
| 31 | 34 |
import itn.com.cmm.util.MJUtil; |
| 32 | 35 |
import itn.com.cmm.util.MsgSendUtils; |
| 33 | 36 |
import itn.com.cmm.util.StringUtil; |
... | ... | @@ -95,6 +98,9 @@ |
| 95 | 98 |
|
| 96 | 99 |
@Resource(name = "egovMjonMsgIdGnrService") |
| 97 | 100 |
private EgovIdGnrService idgenMsgId; |
| 101 |
+ |
|
| 102 |
+ @Resource(name = "egovMjonMsgIdCGnrService") |
|
| 103 |
+ private CustomIdGnrService idgenMsgCId; |
|
| 98 | 104 |
|
| 99 | 105 |
@Resource(name = "egovMjonMsgGroupIdGnrService") |
| 100 | 106 |
private EgovIdGnrService idgenMjonMsgGroupId; |
... | ... | @@ -4033,86 +4039,7 @@ |
| 4033 | 4039 |
return statusResponse; |
| 4034 | 4040 |
} |
| 4035 | 4041 |
|
| 4036 |
- log.debug(" + mjonMsgVO.getFileCnt() :: [{}]", mjonMsgVO.getFileCnt());
|
|
| 4037 |
- |
|
| 4038 |
- |
|
| 4039 |
- /* |
|
| 4040 |
- * 화면에서 넘어오는 단가 금액 및 총 결제 캐시 금액 체크 해주기 |
|
| 4041 |
- * 검증을 위해서 시스템 단가, 회원 협의 단가, 이벤트 단가 정보 조회 |
|
| 4042 |
- * 조회 단가를 이용하여 총 결제 캐시 금액 계산 |
|
| 4043 |
- * 파라미터로 넘어온 개별단가(eachPrice), 총 결제캐시(totPrice)를 비요하여 동일하지 않으면 컨트롤러에서 계산한 금액으로 입력해줌. |
|
| 4044 |
- */ |
|
| 4045 |
- |
|
| 4046 |
- |
|
| 4047 |
- ///////////////////////////////////////////////////////////////////////////// |
|
| 4048 |
- // 금액 관련은 끝에서 이벤트 발송 / 기존금액 박송으로 나눠야하기 때문에 나중에 수정 |
|
| 4049 |
- ///////////////////////////////////////////////////////////////////////////// |
|
| 4050 |
- /* |
|
| 4051 |
- |
|
| 4052 |
- |
|
| 4053 |
- // 기존 소수점 2째자리에서 반올림하였으나, 정책 변경으로 소수점 버림 처리함 |
|
| 4054 |
-// boolean compareEndDate = false; |
|
| 4055 |
- float paramEachPrice = Float.parseFloat(mjonMsgVO.getEachPrice()); |
|
| 4056 |
- |
|
| 4057 |
- |
|
| 4058 |
- |
|
| 4059 |
- MjonEventVO mjonEventVO = new MjonEventVO(); |
|
| 4060 |
- mjonEventVO.setMberId(userId); |
|
| 4061 |
- |
|
| 4062 |
- MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo(mjonEventVO); |
|
| 4063 |
- // 호출부에서 handleEventStatus를 호출하고 예외 처리를 추가 |
|
| 4064 |
- |
|
| 4065 |
- // 기존 컨트롤러 2352 라인 |
|
| 4066 |
- if (eventMberInfo != null) {
|
|
| 4067 |
- String eventEndDate = eventMberInfo.getEventEndDate(); |
|
| 4068 |
- boolean compareEndDate = MJUtil.getCompareDate(eventEndDate); |
|
| 4069 |
- boolean isSuccess = handleEventStatus(eventMberInfo, paramEachPrice, mjonEventVO, compareEndDate); |
|
| 4070 |
- |
|
| 4071 |
- if (!isSuccess) {
|
|
| 4072 |
- // 예외가 발생했을 때의 리턴 처리 |
|
| 4073 |
- return new StatusResponse(HttpStatus.INTERNAL_SERVER_ERROR, "이벤트 상태 처리 중 오류가 발생했습니다."); |
|
| 4074 |
- } |
|
| 4075 |
- // 이벤트 진행 회원의 발송 단가 처리 |
|
| 4076 |
- if("Y".equals(eventMberInfo.getEventStatus()) && compareEndDate) {
|
|
| 4077 |
- shortPrice = Float.parseFloat(eventMberInfo.getEventShortPrice()); |
|
| 4078 |
- longPrice = Float.parseFloat(eventMberInfo.getEventLongPrice()); |
|
| 4079 |
- picturePrice = Float.parseFloat(eventMberInfo.getEventPicturePrice()); |
|
| 4080 |
- picture2Price = Float.parseFloat(eventMberInfo.getEventPicture2Price()); |
|
| 4081 |
- picture3Price = Float.parseFloat(eventMberInfo.getEventPicture3Price()); |
|
| 4082 |
- } |
|
| 4083 |
- } |
|
| 4084 |
- |
|
| 4085 |
- |
|
| 4086 |
- |
|
| 4087 |
- |
|
| 4088 |
- |
|
| 4089 |
- // 토탈금액 "," 리플레이스 처리 |
|
| 4090 |
- mjonMsgVO.setTotPrice(mjonMsgVO.getTotPrice().replaceAll(",", ""));
|
|
| 4091 |
- |
|
| 4092 |
- // 각 문자 종류별 단가 설정 |
|
| 4093 |
- float tmpEachPrice = MsgSendUtils.determinePriceByMsgType(mjonMsgVO, shortPrice, longPrice, picturePrice, picture2Price, picture3Price); |
|
| 4094 |
- mjonMsgVO.setEachPrice(Float.toString(tmpEachPrice)); |
|
| 4095 |
- |
|
| 4096 |
- // 수신자 총 수 * 단가를 통해 총 결제 금액 계산 |
|
| 4097 |
- int tmpTotCallCnt = mjonMsgVO.getCallToList().length; |
|
| 4098 |
- float tmpTotPrice = tmpTotCallCnt * tmpEachPrice; |
|
| 4099 |
- mjonMsgVO.setTotPrice(Float.toString(tmpTotPrice)); |
|
| 4100 |
-*/ |
|
| 4101 |
- ///////////////////////////////////////////////////////////////////////////// |
|
| 4102 |
- // 금액 관련은 끝에서 이벤트 발송 / 기존금액 박송으로 나눠야하기 때문에 나중에 수정 |
|
| 4103 |
- ///////////////////////////////////////////////////////////////////////////// |
|
| 4104 |
- |
|
| 4105 |
- |
|
| 4106 |
- //////////////////////////////////////////////// |
|
| 4107 |
- // 치환 여부 |
|
| 4108 |
- //////////////////////////////////////////////// |
|
| 4109 | 4042 |
List<MjonMsgSendVO> mjonMsgSendVOList = mjonMsgVO.getMjonMsgSendVOList(); |
| 4110 |
-// if (MsgSendUtils.isRepleasYN(mjonMsgVO)) {
|
|
| 4111 |
- |
|
| 4112 |
-// if (!MsgSendUtils.validateReplacementData(mjonMsgVO, mjonMsgTabulVO)) {
|
|
| 4113 |
-// //특정문구 일괄변환 치환문자 데이터가 없습니다. |
|
| 4114 |
-// return statusResponse; // 유효성 검사 실패 시 처리 |
|
| 4115 |
-// } |
|
| 4116 | 4043 |
|
| 4117 | 4044 |
|
| 4118 | 4045 |
// 삭제 전 리스트 크기 저장 |
... | ... | @@ -4126,40 +4053,53 @@ |
| 4126 | 4053 |
int finalSize = mjonMsgSendVOList.size(); |
| 4127 | 4054 |
// 삭제된 건 수 계산 |
| 4128 | 4055 |
int deletedCount = initialSize - finalSize; |
| 4129 |
-// log.info(" +삭제된 건수 :: [{}]",deletedCount);
|
|
| 4056 |
+ |
|
| 4057 |
+ |
|
| 4058 |
+ |
|
| 4059 |
+ |
|
| 4060 |
+ |
|
| 4061 |
+ |
|
| 4062 |
+ |
|
| 4130 | 4063 |
|
| 4131 | 4064 |
|
| 4132 |
-// long startTime = System.nanoTime(); // 시작 시간 측정 |
|
| 4065 |
+ // 전용 전송사 코드 및 대표 전송사 조회 |
|
| 4066 |
+ MberManageVO userInfo = mjonMsgDataDAO.selectMberManageInfo(userId); |
|
| 4067 |
+ String hotlineAgentCode = userInfo.getHotlineAgentCode(); |
|
| 4068 |
+ |
|
| 4069 |
+ // 핫라인 전송사 처리 |
|
| 4070 |
+ if (!"00".equals(hotlineAgentCode)) {
|
|
| 4071 |
+ hotlineAgentCode = handleHotlineAgent(mjonMsgVO, hotlineAgentCode, userInfo); |
|
| 4072 |
+ log.info("Hotline agent code processed: {}", hotlineAgentCode);
|
|
| 4073 |
+ } |
|
| 4133 | 4074 |
|
| 4075 |
+ // 전송사별 전송 수 초기화 |
|
| 4076 |
+ Map<String, Integer> agentSendCounts = MsgSendUtils.initializeAgentSendCounts(); |
|
| 4077 |
+ |
|
| 4078 |
+ // 수신자 총 명수 기준으로 전송사 비율 처리 |
|
| 4079 |
+ // 전송사별 배분률 조회 |
|
| 4080 |
+ List<MjonMsgVO> sendRateList = mjonMsgDataDAO.selectSendAgentList(mjonMsgVO); |
|
| 4081 |
+ |
|
| 4082 |
+ // finalSize :: 수신거부 번호 제거 후 총 수신자 수 |
|
| 4083 |
+ if (finalSize >= 10) {
|
|
| 4084 |
+ // 전송사별 발송 비율 계산 |
|
| 4085 |
+ for (MjonMsgVO sendRate : sendRateList) {
|
|
| 4086 |
+ MsgSendUtils.calculateSendCounts(agentSendCounts, sendRate, finalSize); |
|
| 4087 |
+ } |
|
| 4088 |
+ } |
|
| 4089 |
+ |
|
| 4090 |
+ mjonMsgVO.setAgentCode(hotlineAgentCode); |
|
| 4091 |
+ |
|
| 4134 | 4092 |
// smstxt 치환 및 스팸체크 후 mjonMsgSendVOList 에 add() |
| 4135 | 4093 |
List<String> resultSpamTxt = mjonMsgDataService.selectSpamKeywordList(); |
| 4136 |
- if(!MsgSendUtils.populateSendLists(mjonMsgVO, mjonMsgSendVOList, statusResponse, resultSpamTxt)) {;
|
|
| 4094 |
+ // msgGroupId 생성 |
|
| 4095 |
+ String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId(); |
|
| 4096 |
+ if(!MsgSendUtils.populateSendLists(mjonMsgVO, mjonMsgSendVOList, statusResponse, resultSpamTxt |
|
| 4097 |
+ , agentSendCounts, sendRateList, nextMsgGroupId)) {;
|
|
| 4137 | 4098 |
//문자 치환 후 전송 문자 길이를 초과하였습니다. |
| 4138 | 4099 |
//문자 치환 중 오류가 발생하였습니다. |
| 4139 | 4100 |
return statusResponse; |
| 4140 | 4101 |
} |
| 4141 |
- mjonMsgSendVOList.stream().forEach(t-> System.out.println(" + ReqDate :: "+t.getReqDate()));
|
|
| 4142 | 4102 |
|
| 4143 |
-// long endTime = System.nanoTime(); // 종료 시간 측정 |
|
| 4144 |
-// long duration = endTime - startTime; // 실행 시간 계산 (나노초) |
|
| 4145 |
- |
|
| 4146 |
-// // 나노초를 초와 분으로 변환 |
|
| 4147 |
-// long seconds = duration / 1_000_000_000; |
|
| 4148 |
-// long minutes = seconds / 60; |
|
| 4149 |
-// seconds = seconds % 60; // 분으로 나누고 남은 초 계산 |
|
| 4150 |
- |
|
| 4151 |
-// System.out.println("Execution time: " + minutes + " minutes " + seconds + " seconds");
|
|
| 4152 |
- |
|
| 4153 |
- |
|
| 4154 |
- |
|
| 4155 |
- |
|
| 4156 |
- |
|
| 4157 |
- |
|
| 4158 |
- |
|
| 4159 |
- |
|
| 4160 |
- |
|
| 4161 |
- |
|
| 4162 |
- |
|
| 4163 | 4103 |
|
| 4164 | 4104 |
//1.시스템 기본 단가 정보 불러오기 |
| 4165 | 4105 |
JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo(); |
... | ... | @@ -4168,14 +4108,103 @@ |
| 4168 | 4108 |
MsgSendUtils.setPriceforVO(mjonMsgVO, mjonMsgSendVOList, sysJoinSetVO, mberManageVO); |
| 4169 | 4109 |
|
| 4170 | 4110 |
|
| 4111 |
+ |
|
| 4171 | 4112 |
|
| 4113 |
+ |
|
| 4114 |
+ /*mjonMsgSendVOList.parallelStream().forEach(t -> {
|
|
| 4115 |
+ try {
|
|
| 4116 |
+ t.setMsgId(idgenMsgId.getNextStringId()); |
|
| 4117 |
+ } catch (FdlException e) {
|
|
| 4118 |
+ log.error("MsgId 생성 중 오류 발생", e);
|
|
| 4119 |
+ } |
|
| 4120 |
+ });*/ |
|
| 4121 |
+ List<String> idList = idgenMsgCId.getNextStringId(mjonMsgSendVOList.size()); |
|
| 4122 |
+// System.out.println(" idList.size() : " + idList.size());
|
|
| 4123 |
+// System.out.println(" idList : " + idList);
|
|
| 4124 |
+ for (int i = 0; i < mjonMsgSendVOList.size(); i++) {
|
|
| 4125 |
+ mjonMsgSendVOList.get(i).setMsgId(idList.get(i)); |
|
| 4126 |
+ } |
|
| 4127 |
+ |
|
| 4128 |
+// mjonMsgSendVOList.stream().forEach(t-> System.out.print(t.toString()+"\n") ); |
|
| 4129 |
+ |
|
| 4130 |
+ |
|
| 4131 |
+ |
|
| 4172 | 4132 |
// 이벤트 영역 |
| 4133 |
+ // 이벤트 영역 |
|
| 4134 |
+ |
|
| 4135 |
+ // 이벤트 정보 가져오기 |
|
| 4136 |
+ // 이벤트 상태가 "E"가 아닌 경우에만 호출 |
|
| 4137 |
+ // 이벤트 금액이 있을 시 발송 LIST에서 => optimalMsgList로 데이터 이동 |
|
| 4138 |
+ // 이동하면서 이벤트 금액으로 설정 |
|
| 4173 | 4139 |
MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo_advc(userId); |
| 4140 |
+ OptimalMsgResultDTO result = null; |
|
| 4141 |
+ List<MjonMsgSendVO> optimalMsgList = new ArrayList<>(); |
|
| 4174 | 4142 |
|
| 4175 |
- List<MjonMsgSendVO> optimalMsgList = MsgSendUtils.getOptimalMsgList(mjonMsgVO.getTotalPrice(), eventMberInfo.getEventRemainCash(), mjonMsgSendVOList); |
|
| 4176 |
- |
|
| 4143 |
+ if (eventMberInfo != null && !"E".equals(eventMberInfo.getEventStatus())) {
|
|
| 4144 |
+ try {
|
|
| 4145 |
+ result = MsgSendUtils.getOptimalMsgList(eventMberInfo, mjonMsgSendVOList); |
|
| 4146 |
+ optimalMsgList = result.getOptimalMsgList(); |
|
| 4147 |
+ MjonEventVO returnEventMberInfo = result.getEventInfo(); |
|
| 4148 |
+ |
|
| 4149 |
+ if (returnEventMberInfo != null && "E".equals(returnEventMberInfo.getEventStatus())) {
|
|
| 4150 |
+ returnEventMberInfo.setMberId(userId); |
|
| 4151 |
+ mjonEventService.updateEventEndStatus(returnEventMberInfo); |
|
| 4152 |
+ } |
|
| 4153 |
+ |
|
| 4154 |
+ } catch (IllegalArgumentException e) {
|
|
| 4155 |
+ // 메시지 타입 에러에 대한 응답 처리 |
|
| 4156 |
+ statusResponse.setStatus(HttpStatus.BAD_REQUEST); |
|
| 4157 |
+ statusResponse.setMessage("이벤트 데이터 처리 중 오류가 발생하였습니다.\n관리자에게 문의해 주세요.");
|
|
| 4158 |
+ return statusResponse; |
|
| 4159 |
+ } |
|
| 4160 |
+ } |
|
| 4177 | 4161 |
log.info(" + optimalMsgList :: [{}]", optimalMsgList.size());
|
| 4178 |
- log.info(" + mjonMsgSendVOList :: [{}]", mjonMsgSendVOList.size());
|
|
| 4162 |
+ |
|
| 4163 |
+ |
|
| 4164 |
+ |
|
| 4165 |
+ |
|
| 4166 |
+ |
|
| 4167 |
+ |
|
| 4168 |
+ |
|
| 4169 |
+ // 시작 시간 측정 |
|
| 4170 |
+ long startTime = System.currentTimeMillis(); |
|
| 4171 |
+ |
|
| 4172 |
+ |
|
| 4173 |
+ |
|
| 4174 |
+ log.info("mj_msg_data insert start [{}]", mjonMsgSendVOList.size());
|
|
| 4175 |
+ |
|
| 4176 |
+ // 분할 최대건수가 되면 디비에 입력하기 |
|
| 4177 |
+ int instCnt = mjonMsgDataDAO.insertMsgDataInfo_advc(mjonMsgSendVOList); |
|
| 4178 |
+ |
|
| 4179 |
+ |
|
| 4180 |
+ // 종료 시간 측정 |
|
| 4181 |
+ long endTime = System.currentTimeMillis(); |
|
| 4182 |
+ // 실행 시간 계산 (밀리초 -> 초로 변환) |
|
| 4183 |
+ double executionTimeInSeconds = (endTime - startTime) / 1000.0; |
|
| 4184 |
+ // 실행 시간 출력 |
|
| 4185 |
+ System.out.println("Execution time: " + executionTimeInSeconds + " seconds");
|
|
| 4186 |
+// mjonMsgSendVOList.stream().forEach(t-> System.out.print(t.toString()+"\n") ); |
|
| 4187 |
+// mjonMsgSendVOList.stream().forEach(t-> System.out.print(t.toString()+"\n") ); |
|
| 4188 |
+ |
|
| 4189 |
+ |
|
| 4190 |
+ // 강제로 IllegalArgumentException 발생시키기 |
|
| 4191 |
+ if (true) {
|
|
| 4192 |
+ throw new IllegalArgumentException("강제로 발생한 오류입니다.");
|
|
| 4193 |
+ } |
|
| 4194 |
+ |
|
| 4195 |
+ |
|
| 4196 |
+ |
|
| 4197 |
+ |
|
| 4198 |
+ |
|
| 4199 |
+ |
|
| 4200 |
+// log.info(" + optimalMsgList :: [{}]", optimalMsgList.size());
|
|
| 4201 |
+// log.info(" + optimalMsgList :: [{}]", optimalMsgList.get(0).getEachPrice());
|
|
| 4202 |
+// log.info(" + mjonMsgSendVOList :: [{}]", mjonMsgSendVOList.size());
|
|
| 4203 |
+// log.info(" + mjonMsgSendVOList :: [{}]", mjonMsgSendVOList.get(0).getEachPrice());
|
|
| 4204 |
+ |
|
| 4205 |
+ |
|
| 4206 |
+ |
|
| 4207 |
+ |
|
| 4179 | 4208 |
// log.info("mjonMsgVO.getTotalPrice() :: [{}]", mjonMsgVO.getTotalPrice());
|
| 4180 | 4209 |
|
| 4181 | 4210 |
// log.info(" + userId :: [{}]", userId);
|
... | ... | @@ -4214,6 +4243,41 @@ |
| 4214 | 4243 |
|
| 4215 | 4244 |
} |
| 4216 | 4245 |
|
| 4246 |
+ /** |
|
| 4247 |
+ * @methodName : handleHotlineAgent |
|
| 4248 |
+ * @author : 이호영 |
|
| 4249 |
+ * @date : 2024.11.26 |
|
| 4250 |
+ * @description : agent 발송 비율 리스트를 가져오기위해 msgType 수정 |
|
| 4251 |
+ * @param mjonMsgVO |
|
| 4252 |
+ * @param hotlineAgentCode |
|
| 4253 |
+ * @param userInfo |
|
| 4254 |
+ * @return |
|
| 4255 |
+ * @throws Exception |
|
| 4256 |
+ */ |
|
| 4257 |
+ private String handleHotlineAgent(MjonMsgVO mjonMsgVO, String hotlineAgentCode, MberManageVO userInfo) throws Exception {
|
|
| 4258 |
+ MjonMsgAgentStsVO mjonMsgAgentStsVO = new MjonMsgAgentStsVO(); |
|
| 4259 |
+ mjonMsgAgentStsVO.setAgentCode(hotlineAgentCode); |
|
| 4260 |
+ |
|
| 4261 |
+ // 메시지 타입에 따른 전송사 설정 |
|
| 4262 |
+ if ("6".equals(mjonMsgVO.getMsgType())) {
|
|
| 4263 |
+ int fileCount = Integer.parseInt(mjonMsgVO.getFileCnt()); |
|
| 4264 |
+ mjonMsgAgentStsVO.setMsgType(fileCount > 0 ? "P" : "L"); |
|
| 4265 |
+ } else {
|
|
| 4266 |
+ mjonMsgAgentStsVO.setMsgType("S");
|
|
| 4267 |
+ } |
|
| 4268 |
+ |
|
| 4269 |
+ // 핫라인 전송사 리스트 조회 |
|
| 4270 |
+ List<MjonMsgAgentStsVO> hotlineMsgAgentList = mjonMsgAgentStsDAO.selectMsgAgentListByAgentCode(mjonMsgAgentStsVO); |
|
| 4271 |
+ |
|
| 4272 |
+ // 핫라인 전송사 코드 업데이트 |
|
| 4273 |
+ for (MjonMsgAgentStsVO tmp : hotlineMsgAgentList) {
|
|
| 4274 |
+ hotlineAgentCode = MsgSendUtils.handleHotlineAgentRate(userInfo, tmp, hotlineAgentCode); |
|
| 4275 |
+ } |
|
| 4276 |
+ |
|
| 4277 |
+ return hotlineAgentCode; // 최종 변경된 hotlineAgentCode 반환 |
|
| 4278 |
+ } |
|
| 4279 |
+ |
|
| 4280 |
+ |
|
| 4217 | 4281 |
private MjonMsgVO setImagesSetting(MjonMsgVO mjonMsgVO, StatusResponse statusResponse) throws Exception {
|
| 4218 | 4282 |
|
| 4219 | 4283 |
int fileCount = 0; |
--- src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java
+++ src/main/java/itn/let/mjo/msgdata/web/MjonMsgDataController.java
... | ... | @@ -3174,11 +3174,10 @@ |
| 3174 | 3174 |
ModelMap model) throws Exception {
|
| 3175 | 3175 |
|
| 3176 | 3176 |
// 디버깅 출력 |
| 3177 |
- System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().toString());
|
|
| 3178 |
- System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().size());
|
|
| 3177 |
+// System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().toString());
|
|
| 3178 |
+// System.out.println("mjonMsgVO : " + mjonMsgVO.getMjonMsgSendVOList().size());
|
|
| 3179 | 3179 |
|
| 3180 | 3180 |
return ResponseEntity.ok().body(mjonMsgDataService.sendMsgData_advc(mjonMsgVO, request)) ; |
| 3181 |
-// return null; |
|
| 3182 | 3181 |
|
| 3183 | 3182 |
} |
| 3184 | 3183 |
|
--- src/main/java/itn/let/module/base/PriceAndPoint.java
+++ src/main/java/itn/let/module/base/PriceAndPoint.java
... | ... | @@ -34,6 +34,12 @@ |
| 34 | 34 |
|
| 35 | 35 |
@Autowired |
| 36 | 36 |
private MjonMsgDataDAO mjonMsgDataDAO; |
| 37 |
+ |
|
| 38 |
+ @Autowired |
|
| 39 |
+ private MjonPayDAO mjonPayDAO; |
|
| 40 |
+ |
|
| 41 |
+ @Resource(name = "egovMjonCashIdGnrService") |
|
| 42 |
+ private EgovIdGnrService idgenMjonCashId; |
|
| 37 | 43 |
|
| 38 | 44 |
/** |
| 39 | 45 |
* @methodName : getBefCash |
... | ... | @@ -95,10 +101,8 @@ |
| 95 | 101 |
* @param msgGroupId |
| 96 | 102 |
* @throws Exception |
| 97 | 103 |
*/ |
| 98 |
- public static void insertCashAndPoint( |
|
| 99 |
- MjonPayDAO mjonPayDAO |
|
| 100 |
- , EgovIdGnrService idgenMjonCashId |
|
| 101 |
- , String userId |
|
| 104 |
+ public void insertCashAndPoint( |
|
| 105 |
+ String userId |
|
| 102 | 106 |
, float totPrice |
| 103 | 107 |
, String memo |
| 104 | 108 |
, String msgGroupId |
--- src/main/resources/egovframework/spring/com/context-idgen.xml
+++ src/main/resources/egovframework/spring/com/context-idgen.xml
... | ... | @@ -2331,6 +2331,31 @@ |
| 2331 | 2331 |
<property name="fillChar" value="0" /> |
| 2332 | 2332 |
</bean> |
| 2333 | 2333 |
|
| 2334 |
+ |
|
| 2335 |
+ |
|
| 2336 |
+ <!-- 문자온 개선 작업(advc) 중 대량 발송을 위한 ids |
|
| 2337 |
+ 문자ID Generation Strategy Config --> |
|
| 2338 |
+ <bean id="egovMjonMsgIdCGnrService" |
|
| 2339 |
+ class="egovframework.com.idgen.impl.CustomTableIdGnrServiceImpl"> |
|
| 2340 |
+ <property name="dataSource" ref="dataSource" /> |
|
| 2341 |
+ <property name="blockSize" value="1000"/> |
|
| 2342 |
+ <property name="table" value="IDS"/> <!-- 실제 테이블 이름 --> |
|
| 2343 |
+ <property name="tableName" value="MSGC_ID"/> <!-- TABLE_NAME 컬럼의 값 --> |
|
| 2344 |
+ <!-- <property name="columnName" value="NEXT_ID"/> NEXT_ID 컬럼명 --> |
|
| 2345 |
+ <property name="prefix" value="MSGCID_"/> |
|
| 2346 |
+ <property name="cipers" value="14"/> |
|
| 2347 |
+ <property name="fillChar" value="0"/> |
|
| 2348 |
+ <property name="applyYear" value="false"/> |
|
| 2349 |
+ <!-- 필요에 따라 추가 프로퍼티 설정 --> |
|
| 2350 |
+ </bean> |
|
| 2351 |
+ |
|
| 2352 |
+ |
|
| 2353 |
+ |
|
| 2354 |
+ |
|
| 2355 |
+ |
|
| 2356 |
+ |
|
| 2357 |
+ |
|
| 2358 |
+ |
|
| 2334 | 2359 |
<!-- 문자의 장문,단문, 그림문자 등록 ID Generation Strategy Config --> |
| 2335 | 2360 |
<bean name="egovLetterInfoIdGnrService" |
| 2336 | 2361 |
class="egovframework.rte.fdl.idgnr.impl.EgovTableIdGnrServiceImpl" |
--- src/main/resources/egovframework/sqlmap/let/msg/MjonMsgData_SQL_mysql.xml
+++ src/main/resources/egovframework/sqlmap/let/msg/MjonMsgData_SQL_mysql.xml
... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 |
========= ======= ================================================= |
| 4 | 4 |
2021.03.01 신명섭 |
| 5 | 5 |
--> |
| 6 |
-<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd"> |
|
| 6 |
+<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> |
|
| 7 | 7 |
<sqlMap namespace="Msg"> |
| 8 | 8 |
<typeAlias alias="mjonMsgVO" type="itn.let.mjo.msg.service.MjonMsgVO"/> |
| 9 | 9 |
<typeAlias alias="mjonResvMsgVO" type="itn.let.mjo.reservmsg.service.MjonResvMsgVO"/> |
... | ... | @@ -153,6 +153,37 @@ |
| 153 | 153 |
) |
| 154 | 154 |
</iterate> |
| 155 | 155 |
</insert> |
| 156 |
+ |
|
| 157 |
+ <insert id="mjonMsgDAO.insertMsgData_advc" parameterClass="java.util.List"> |
|
| 158 |
+ INSERT INTO MJ_MSG_DATA |
|
| 159 |
+ ( MSG_ID, |
|
| 160 |
+ MSG_GROUP_ID, |
|
| 161 |
+ USER_ID, |
|
| 162 |
+ AGENT_CODE, |
|
| 163 |
+ CUR_STATE, |
|
| 164 |
+ REQ_DATE, |
|
| 165 |
+ CALL_TO, |
|
| 166 |
+ CALL_FROM, |
|
| 167 |
+ SUBJECT, |
|
| 168 |
+ SMS_TXT, |
|
| 169 |
+ MSG_TYPE |
|
| 170 |
+ )VALUES |
|
| 171 |
+ <iterate conjunction=","> |
|
| 172 |
+ ( |
|
| 173 |
+ #[].msgId#, |
|
| 174 |
+ #[].msgGroupId#, |
|
| 175 |
+ #[].userId#, |
|
| 176 |
+ #[].agentCode#, |
|
| 177 |
+ 0, |
|
| 178 |
+ #[].reqDate#, |
|
| 179 |
+ #[].callTo#, |
|
| 180 |
+ #[].callFrom#, |
|
| 181 |
+ #[].subject#, |
|
| 182 |
+ #[].smsTxt#, |
|
| 183 |
+ #[].msgType# |
|
| 184 |
+ ) |
|
| 185 |
+ </iterate> |
|
| 186 |
+ </insert> |
|
| 156 | 187 |
|
| 157 | 188 |
<select id="mjonMsgDAO.selectMjonMsgList" parameterClass="mjonMsgVO" resultClass="mjonMsgVO"> |
| 158 | 189 |
SELECT |
--- src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataSMLView.jsp
... | ... | @@ -2207,7 +2207,8 @@ |
| 2207 | 2207 |
|| contents.indexOf("[*3*]") > -1
|
| 2208 | 2208 |
|| contents.indexOf("[*4*]") > -1){
|
| 2209 | 2209 |
|
| 2210 |
- fnReplCell(); |
|
| 2210 |
+// fnReplCell(); |
|
| 2211 |
+ fnReplCell_advc(); |
|
| 2211 | 2212 |
|
| 2212 | 2213 |
}else{
|
| 2213 | 2214 |
|
--- src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgdata/MsgDataView.jsp
... | ... | @@ -1105,6 +1105,7 @@ |
| 1105 | 1105 |
if(eventStatus == 'Y' |
| 1106 | 1106 |
&& parseFloat(eventRemainCash) < parseFloat(totPriceOnly)) |
| 1107 | 1107 |
{
|
| 1108 |
+ console.log('eventRemainCash : ', eventRemainCash);
|
|
| 1108 | 1109 |
if(!confirm("고객님의 이벤트 캐시 잔액(" + eventRemainCash + "원) 부족으로 요청하신 문자("+numberWithCommas($selectedData.length)+"건)를 모두 발송할 수 없습니다. 이벤트 캐시 초과 건에 대해서는 일반 단가를 적용하여 발송하시겠습니까?")){
|
| 1109 | 1110 |
return false; |
| 1110 | 1111 |
} |
... | ... | @@ -1288,11 +1289,16 @@ |
| 1288 | 1289 |
|
| 1289 | 1290 |
$('.pop_msg_success').css({'display':'block','opacity':'1','left':'50%','top':'50%','transform':'translate(-50%,-50%)'});
|
| 1290 | 1291 |
//예약발송 건의 경우 결과 팝업 문구 변경 |
| 1291 |
- if(reserYn == 'Y'){
|
|
| 1292 |
- $('.pop_msg_success .msg_text').html("예약 성공 : <strong>"+ smsCnt + "</strong>건,수신거부 : <span>" + blockCnt + "</span>건의<br>문자가 예약 되었습니다.");
|
|
| 1293 |
- }else{
|
|
| 1294 |
- $('.pop_msg_success .msg_text').html("발송 성공 : <strong>"+ smsCnt + "</strong>건,수신거부 : <span>" + blockCnt + "</span>건의<br>문자가 발송 되었습니다.");
|
|
| 1292 |
+ var resText = (reserYn === 'Y') ? '예약' : '발송'; |
|
| 1293 |
+ if(reserYn == 'Y') |
|
| 1294 |
+ /* {
|
|
| 1295 |
+ resText = "예약"; |
|
| 1295 | 1296 |
} |
| 1297 |
+ else |
|
| 1298 |
+ {
|
|
| 1299 |
+ resText = "발송"; |
|
| 1300 |
+ } */ |
|
| 1301 |
+ $('.pop_msg_success .msg_text').html(resText+" 성공 : <strong>"+ smsCnt + "</strong>건,수신거부 : <span>" + blockCnt + "</span>건의<br>문자가 "+resText+" 되었습니다.");
|
|
| 1296 | 1302 |
|
| 1297 | 1303 |
$('.mask').addClass('on');
|
| 1298 | 1304 |
|
--- src/main/webapp/js/txtSpecialReplace.js
+++ src/main/webapp/js/txtSpecialReplace.js
... | ... | @@ -1,3 +1,59 @@ |
| 1 |
+ |
|
| 2 |
+function fnReplCell_advc(){
|
|
| 3 |
+ |
|
| 4 |
+ var smsTxtArea = $('#smsTxtArea').val();
|
|
| 5 |
+ console.log('smsTxtArea : ', smsTxtArea);
|
|
| 6 |
+ var orgSmsTxt = smsTxtArea; // 광고문자 뺀 문자내용 |
|
| 7 |
+ |
|
| 8 |
+ var recTableData = tableL.getRows(); // 받는사람 리스트의 전체 목록을 저장 |
|
| 9 |
+ |
|
| 10 |
+ var smsTxt = smsTxtArea; |
|
| 11 |
+ |
|
| 12 |
+ var data = recTableData[0].getData(); |
|
| 13 |
+ |
|
| 14 |
+ if(typeof data.name != 'undefined' |
|
| 15 |
+ && data.name != null |
|
| 16 |
+ && data.name != ""){
|
|
| 17 |
+ |
|
| 18 |
+ var name = data.name; |
|
| 19 |
+ smsTxt = stringReplaceAll(smsTxt, "[*이름*]", name); |
|
| 20 |
+ |
|
| 21 |
+ |
|
| 22 |
+ } |
|
| 23 |
+ if(typeof data.rep1 != 'undefined' && data.rep1 != null && data.rep1 != ""){
|
|
| 24 |
+ |
|
| 25 |
+ var rep1 = data.rep1; |
|
| 26 |
+ smsTxt = stringReplaceAll(smsTxt, "[*1*]", rep1); |
|
| 27 |
+ |
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ if(typeof data.rep2 != 'undefined' && data.rep2 != null && data.rep2 != ""){
|
|
| 31 |
+ |
|
| 32 |
+ var rep2 = data.rep2; |
|
| 33 |
+ smsTxt = stringReplaceAll(smsTxt, "[*2*]", rep2); |
|
| 34 |
+ |
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 37 |
+ if(typeof data.rep3 != 'undefined' && data.rep3 != null && data.rep3 != ""){
|
|
| 38 |
+ |
|
| 39 |
+ var rep3 = data.rep3; |
|
| 40 |
+ smsTxt = stringReplaceAll(smsTxt, "[*3*]", rep3); |
|
| 41 |
+ |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ if(typeof data.rep4 != 'undefined' && data.rep4 != null && data.rep4 != ""){
|
|
| 45 |
+ |
|
| 46 |
+ var rep4 = data.rep4; |
|
| 47 |
+ smsTxt = stringReplaceAll(smsTxt, "[*4*]", rep4); |
|
| 48 |
+ |
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ console.log('smsTxt : ', smsTxt);
|
|
| 52 |
+ $('.realtime').text(smsTxt);
|
|
| 53 |
+ |
|
| 54 |
+ |
|
| 55 |
+} |
|
| 56 |
+ |
|
| 1 | 57 |
//특정문구 일괄변환 문자길이 체크 하기 |
| 2 | 58 |
function fnReplCell(){
|
| 3 | 59 |
|
... | ... | @@ -86,7 +142,9 @@ |
| 86 | 142 |
|
| 87 | 143 |
var smsTxt = smsTxtArea; |
| 88 | 144 |
|
| 89 |
- if(typeof recTableData[j].getData().name != 'undefined' && recTableData[j].getData().name != null && recTableData[j].getData().name != ""){
|
|
| 145 |
+ if(typeof recTableData[j].getData().name != 'undefined' |
|
| 146 |
+ && recTableData[j].getData().name != null |
|
| 147 |
+ && recTableData[j].getData().name != ""){
|
|
| 90 | 148 |
|
| 91 | 149 |
// console.log('name : ', name);
|
| 92 | 150 |
// console.log('smsTxt : ', smsTxt);
|
... | ... | @@ -343,7 +401,10 @@ |
| 343 | 401 |
for(var j=0; j < recTableData.length; j++){
|
| 344 | 402 |
|
| 345 | 403 |
var smsTxt = smsTxtArea; |
| 346 |
- if(typeof recTableData[j].getData().name != 'undefined' && recTableData[j].getData().name != null && recTableData[j].getData().name != ""){
|
|
| 404 |
+ if(typeof recTableData[j].getData().name != 'undefined' |
|
| 405 |
+ && recTableData[j].getData().name != null |
|
| 406 |
+ && recTableData[j].getData().name != "") |
|
| 407 |
+ {
|
|
| 347 | 408 |
|
| 348 | 409 |
var name = recTableData[j].getData().name; |
| 349 | 410 |
smsTxt = stringReplaceAll(smsTxt, "[*이름*]", name); |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?