이호영 이호영 2025-02-10
Merge branch '4942_문자발송금액누락오류' into 4891_발송결과_속도개선
@e9891f36246ce3ee5dda6ca56274b1311d4f9020
src/main/java/itn/com/cmm/MjonMsgSendVO.java
--- src/main/java/itn/com/cmm/MjonMsgSendVO.java
+++ src/main/java/itn/com/cmm/MjonMsgSendVO.java
@@ -110,9 +110,9 @@
 
 
 	/**
-	 * @description : event 여부 / group tb에 넣는 용도
+	 * @description : event 여부 / group tb에 넣는 용도 / 기본값 N 
 	 */
-	private String 	eventYn;
+	private String 	eventYn="N";
 	
 	
 	
src/main/java/itn/com/cmm/util/MsgSendUtils.java
--- src/main/java/itn/com/cmm/util/MsgSendUtils.java
+++ src/main/java/itn/com/cmm/util/MsgSendUtils.java
@@ -726,11 +726,11 @@
 		}
 
 		// 이벤트 잔액과 종료 조건 확인
-		double targetCash = eventMberInfo.getEventRemainCash();
+		double remainCash = eventMberInfo.getEventRemainCash();
 		String eventEndDate = eventMberInfo.getEventEndDate();
 
-		if (isEventExpired(targetCash, eventEndDate)) {
-			MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, targetCash);
+		if (isEventExpired(remainCash, eventEndDate)) {
+			MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, remainCash);
 			return OptimalMsgResultDTO.builder()
 					.optimalMsgList(optimalList)
 					.eventInfo(returnEventMberInfo)
@@ -757,10 +757,12 @@
 			float floatEachPrice = Float.parseFloat(eachPrice);
 
 			// 최적의 메시지 리스트에 추가
-			if (sum + floatEachPrice <= targetCash) {
+			if (sum + floatEachPrice <= remainCash) {
 				sum += floatEachPrice;
+				
 				msg.setEachPrice(eachPrice);
 				msg.setEventYn("Y");
+				
 				optimalList.add(msg);
 				iterator.remove();
 			} else {
@@ -768,22 +770,19 @@
 			}
 		}
 
-		// 잔액 부족 시 이벤트 종료 처리하는 VO 생성
-		double remainAmt = targetCash - sum; 
-		log.info("remainAmt :: [{}]", remainAmt);
-		if (remainAmt < MIN_EVENT_REMAIN_CASH) {
-			MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, remainAmt);
-			return OptimalMsgResultDTO.builder()
-					.optimalMsgList(optimalList)
-					.eventInfo(returnEventMberInfo)
-					.build();
-		}
-
-		// 결과 반환
+		// 이벤트 잔액 처리하는 매소드 terminateEvent
+//		double remainAmt = targetCash - sum; 
+//		MjonEventVO returnEventMberInfo = terminateEvent(eventMberInfo, remainAmt);
 		return OptimalMsgResultDTO.builder()
 				.optimalMsgList(optimalList)
-				.eventInfo(null)
+//				.eventInfo(returnEventMberInfo)
 				.build();
+
+		// 결과 반환
+//		return OptimalMsgResultDTO.builder()
+//				.optimalMsgList(optimalList)
+//				.eventInfo(null)
+//				.build();
 	}
 	
 	/** 
@@ -827,18 +826,23 @@
 	 * @date		: 2024.11.26 
 	 * @description	: 이벤트 종료 VO 생성
 	 * @param eventMberInfo
-	 * @param targetCash
+	 * @param remainCash
 	 * @return 
 	 */
-	private static MjonEventVO terminateEvent(MjonEventVO eventMberInfo, double targetCash) {
+	public static MjonEventVO terminateEvent(MjonEventVO eventMberInfo, double remainCash) {
 		// TODO Auto-generated method stub
 
 		// 이벤트 상태를 종료로 변경
 		MjonEventVO returnEventMberInfo = new MjonEventVO();
 		returnEventMberInfo.setEventInfoId(eventMberInfo.getEventInfoId());
-		returnEventMberInfo.setEventStatus("E");
-		returnEventMberInfo.setEventRemainCash(targetCash);
-		returnEventMberInfo.setEventMemo("발송 최소 금액("+ MIN_EVENT_REMAIN_CASH +") 부족 혹은 이벤트 종료일 초과되어 이벤트 종료 시킴");
+		returnEventMberInfo.setMberId(eventMberInfo.getMberId());
+		returnEventMberInfo.setEventRemainCash(remainCash);
+		returnEventMberInfo.setEventStatus("Y");
+		
+		if (remainCash < MIN_EVENT_REMAIN_CASH) {
+			returnEventMberInfo.setEventStatus("E");
+			returnEventMberInfo.setEventMemo("발송 최소 금액("+ MIN_EVENT_REMAIN_CASH +") 부족 혹은 이벤트 종료일 초과되어 이벤트 종료 시킴");	
+		}
 		return returnEventMberInfo;
 	}
 
@@ -961,13 +965,25 @@
 		return mmsTitleTemp;
 	}
 
+	/** 
+	 * @methodName	: eventYN 
+	 * @author		: 이호영
+	 * @date		: 2025.02.10 
+	 * @description	: 이벤트 확인 
+	 * @param eventMberInfo
+	 * @return 
+	 */
+	public static Boolean isNotEvent(MjonEventVO eventMberInfo) {
+		
 
-
-
-
-
-
-
+		if (eventMberInfo == null 
+				|| "E".equals(eventMberInfo.getEventStatus())
+				|| org.apache.commons.lang3.StringUtils.isEmpty(eventMberInfo.getEventEndDate()) 
+				) {
+			return true;
+		}
+		return false;
+	}
 
 
 
src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
--- src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
+++ src/main/java/itn/let/mjo/mjocommon/MjonCommon.java
@@ -616,19 +616,17 @@
 
 	// 이벤트 메시지 처리
 	public StatusResponse processEventMessages(String userId, MjonMsgVO mjonMsgVO, 
-											List<MjonMsgSendVO> mjonMsgSendVOList) throws Exception {
+											List<MjonMsgSendVO> mjonMsgSendVOList, MjonEventVO eventMberInfo) throws Exception {
+		
 		StatusResponse statusResponse = new StatusResponse();
 
 		try {
-			// 이벤트 정보 가져오기
-			MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo_advc(userId);
-			if (eventMberInfo == null 
-					|| "E".equals(eventMberInfo.getEventStatus())
-					|| org.apache.commons.lang3.StringUtils.isEmpty(eventMberInfo.getEventEndDate()) 
-					) {
+			// 이벤트 여부 확인
+			if (MsgSendUtils.isNotEvent(eventMberInfo)) {
 				return statusResponse; // 이벤트 상태가 종료이거나 endDate가 없는 경우 처리하지 않음
 			}
 			log.info(" + 이벤트 진행 대상자 :: [{}]", userId);
+			log.info(" + 이벤트 진행 대상자 eventMberInfo.getMberId() :: [{}]", eventMberInfo.getMberId());
 
 			// 최적화된 메시지 리스트 및 이벤트 정보 가져오기
 			OptimalMsgResultDTO result = MsgSendUtils.getOptimalMsgList(eventMberInfo, mjonMsgSendVOList);
@@ -641,11 +639,8 @@
 				mjonMsgSendVOList.addAll(optimalMsgList); // 기존 리스트와 병합
 			}
 
-			// 이벤트 상태 종료 시 업데이트
-			if (returnEventMberInfo != null && "E".equals(returnEventMberInfo.getEventStatus())) {
-				returnEventMberInfo.setMberId(userId);
-				mjonEventService.updateEventEndStatus(returnEventMberInfo);
-			}
+			// 이벤트 관련 데이터가 있으면 updqte
+			eventChkAndInsertAmount(returnEventMberInfo);
 
 		} catch (IllegalArgumentException e) {
 			
@@ -656,5 +651,60 @@
 
 		return statusResponse;
 	}
+
+
+	/** 
+	 * @methodName	: checkEventAndDeductAmount 
+	 * @author		: 이호영
+	 * @date		: 2025.02.10 
+	 * @description	: 
+	 * @param eventMberInfo
+	 * @param eachPrice 
+	 * @throws Exception 
+	 */
+	public void checkEventAndDeductAmount(MjonEventVO eventMberInfo, List<MjonMsgSendVO> groupedMsgList) throws Exception {
+		
+		// 이벤트 그룹인지 확인
+		if("Y".equals(groupedMsgList.get(0).getEventYn())) {
+			// 이벤트 남은 금액
+			double remainCash = eventMberInfo.getEventRemainCash();
+			// 현재 그룹에서 발송한 총 금액
+			float sendTotalPrice = MsgSendUtils.setPriceforVO(groupedMsgList);
+			
+			// 이벤트 남은 금액에서 현재 그룹에 총 발송금액 차감
+			remainCash -= sendTotalPrice;
+			
+			MjonEventVO returnEventMberInfo = returnEventMberInfo = MsgSendUtils.terminateEvent(eventMberInfo, remainCash);
+			
+			eventChkAndInsertAmount(returnEventMberInfo);		
+		} 
+		
+	}
+	
+
+	/** 
+	 * @methodName	: eventChkAndInsertAmount 
+	 * @author		: 이호영
+	 * @date		: 2025.02.10 
+	 * @description	: 이벤트 관련 데이터가 있으면 update
+	 * @param returnEventMberInfo
+	 * @throws Exception 
+	 */
+	private void eventChkAndInsertAmount(MjonEventVO returnEventMberInfo) throws Exception {
+		// 이벤트 상태 종료 시 업데이트
+		if (returnEventMberInfo != null) {
+			mjonEventService.updateEventEndStatus(returnEventMberInfo);
+		}
+	}
+	
+
+
+	
+	
+	
+	
+	
+	
+	
 	
 }
src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
--- src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
+++ src/main/java/itn/let/mjo/msgdata/service/impl/MjonMsgDataServiceImpl.java
@@ -4100,18 +4100,25 @@
 			mjonMsgSendVOList.get(i).setMsgId(idList.get(i));
 		}
 
+		
+
+		// 이벤트 정보 가져오기
+		MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo_advc(userId);
 		/*
 		 * 이벤트 영역 이벤트 정보 가져오기 이벤트 상태가 "E"가 아닌 경우에만 호출 이벤트 금액이 있을 시 발송 LIST에서 =>
 		 * optimalMsgList로 데이터 이동 이동하면서 이벤트 금액으로 설정
 		 */
 		// mjonCommon 호출
-		statusResponse = mjonCommon.processEventMessages(userId, mjonMsgVO, mjonMsgSendVOList);
+		statusResponse = mjonCommon.processEventMessages(userId, mjonMsgVO, mjonMsgSendVOList, eventMberInfo);
 		if (statusResponse.getStatus() != null && !statusResponse.getStatus().equals(HttpStatus.OK)) {
 			log.error("이벤트 처리 중 오류 발생: {}", statusResponse.getMessage());
 			return statusResponse;
 		}
 
-		if (!isCashSufficient(mjonMsgVO)) {
+		/*
+		 * @ 금액체크
+		 * */
+		if (!isCashSufficient(mjonMsgVO, mjonMsgSendVOList)) {
 			log.error("Insufficient balance for message sending.");
 			return new StatusResponse(HttpStatus.BAD_REQUEST, "문자 발송에 필요한 보유 잔액이 부족 합니다.");
 		}
@@ -4125,12 +4132,13 @@
 		Map<String, List<MjonMsgSendVO>> priceGroupedMessages = mjonMsgSendVOList.stream()
 				.collect(Collectors.groupingBy(MjonMsgSendVO::getEachPrice));
 
+		// instTotalCnt : 화면에서 보여줄 총 발송건수
 		int instTotalCnt = 0;
 		// Step 2: 그룹화 된 데이터를 그룹별로 insert 처리
 		for (Map.Entry<String, List<MjonMsgSendVO>> entry : priceGroupedMessages.entrySet()) {
 			String price = entry.getKey(); // 가격 (String)
 			List<MjonMsgSendVO> groupedMsgList = entry.getValue(); // 해당 가격의 메시지 리스트
-
+			
 			// msgGroupId 생성
 			String nextMsgGroupId = idgenMjonMsgGroupId.getNextStringId();
 			groupedMsgList.forEach(t -> t.setMsgGroupId(nextMsgGroupId));
@@ -4139,12 +4147,23 @@
 			int instCnt = this.insertMsgData_advc(groupedMsgList);
 
 			if (instCnt > 0) {
+				
 				instTotalCnt += instCnt;
 				this.insertMsgGroupDataTb_advc(instCnt, mjonMsgVO, groupedMsgList);
 
 				// 금액 및 포인트 insert
-				priceAndPoint.insertCashAndPoint(userId, -Float.parseFloat(mjonMsgVO.getTotPrice()),
-						"SMS 문자 총 " + groupedMsgList.size() + "건 중 " + instCnt + "건 발송", mjonMsgVO.getMsgGroupId());
+				priceAndPoint.insertCashAndPoint(
+						userId
+						, -Float.parseFloat(mjonMsgVO.getTotPrice()),
+						"SMS 문자 총 " + groupedMsgList.size() + "건 중 " + instCnt + "건 발송"
+						, mjonMsgVO.getMsgGroupId()
+						);
+				
+				// event chk
+				if (!MsgSendUtils.isNotEvent(eventMberInfo)) {
+					mjonCommon.checkEventAndDeductAmount(eventMberInfo, groupedMsgList);
+				}
+				
 				// spam 문자 저장
 				handleSpamMsg_advc(mjonMsgVO, groupedMsgList.get(0));
 			}
@@ -4167,7 +4186,6 @@
 		
 		// TEST발송 시 발송 후 캐시가 있어야함.
 		returnMap.put("afterCash", priceAndPoint.getBefCash(userId));
-		log.debug("총 단가 합계: [{}]", mjonMsgVO.getTotPrice());
 //		
 
 		boolean isNotified = mjonCommon.processUserAndCheckSms(mjonMsgVO, userId);
@@ -4203,46 +4221,11 @@
 		// 개별단가
 		mjonMsgVO.setEachPrice(mjonMsgSendVO.getEachPrice());
 
-		//이벤트 회원인 경우 이벤트 캐시도 함께 차감.
-		MjonEventVO mjonEventVO = new MjonEventVO();
-		mjonEventVO.setMberId(mjonMsgSendVO.getUserId());
-		MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo(mjonEventVO);
-		
-        String str = String.valueOf(mjonMsgSendVO.getEachPrice());
-        // 소수점 제거
-        String EachPrice = str.split("\\.")[0];
-        
-        
-		if(eventMberInfo != null) {
-			String eventShortPrice = String.valueOf(eventMberInfo.getEventShortPrice());
-			eventShortPrice = eventShortPrice.split("\\.")[0];
-			
-			String eventLongPrice = String.valueOf(eventMberInfo.getEventLongPrice());
-			eventLongPrice = eventLongPrice.split("\\.")[0];
-			
-			String eventPicturePrice = String.valueOf(eventMberInfo.getEventPicturePrice());
-			eventPicturePrice = eventPicturePrice.split("\\.")[0];
-			
-			String eventPicture2Price = String.valueOf(eventMberInfo.getEventPicture2Price());
-			eventPicture2Price = eventPicture2Price.split("\\.")[0];
-			
-			String eventPicture3Price = String.valueOf(eventMberInfo.getEventPicture3Price());
-			eventPicture3Price = eventPicture3Price.split("\\.")[0];
-			
-			if(EachPrice.equals(eventShortPrice)) {
-				mjonMsgVO.setEventYn("Y");
-			}else if(EachPrice.equals(eventLongPrice)) {
-				mjonMsgVO.setEventYn("Y");
-			}else if(EachPrice.equals(eventPicturePrice)) {
-				mjonMsgVO.setEventYn("Y");
-			}else if(EachPrice.equals(eventPicture2Price)) {
-				mjonMsgVO.setEventYn("Y");
-			}else if(EachPrice.equals(eventPicture3Price)) {
-				mjonMsgVO.setEventYn("Y");
-			}else {
-				mjonMsgVO.setEventYn("N");
-			}
-		}
+		mjonMsgVO.setEventYn(mjonMsgSendVO.getEventYn()); 
+
+		// event Chk
+//		String eventYn = getEventYn(mjonMsgSendVO.getUserId(), mjonMsgSendVO.getEachPrice());
+//		mjonMsgVO.setEventYn(eventYn);
 		
 		
 		// 전송사 코드 번호를 셋팅해 준다.
@@ -4460,7 +4443,7 @@
 	 * 
 	 * return statusResponse; }
 	 */
-
+/*
 	private Map<String, String> fncSendMsgRtnMap(MjonMsgVO mjonMsgVO) throws Exception {
 		Map<String, String> returnMap = new HashMap<String, String>();
 
@@ -4509,7 +4492,7 @@
 		returnMap.put("resultBlockSts", Integer.toString(resultBlockSts));
 
 		return returnMap;
-	}
+	}*/
 
 	private void handleSpamMsg(MjonMsgVO mjonMsgVO) {
 		try {
@@ -4534,7 +4517,6 @@
 			mjonSpamMsgVO.setFilePath3(mjonMsgSendVO.getFilePath3());
 
 			int resultCnt = mjonSpamMsgService.insertSpamKeyWordMsgData(mjonMsgVO);
-			System.out.println("스팸 문구 발송 내용 등록: " + resultCnt);
 		}
 	}
 
@@ -4601,23 +4583,24 @@
 	}
 
 	// 보유 금액이 충분한지 확인하는 메서드
-	private boolean isCashSufficient(MjonMsgVO mjonMsgVO) throws Exception {
+	private boolean isCashSufficient(MjonMsgVO mjonMsgVO, List<MjonMsgSendVO> mjonMsgSendVOList) throws Exception {
+		
+		
 		String userMoney = priceAndPoint.getBefCash(mjonMsgVO.getUserId());
 		// 쉼표 제거
 		userMoney = userMoney.replace(",", "");
 
-		String totalPrice = mjonMsgVO.getTotPrice();
-		// 쉼표 제거
-		totalPrice = totalPrice.replace(",", "");
-
+		// 사용자 보유 금액 BigDecimal 변환 (HALF_EVEN 적용)
 		BigDecimal befCash = new BigDecimal(userMoney).setScale(2, RoundingMode.HALF_EVEN);
-		BigDecimal totMsgPrice = new BigDecimal(totalPrice).setScale(2, RoundingMode.HALF_EVEN);
 
-//		String userMoney = priceAndPoint.getBefCash(mjonMsgVO.getUserId());
-//		BigDecimal befCash = new BigDecimal(userMoney).setScale(2, RoundingMode.HALF_EVEN);
-//		BigDecimal totMsgPrice = new BigDecimal(mjonMsgVO.getTotPrice()).setScale(2, RoundingMode.HALF_EVEN);
+		// 총 메시지 금액 계산 (HALF_EVEN 적용)
+		BigDecimal totalEachPrice = mjonMsgSendVOList.stream()
+			.map(msg -> new BigDecimal(String.valueOf(msg.getEachPrice()))) // 변환 오류 방지
+			.reduce(BigDecimal.ZERO, BigDecimal::add)
+			.setScale(2, RoundingMode.HALF_EVEN); // 일관성 유지
 
-		return befCash.compareTo(totMsgPrice) >= 0;
+		// 비교 수행
+		return befCash.compareTo(totalEachPrice) >= 0;
 	}
 
 	/**
@@ -4772,7 +4755,6 @@
 	 * 
 	 * @throws Exception
 	 * 
-	 */
 	public StatusResponse fncSendMsg(MjonMsgVO mjonMsgVO) throws Exception {
 		log.info(" :: fncSendMsg :: ");
 
@@ -4823,6 +4805,7 @@
 		log.info("Message sending process completed.");
 		return new StatusResponse(HttpStatus.OK, "문자 전송이 완료되었습니다.", getReturnMap(resultSts, resultBlockSts));
 	}
+	 */
 
 	/**
 	 * @param mjonMsgVO
src/main/java/itn/let/module/base/PriceAndPoint.java
--- src/main/java/itn/let/module/base/PriceAndPoint.java
+++ src/main/java/itn/let/module/base/PriceAndPoint.java
@@ -124,36 +124,6 @@
  
 		mjonPayDAO.insertCash(mjonPayVO); //캐시 
 		mjonPayDAO.updateMemberCash(mjonPayVO); //회원정보 업데이트
- 
-		//이벤트 회원인 경우 이벤트 캐시도 함께 차감.
-		MjonEventVO mjonEventVO = new MjonEventVO();
-		mjonEventVO.setMberId(mjonPayVO.getUserId());
-		mjonEventVO.setEventStatus("Y");
-		MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo(mjonEventVO);
-		
-		if(eventMberInfo != null) {
-			
-			float evntRemainCash = (float) eventMberInfo.getEventRemainCash();
-			totPrice = (float) Math.abs(mjonPayVO.getCash());
-			
-			float totRemainCash = evntRemainCash - totPrice;
-			mjonEventVO.setEventInfoId(eventMberInfo.getEventInfoId());
-			
-			if(totRemainCash <= 0.0) {//차감액이 남아있지 않으면 이벤트를 종료
-				
-				//이벤트 상태값을 종료로 변경한다.
-				mjonEventVO.setEventStatus("E");
-				mjonEventVO.setEventRemainCash(0.0);
-				mjonEventService.updateEventEndStatus(mjonEventVO);
-				
-			}else {//이벤트 회원 캐시 차감시킴
-				
-				mjonEventVO.setEventRemainCash(totRemainCash);
-				mjonEventService.updateEventRemainCash(mjonEventVO);
-				
-			}
-			
-		}
 		
 	}
  
src/main/resources/egovframework/sqlmap/let/mjo/event/Event_SQL_Mysql.xml
--- src/main/resources/egovframework/sqlmap/let/mjo/event/Event_SQL_Mysql.xml
+++ src/main/resources/egovframework/sqlmap/let/mjo/event/Event_SQL_Mysql.xml
@@ -180,7 +180,9 @@
 			<isNotEmpty property="eventEndDate">
 				,EVENT_END_DATE = #eventEndDate#
 			</isNotEmpty>
+			<isNotEmpty property="eventStatus">
 			, EVENT_STATUS = #eventStatus#
+			</isNotEmpty>
 			, LAST_UPDT_PNTTM = NOW()
 		WHERE MBER_ID = #mberId#
 		AND EVENT_INFO_ID = #eventInfoId#
Add a comment
List