fo bo 머지작업(sopmal)

This commit is contained in:
jazz
2025-11-21 18:19:13 +09:00
parent 956bc68e24
commit 2903f1c6e6
26 changed files with 7066 additions and 1228 deletions

View File

@@ -1,15 +1,29 @@
package com.wb.domainserver.domain.sopmal.csc.controller;
import com.wb.domainserver.domain.gcone.bbs.prom.service.BOPromService;
import com.wb.domainserver.domain.gcone.bbs.prom.vo.BOPromVO;
import com.wb.domainserver.domain.gcone.mbr.mlg.service.BOMlgService;
import com.wb.domainserver.domain.gcone.mbr.mlg.vo.BOMlgVO;
import com.wb.domainserver.domain.gcone.promtn.coupon.service.BOCouponService;
import com.wb.domainserver.domain.gcone.promtn.coupon.vo.BODwldCouponVO;
import com.wb.domainserver.domain.sopmal.csc.vo.PromVO;
import com.wb.domainserver.response.ApiResponse;
import com.wb.domainserver.response.WnbtResponse;
import com.wb.domainserver.response.WnbtResponseBody;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.security.authentication.AnonymousUser;
import com.wb.domainserver.security.authentication.MemberJwtContextHolder;
import com.wb.domainserver.security.authorization.annotation.AuthPolicy;
import com.wb.domainserver.security.authorization.annotation.Policy;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.ReplyFromResrc;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.dataaccess.DataMap;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
@@ -17,6 +31,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("/sopmal/prom")
@@ -27,13 +45,279 @@ public class PromController {
@Autowired
private SendToResrc sendToResrc;
@Policy(AuthPolicy.PUBLIC)
@RequestMapping(value = "/promJoin", method = RequestMethod.POST)
public ResponseEntity<?> promJoin(HttpServletRequest request, @RequestBody PromVO promVO) {
@Autowired
private BOPromService promService;
return responseHandler.handleResponse(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/bbs/prom/promJoin", promVO),
ReplyFromResrc::getReply
@Autowired
private BOMlgService bomlgService;
@Autowired
private BOCouponService couponService;
@Policy(AuthPolicy.PUBLIC)
@RequestMapping(value = "/promJoin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> promJoin(HttpServletRequest request, @RequestBody BOPromVO promVO) {
AnonymousUser user = MemberJwtContextHolder.getMemberInfo();
if (user.getUserInnb() > 0) {
// 1. 이벤트 정보 조회 및 유효성 체크
DataMap promInfo = promService.selectPromInfo(promVO);
boolean isActive = promService.isPromActive(promInfo);
Map<String, Object> content = new HashMap<>();
if (!isActive) {
content.put("eventActive", false);
content.put("message", "이벤트 기간이 아닙니다.");
return ApiResponse.of(content).ifPresentOrElse(HttpStatus.OK, HttpStatus.OK);
}
// 2. 참여 이력 조회
// promVO에 mbrInnb 설정
promVO.setMbrInnb((long) user.getUserInnb());
// daily 룰일 때만 오늘 날짜 세팅
if ("daily".equals((String)promInfo.get("promRule"))) {
promVO.setJoinDt(LocalDate.now());
}
if(!user.getSopmalCd().equals((String) promInfo.get("sopmalCd"))){
content.put("alreadySpun", true);
content.put("message", "해당 쇼핑몰 이벤트가 아닙니다.");
return ApiResponse.of(content).ifPresentOrElse(HttpStatus.OK, HttpStatus.OK);
}
DataMap joinInfo = promService.selectPromJoinInfo(promVO);
if (joinInfo != null) {
// 이미 참여한 경우
content.put("alreadySpun", true);
Object sortOrdrObj = joinInfo.get("sortOrdr");
if (sortOrdrObj != null) {
int selected = (sortOrdrObj instanceof Number) ? ((Number) sortOrdrObj).intValue() : Integer.parseInt(sortOrdrObj.toString());
content.put("selected", selected);
}
content.put("message", "이미 참여하셨습니다.");
return ApiResponse.of(content).ifPresentOrElse(HttpStatus.OK, HttpStatus.OK);
}
// 3. 추첨 및 지급 로직 (미참여자)
int totalJoinCount = promService.countPromJoin(promVO);
List<DataMap> rewardList = promService.selectPromRewardList(promVO);
Map<Integer, Integer> rewardWinCount = promService.countRewardWinners(promVO);
log.info("rewardWinCount 전체 데이터: {}", rewardWinCount);
log.info("totalJoinCount: {}", totalJoinCount);
double[] probabilities = new double[rewardList.size()];
for (int i = 0; i < rewardList.size(); i++) {
double baseProb = ((BigDecimal) rewardList.get(i).get("probability")).doubleValue();
Object sortOrdrObj = rewardList.get(i).get("sortOrdr");
int sortOrdr = (sortOrdrObj instanceof Number) ? ((Number) sortOrdrObj).intValue() : Integer.parseInt(sortOrdrObj.toString());
double actualRate = 0.0;
if (totalJoinCount > 0 && rewardWinCount.containsKey(sortOrdr)) {
actualRate = (double) rewardWinCount.get(sortOrdr) / totalJoinCount * 100.0;
}
if (totalJoinCount > 100) {
double diff = baseProb - actualRate;
probabilities[i] = baseProb + diff * 0.8;
if (probabilities[i] < 0) probabilities[i] = 0;
log.info("확률 보정 - baseProb: {}, actualRate: {}, diff: {}, 보정 후: {}", baseProb, actualRate, diff, probabilities[i]);
} else {
probabilities[i] = baseProb;
log.info("확률 보정 - baseProb: {}, actualRate: {}, diff: {}, 보정 후: {}", baseProb, actualRate, 0.0, probabilities[i]);
}
}
double rand = Math.random() * 100;
double acc = 0;
int selectedIdx = 0;
for (int i = 0; i < probabilities.length; i++) {
acc += probabilities[i];
if (rand < acc) {
selectedIdx = i;
break;
}
}
DataMap selectedReward = rewardList.get(selectedIdx);
log.info("추첨 결과 - rand: {}, selectedIdx: {}, selectedReward: {}", rand, selectedIdx, selectedReward);
// 보상 정보 추출
Object sortOrdrObj = selectedReward.get("sortOrdr");
int sortOrdr = (sortOrdrObj instanceof Number) ? ((Number) sortOrdrObj).intValue() : Integer.parseInt(sortOrdrObj.toString());
String rewardTy = (String) selectedReward.get("rewardTy");
BigDecimal accmlmnyAmt = (BigDecimal) selectedReward.get("accmlmnyAmt");
String mlgApplcResn = (String) selectedReward.get("mlgApplcResn");
log.info("원본 mlgApplcResn: {}", mlgApplcResn);
// 마일리지 소멸일자 세팅
String mlgExpireDt = String.valueOf(selectedReward.get("expireDt"));
Date exPireDate = new Date();
if (!"null".equals(mlgExpireDt)) {
int expireDays = Integer.parseInt(mlgExpireDt);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, expireDays);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
exPireDate = calendar.getTime();
}
Long couponInnb = selectedReward.get("couponInnb") != null ? Long.valueOf(selectedReward.get("couponInnb").toString()) : null;
Long couponSndngInnb = selectedReward.get("couponSndngInnb") != null ? Long.valueOf(selectedReward.get("couponSndngInnb").toString()) : null;
String rewardDc = (String) selectedReward.get("rewardDc");
boolean rewardSuccess = false;
DataMap result = null;
if ("coupon".equals(rewardTy)) {
// 쿠폰 발급 로직
try {
BODwldCouponVO dwldCouponVO = new BODwldCouponVO();
dwldCouponVO.setSopmalCd(user.getSopmalCd());
dwldCouponVO.setMbrInnb(user.getUserInnb());
dwldCouponVO.setMbrDvCd(user.getMbrDvCd());
dwldCouponVO.setCouponSndngInnb(couponSndngInnb.intValue()); // Long → Integer 변환 필요
dwldCouponVO.setEventYn("Y");
dwldCouponVO.setCouponSndngTy("01");
// 필요시 추가 필드 세팅
log.info("VO: {}", dwldCouponVO);
Map<String, Object> couponResult = couponService.insertBOBnfCouponRegist(dwldCouponVO);
if ("success".equals(couponResult.get("result"))) {
rewardSuccess = true;
log.info("쿠폰 발급 성공: {}", couponResult);
} else {
rewardSuccess = false;
log.error("쿠폰 발급 실패: {}", couponResult.get("message"));
}
} catch (Exception e) {
rewardSuccess = false;
log.error("쿠폰 발급 예외: {}", e.getMessage(), e);
}
} else if ("mileage".equals(rewardTy)) {
// null 체크를 더 엄격하게
if (mlgApplcResn == null || mlgApplcResn.trim().isEmpty()) {
mlgApplcResn = "이벤트 마일리지 지급";
log.info("기본값 사용: {}", mlgApplcResn);
} else {
log.info("DB 값 사용: {}", mlgApplcResn);
}
// 마일리지 VO 설정
BOMlgVO mlgVO = new BOMlgVO();
// 회원 고유번호 설정
mlgVO.setMbrInnb(String.valueOf(user.getUserInnb()));
// 등록자 설정
mlgVO.setRegusr(user.getUserInnb());
// 회원구분코드 설정
mlgVO.setMbrDvCd(user.getMbrDvCd());
// 쇼핑몰코드 설정
mlgVO.setSopmalCd(user.getSopmalCd());
// 등록자구분코드 설정 (01: 회원)
mlgVO.setRegusrDvCd("01");
//마일리지 적립 구분 설정
mlgVO.setMlgAccmlDvCd("add");
// 이벤트 보상 마일리지 적용 구분 설정
mlgVO.setMlgApplcDvCd("07"); // 이벤트 보상 마일리지
// 온라인 오프라인 구분 설정
mlgVO.setOnlineOflneDvCd("01");
// 마일리지 적립 처리 구분 설정
mlgVO.setMlgApplcDvCd("07");
// 이벤트 보상 마일리지 적용 사유 설정
mlgVO.setMlgApplcResn(mlgApplcResn);
// 이벤트 보상 마일리지 금액 설정
mlgVO.setAccmlmnyAmt(accmlmnyAmt);
// 마일리지 유효기간 설정
if (!"null".equals(mlgExpireDt)) {
mlgVO.setUsePosblEndDt(exPireDate);
mlgVO.setMlgValidPd(0);
}
mlgVO.setMlgValidPdAt("Y");
// 마일리지 적립 처리 전 로그
log.info("마일리지 적립 시작 - mlgVO: {}", mlgVO);
// 마일리지 적립 처리
result = bomlgService.insertBOMlgAdd(mlgVO);
// 마일리지 적립 처리 후 로그
log.info("마일리지 적립 결과: {}", result);
rewardSuccess = "success".equals(result.get("result")) || "Y".equals(result.get("success"));
log.debug("mlgVO 확인 {}", mlgVO);
log.info("마일리지 지급 결과: {}", result);
}
if (rewardSuccess) {
// 참여 이력 저장 전에 필수 데이터 설정
promVO.setMbrInnb((long) user.getUserInnb()); // 회원 고유번호
promVO.setSopmalCd(user.getSopmalCd()); // 쇼핑몰코드
// 보상 정보 설정
promVO.setPromInnb(promVO.getPromInnb());
promVO.setSortOrdr(sortOrdr);
promVO.setRewardTy(rewardTy);
promVO.setAccmlmnyAmt(accmlmnyAmt);
promVO.setCouponInnb(couponInnb);
promVO.setCouponSndngInnb(couponSndngInnb);
promVO.setRewardDc(rewardDc);
// 참여 이력 저장 전에 로그 추가
log.info("참여 이력 저장 시작 - promVO: {}", promVO);
try {
Map<String, String> insertResult = promService.insertPromJoin(promVO);
log.info("참여 이력 저장 결과 전체: {}", insertResult);
if ("Y".equals(insertResult.get("success"))) { // "result" → "success"로 변경
log.info("참여 이력 저장 성공");
} else {
log.error("참여 이력 저장 실패 - success: {}", insertResult.get("success"));
}
} catch (Exception e) {
log.error("참여 이력 저장 예외 발생: {}", e.getMessage(), e);
content.put("message", "참여 이력 저장에 실패했습니다.");
return ApiResponse.of(content).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR);
}
Map<String, Object> response = new HashMap<>();
response.put("result", "success");
//response.put("message", "이벤트에 참여되었습니다!");
response.put("selected", sortOrdr);
response.put("selectedReward", selectedReward);
return ResponseEntity.ok(response);
} else {
content.put("message", "보상 지급에 실패했습니다.");
return ApiResponse.of(content).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// 여기에 추가 (if 블록 밖으로)
Map<String, Object> content = new HashMap<>();
content.put("message", "로그인이 필요합니다.");
return ResponseEntity.ok(
WnbtResponse.builder()
.resBody(new WnbtResponseBody(content))
.build()
);
// return responseHandler.handleResponse(
// sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/bbs/prom/promJoin", promVO),
// ReplyFromResrc::getReply
// );
}
}