package com.caliverse.admin.domain.service; import com.caliverse.admin.domain.dao.admin.HistoryMapper; import com.caliverse.admin.domain.dao.admin.MailMapper; import com.caliverse.admin.domain.dao.total.WalletUserMapper; import com.caliverse.admin.domain.datacomponent.MetaDataHandler; import com.caliverse.admin.domain.entity.*; import com.caliverse.admin.domain.request.MailRequest; import com.caliverse.admin.domain.response.MailResponse; import com.caliverse.admin.dynamodb.service.DynamodbCaliumService; import com.caliverse.admin.global.common.code.CommonCode; import com.caliverse.admin.global.common.code.ErrorCode; import com.caliverse.admin.global.common.code.SuccessCode; import com.caliverse.admin.global.common.constants.CommonConstants; import com.caliverse.admin.global.common.exception.RestApiException; import com.caliverse.admin.global.common.utils.CommonUtils; import com.caliverse.admin.global.common.utils.ExcelUtils; import com.caliverse.admin.scheduler.ScheduleService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import org.springframework.core.io.ResourceLoader; import java.net.MalformedURLException; import java.nio.file.Path; import java.time.LocalDateTime; import java.util.*; @Slf4j @Service @RequiredArgsConstructor public class MailService { private final DynamoDBService dynamoDBService; private final WalletUserMapper walletUserMapper; @Value("${excel.file-path}") private String excelPath; @Value("${caliverse.file}") private String samplePath; private final ExcelUtils excelUtils; private final MailMapper mailMapper; private final HistoryMapper historyMapper; private final MetaDataHandler metaDataHandler; private final ResourceLoader resourceLoader; private final ScheduleService scheduleService; private final HistoryService historyService; private final DynamodbCaliumService dynamodbCaliumService; public MailResponse getStockCalium(){ double stock_calium = dynamodbCaliumService.getCaliumTotal(); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .stockCalium(stock_calium) .build() ) .build(); } public MailResponse getList(Map requestParam){ // gameDB 조회 및 서비스 로직 //페이징 처리 requestParam = CommonUtils.pageSetting(requestParam); List list = mailMapper.getMailList(requestParam); int allCnt = mailMapper.getAllCnt(requestParam); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .mailList(list) .total(mailMapper.getTotal()) .totalAll(allCnt) .pageNo(requestParam.get("page_no")!=null? Integer.valueOf(requestParam.get("page_no").toString()):1) .build() ) .build(); } public MailResponse getdetail(Long id){ // gameDB 조회 및 서비스 로직 Mail mail = mailMapper.getMailDetail(id); mail.setMailList(mailMapper.getMessage(id)); // mail.setItemList(mailMapper.getItem(id)); List itemList = mailMapper.getItem(id); for(Item item : itemList){ String itemName = metaDataHandler.getMetaItemNameData(Integer.parseInt(item.getItem())); item.setItemName(metaDataHandler.getTextStringData(itemName)); } mail.setItemList(itemList); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .mail(mail) .build()) .build(); } public MailResponse excelUpload(MultipartFile file){ List list = new ArrayList<>(); // 파일 존재하지 않는 경우 if (file.isEmpty()) { throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.getMessage() ); //Excel 파일을 선택해주세요. } List listData = excelUtils.getListData(file, 1, 0); // 엑셀 파일내 중복된 데이터 있는지 체크 if(excelUtils.hasDuplicates(listData)){ throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DUPLICATE_EXCEL.getMessage() ); //Excel 파일을 선택해주세요. } listData.forEach( item->{ Mail mail = new Mail(); mail.setGuid(item.toString()); list.add(mail); } ); // 파일을 서버에 저장 String fileName = excelUtils.saveExcelFile(file); return MailResponse.builder() .resultData(MailResponse.ResultData.builder() .mailList(list).message(SuccessCode.EXCEL_UPLOAD.getMessage()) .fileName(fileName) .build()) .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .build(); } public Resource excelDown(String fileName) { Path filePath = Path.of(excelPath+fileName); try { if(fileName.contains("sample")){ return resourceLoader.getResource(samplePath + fileName); } Resource resource = new UrlResource(filePath.toUri()); if (resource.exists() && resource.isReadable()) { return resource; } else { throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.getMessage()); } }catch (MalformedURLException e){ throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.getMessage()); } } @Transactional(transactionManager = "transactionManager") public MailResponse postMail(MailRequest mailRequest){ mailRequest.setCreateBy(CommonUtils.getAdmin().getId()); if(mailRequest.isReserve()){ mailRequest.setSendType(Mail.SENDTYPE.RESERVE_SEND); }else{ mailRequest.setSendType(Mail.SENDTYPE.DIRECT_SEND); mailRequest.setSendDt(LocalDateTime.now()); } //단일일경우 guid 를 target 설정, 복수이면은 fileName을 target에 설정 if(mailRequest.getGuid() != null){ if(mailRequest.getUserType().equals(Mail.USERTYPE.GUID) && dynamoDBService.isGuidChecked(mailRequest.getGuid())){ log.error("postMail RECEIVETYPE Single Guid Find Fail"); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.GUID_CHECK.getMessage()); } String guid = mailRequest.getGuid(); // 닉네임이면 guid로 바꾼다 if(mailRequest.getUserType().equals(Mail.USERTYPE.NICKNAME)) { // guid = dynamoDBService.getNickNameByGuid(guid); guid = getGuid(guid, Mail.USERTYPE.NICKNAME.name()); if(guid == null || mailRequest.getGuid().equals(guid)){ log.error("postMail RECEIVETYPE Single Nickname Find Fail"); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NICKNAME_CHECK.getMessage() ); } }else if(mailRequest.getUserType().equals(Mail.USERTYPE.EMAIL)){ guid = getGuid(guid, Mail.USERTYPE.EMAIL.name()); if(guid == null || guid.isEmpty()){ log.error("postMail RECEIVETYPE Single EMAIL Find Fail"); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.EMAIL_CHECK.getMessage() ); } } mailRequest.setReceiveType(Mail.RECEIVETYPE.SINGLE); mailRequest.setTarget(guid); } //엑셀 처리 else{ mailRequest.setReceiveType(Mail.RECEIVETYPE.MULTIPLE); if(mailRequest.getFileName() == null){ throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.toString() ); //Excel 파일을 선택해주세요. } List excelList = excelUtils.getExcelListData(mailRequest.getFileName()); for(Excel excel : excelList){ switch (excel.getType()) { case "GUID" -> { if (dynamoDBService.isGuidChecked(excel.getUser())) { log.error("postMail Multi Guid({}) Find Fail", excel.getUser()); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.GUID_CHECK.toString()); } } case "NICKNAME" -> { String user = getGuid(excel.getUser(), Mail.USERTYPE.NICKNAME.name()); if (user == null || user.isEmpty()) { log.error("postMail Multi Nickname({}) Find Fail", excel.getUser()); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NICKNAME_CHECK.toString()); } } case "EMAIL" -> { String user = getGuid(excel.getUser(), Mail.USERTYPE.EMAIL.name()); if (user == null || user.isEmpty()) { log.error("postMail Multi Email({}) Find Fail", excel.getUser()); throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.EMAIL_CHECK.toString()); } } default -> throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.USERTYPE_CHECK_EXCEL.toString()); //Excel 파일을 선택해주세요. } } mailRequest.setTarget(mailRequest.getFileName()); } mailMapper.postMail(mailRequest); //log.info("mail_id::"+ mailRequest.getId()); HashMap map = new HashMap<>(); map.put("mailId",String.valueOf(mailRequest.getId())); //아이템 저장 if(mailRequest.getItemList()!= null && !mailRequest.getItemList().isEmpty()){ //칼리움일경우 수량체크 boolean hasCalium = mailRequest.getItemList().stream().anyMatch(item -> item.getItem().equals(CommonConstants.CALIUM_ITEM_CODE)); double caliumSum = 0; if(hasCalium){ caliumSum = mailRequest.getItemList().stream() .filter(item -> item.getItem().equals(CommonConstants.CALIUM_ITEM_CODE)) .mapToDouble(Item::getItemCnt) .sum(); double stockCalium = dynamodbCaliumService.getCaliumTotal(); if(caliumSum > stockCalium){ throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_MAIL_ITEM_CALIUM_OVER.toString()); } } mailRequest.getItemList().forEach( item -> { map.put("goodsId",item.getItem()); map.put("itemCnt", String.valueOf(item.getItemCnt())); mailMapper.insertItem(map); } ); //재원저장소 칼리움 차감 if(hasCalium){ dynamodbCaliumService.caliumStockDeduction(caliumSum); } } //메시지 저장 if(mailRequest.getMailList()!= null && !mailRequest.getMailList().isEmpty()){ mailRequest.getMailList().forEach( item -> { map.put("title",item.getTitle()); map.put("content",item.getContent()); map.put("language",item.getLanguage()); mailMapper.insertMessage(map); } ); } log.info("postMail Insert Mail: {}", mailRequest); //로그 기록 JSONObject jsonObject = new JSONObject(); jsonObject.put("mail_type",mailRequest.getMailType()); jsonObject.put("receiver",mailRequest.getTarget()); Mail.SENDTYPE sendType = mailRequest.getSendType(); jsonObject.put("send_type",sendType); if(sendType.equals(Mail.SENDTYPE.RESERVE_SEND)) jsonObject.put("send_dt",mailRequest.getSendDt()); jsonObject.put("mail_list",map); historyService.setLog(HISTORYTYPE.MAIL_ADD, jsonObject); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .message(SuccessCode.SAVE.getMessage()) .build()) .build(); } @Transactional(transactionManager = "transactionManager") public MailResponse updateMail(Long id, MailRequest mailRequest) { mailRequest.setId(id); mailRequest.setUpdateBy(CommonUtils.getAdmin().getId()); mailRequest.setUpdateDt(LocalDateTime.now()); if (mailRequest.isReserve()) { mailRequest.setSendType(Mail.SENDTYPE.RESERVE_SEND); } else { mailRequest.setSendType(Mail.SENDTYPE.DIRECT_SEND); mailRequest.setSendDt(LocalDateTime.now()); } //단일일경우 guid 를 target 설정, 복수이면은 fileName을 target에 설정 if (mailRequest.getGuid() != null) { String guid = mailRequest.getGuid(); // 닉네임이면 guid로 바꾼다 if(mailRequest.getUserType().equals(Mail.USERTYPE.NICKNAME)) guid = dynamoDBService.getNickNameByGuid(guid); mailRequest.setReceiveType(Mail.RECEIVETYPE.SINGLE); mailRequest.setTarget(guid); } else { mailRequest.setReceiveType(Mail.RECEIVETYPE.MULTIPLE); if (mailRequest.getFileName() == null) { throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.getMessage()); } mailRequest.setTarget(mailRequest.getFileName()); } Long mail_id = mailRequest.getId(); Mail before_info = mailMapper.getMailDetail(mail_id); List before_msg = mailMapper.getMessage(mail_id); List before_item = mailMapper.getItem(mail_id); log.info("updateMail Update Before MailInfo: {}, Message: {}, Item: {}", before_info, before_msg, before_item); mailMapper.updateMail(mailRequest); // 스케줄에서 제거 scheduleService.closeTask("mail-" + mail_id.toString()); Map map = new HashMap<>(); map.put("mailId", String.valueOf(mailRequest.getId())); // item 테이블 데이터 삭제 처리 by mail_id mailMapper.deleteItem(map); // 아이템 업데이트 if (mailRequest.getItemList() != null && !mailRequest.getItemList().isEmpty()) { mailRequest.getItemList().forEach(item -> { map.put("goodsId", item.getItem()); map.put("itemCnt", String.valueOf(item.getItemCnt())); mailMapper.insertItem(map); }); } // message 테이블 데이터 삭제 처리 by mail_id mailMapper.deleteMessage(map); // 메일 업데이트 if (mailRequest.getMailList() != null && !mailRequest.getMailList().isEmpty()) { mailRequest.getMailList().forEach(item -> { map.put("title", item.getTitle()); map.put("content", item.getContent()); map.put("language", item.getLanguage()); mailMapper.insertMessage(map); }); } log.info("updateMail Update After Mail: {}", mailRequest); //로그 기록 JSONObject jsonObject = new JSONObject(); jsonObject.put("before_info",before_info.toString()); jsonObject.put("before_msg",before_msg.toString()); jsonObject.put("before_item",before_item.toString()); jsonObject.put("mail_type",mailRequest.getMailType()); jsonObject.put("receiver",mailRequest.getTarget()); Mail.SENDTYPE sendType = mailRequest.getSendType(); jsonObject.put("send_type",sendType); if(sendType.equals(Mail.SENDTYPE.RESERVE_SEND)) jsonObject.put("send_dt",mailRequest.getSendDt()); historyService.setLog(HISTORYTYPE.MAIL_UPDATE, jsonObject); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .message(SuccessCode.UPDATE.getMessage()) .build()) .build(); } @Transactional(transactionManager = "transactionManager") public MailResponse deleteMail(MailRequest mailRequest){ Map map = new HashMap<>(); mailRequest.getList().forEach( item->{ map.put("id",item.getId()); mailMapper.deleteMail(map); // 스케줄에서 제거 scheduleService.closeTask("mail-" + item.getId()); log.info("deleteMail Mail: {}", item); //로그 기록 List message = mailMapper.getMessage(Long.valueOf(item.getId())); map.put("adminId", CommonUtils.getAdmin().getId()); map.put("name", CommonUtils.getAdmin().getName()); map.put("mail", CommonUtils.getAdmin().getEmail()); map.put("type", HISTORYTYPE.MAIL_DELETE); JSONObject jsonObject = new JSONObject(); if(!message.isEmpty()){ jsonObject.put("message",message.get(0).getTitle()); } map.put("content",jsonObject.toString()); historyMapper.saveLog(map); } ); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .message(SuccessCode.DELETE.getMessage()) .build()) .build(); } public List getScheduleMailList(){ return mailMapper.getSchesuleMailList(); } public List getMailMessageList(Long id){ return mailMapper.getMessage(id); } public List getMailItemList(Long id){ return mailMapper.getItem(id); } public void updateMailStatus(Long id, Mail.SENDSTATUS status){ Map map = new HashMap<>(); map.put("id", id); map.put("status", status.toString()); mailMapper.updateCompleteMail(map); } //메타 아이템 public MailResponse getMetaItem(String metaId){ long id = Long.parseLong(metaId); String item = metaDataHandler.getMetaItemNameData((int) id); boolean isItem = (item != null && !item.isEmpty()); if(isItem) { Item item_info = new Item(); item_info.setItem(metaId); item_info.setItemName(metaDataHandler.getTextStringData(item)); return MailResponse.builder() .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .resultData(MailResponse.ResultData.builder() .message(SuccessCode.ITEM_EXIST.getMessage()) .itemInfo(item_info) .build()) .build(); }else return MailResponse.builder() .status(CommonCode.ERROR.getHttpStatus()) .result(CommonCode.ERROR.getResult()) .resultData(MailResponse.ResultData.builder() .message(ErrorCode.NOT_ITEM.getMessage()) .build()) .build(); } public String getGuid(String target, String type){ if(Mail.USERTYPE.EMAIL.name().equals(type)){ WalletUser user = walletUserMapper.getUser(target); return dynamoDBService.getAccountIdByGuid(user.getAccount_id()); }else if(Mail.USERTYPE.NICKNAME.name().equals(type)){ return dynamoDBService.getNickNameByGuid(target); } return target; } public void setScheduleLog(HISTORYTYPE type, String message){ //스케줄 로그 기록 historyService.setScheduleLog(type, message); } }