Skip to content

Commit

Permalink
Merge pull request #295 from LearnsMate/feature/campaign
Browse files Browse the repository at this point in the history
✨기능 추가: Campaign -> campaignSendFlag 추가
  • Loading branch information
YuJeeun authored Nov 29, 2024
2 parents d7a8a24 + def6ea3 commit 7df51a5
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,54 @@ public EmailService(StringRedisTemplate stringRedisTemplate, JavaMailSender mail

private final long VERIFICATION_CODE_TTL = 5; // 5분

// 인증 코드 발송 메소드
public void sendVerificationEmail(String email) {
log.info("start sending verification email");
log.info("Start sending verification email");
String verificationCode = generateVerificationCode();

SimpleMailMessage message = new SimpleMailMessage();
message.setTo(email);
message.setSubject("[LearnsMate] 이메일 인증 코드 안내");
message.setText("안녕하세요,\n\n"
String subject = "[LearnsMate] 이메일 인증 코드 안내";
String content = "안녕하세요,\n\n"
+ "LearnsMate를 이용해 주셔서 진심으로 감사드립니다.\n"
+ "아래의 인증 코드를 입력하여 이메일 인증을 완료해 주시기 바랍니다.\n\n"
+ "인증 코드: " + verificationCode + "\n\n"
+ "※ 인증 코드는 발송 후 5분간만 유효합니다.\n\n"
+ "본 이메일은 LearnsMate 서비스 이용과 관련하여 발송되었습니다. "
+ "궁금하신 사항이 있으시면 LearnsMate 고객 지원팀으로 언제든 문의해 주시기 바랍니다.\n\n"
+ "감사합니다.\n\n"
+ "LearnsMate 드림");

mailSender.send(message);
+ "LearnsMate 드림";

sendEmail(email, subject, content);
saveVerificationCode(email, verificationCode);
}

// 캠페인 이메일 발송 메소드 추가
public void sendCampaignEmail(String email, String campaignTitle, String campaignContents) {
log.info("Start sending campaign email to: " + email);

String subject = "[LearnsMate]: " + campaignTitle;
String content = campaignContents + "\n\n"
+ "더 자세한 사항은 LearnsMate 홈페이지를 방문해 주세요.\n\n"
+ "감사합니다.\n\n"
+ "LearnsMate 드림";

sendEmail(email, subject, content);
}

// 이메일 발송 공통 메소드
private void sendEmail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(content);

try {
mailSender.send(message);
log.info("Email sent successfully to: " + to);
} catch (Exception e) {
log.error("Failed to send email to: " + to + ", error: " + e.getMessage());
}
}

//필기. 해당 이메일의 코드가 일치하는지 확인하는 코드
public boolean verifyCode(String email, String code) {
String savedCode = stringRedisTemplate.opsForValue().get(email); //필기. Redis에서 코드 가져오기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class Campaign {
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime campaignSendDate;

@Column(name="campaign_send_flag" , nullable = true)
private Boolean campaignSendFlag;

@Column(name = "created_at")
@CreationTimestamp
Expand All @@ -47,4 +49,15 @@ public class Campaign {
@JoinColumn(name = "admin_code", nullable = false)
private Admin admin;

// 엔티티가 처음 저장되기 전에 실행되어 기본값을 설정해 줌
@PrePersist
public void prePersist() {
if (campaignSendFlag == null) {
campaignSendFlag = false; // 기본값 설정
}
}

public void updateSendFlag() {
this.campaignSendFlag = true;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package intbyte4.learnsmate.campaign.repository;

import intbyte4.learnsmate.campaign.domain.entity.Campaign;
import intbyte4.learnsmate.campaign.domain.entity.CampaignTypeEnum;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
Expand All @@ -13,5 +14,6 @@
@Primary
public interface CampaignRepository extends JpaRepository<Campaign, Long>, CampaignRepositoryCustom {

List<Campaign> findByCampaignSendDateLessThanEqual(LocalDateTime currentTime);
// campaign_type이 RESERVATION 이고 lessthan이고 flag가 false인 것들에 한해서
List<Campaign> findByCampaignSendDateLessThanEqualAndCampaignSendFlagFalseAndCampaignType(LocalDateTime currentTime, CampaignTypeEnum campaignTypeEnum);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ CampaignDTO editCampaign(CampaignDTO requestCampaign
(CampaignFilterDTO request, int page, int size);
List<FindAllCampaignsDTO> findCampaignListByConditionWithExcel(CampaignFilterDTO filterDTO);
List<FindAllCampaignsDTO> findAllCampaignListWithExcel();

void updateCampaignSendFlag(Long campaignCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import intbyte4.learnsmate.admin.domain.entity.Admin;
import intbyte4.learnsmate.admin.mapper.AdminMapper;
import intbyte4.learnsmate.admin.service.AdminService;
import intbyte4.learnsmate.admin.service.EmailService;
import intbyte4.learnsmate.campaign.batch.CampaignIssueCouponReader;
import intbyte4.learnsmate.campaign.domain.dto.*;
import intbyte4.learnsmate.campaign.domain.entity.Campaign;
Expand Down Expand Up @@ -55,6 +56,7 @@ public class CampaignServiceImpl implements CampaignService {
private final MemberService memberService;
private final CouponService couponService;
private final IssueCouponService issueCouponService;
private final EmailService emailService;
private final CampaignMapper campaignMapper;
private final AdminMapper adminMapper;
private final JobLauncher jobLauncher;
Expand Down Expand Up @@ -114,8 +116,11 @@ else if (foundCoupon.getTutorCode() != null) {
if (Objects.equals(requestCampaign.getCampaignType(), CampaignTypeEnum.INSTANT.getType())) {
// 즉시 발송
issueCouponService.issueCouponsToStudents(studentCodes, couponCodes);
requestStudentList.forEach(memberDTO -> {
emailService.sendCampaignEmail(memberDTO.getMemberEmail(), campaign.getCampaignTitle(), campaign.getCampaignContents());
});
} else {
// 예약 발송은 스케줄러에 등록 아직
// 예약 발송은 스케줄러에 등록
registerScheduledCampaign(requestStudentList, requestCouponList, savedCampaignDTO.getCampaignSendDate());
}

Expand Down Expand Up @@ -149,7 +154,8 @@ public void registerScheduledCampaign(List<MemberDTO> studentList, List<CouponDT
@Transactional
public List<CampaignDTO> getReadyCampaigns(LocalDateTime currentTime) {
// 예약 시간이 현재 시간보다 이전이면서 아직 발송되지 않은 캠페인 조회
List<Campaign> readyCampaigns = campaignRepository.findByCampaignSendDateLessThanEqual(currentTime);
List<Campaign> readyCampaigns = campaignRepository
.findByCampaignSendDateLessThanEqualAndCampaignSendFlagFalseAndCampaignType(currentTime, CampaignTypeEnum.RESERVATION);
return readyCampaigns.stream()
.map(campaignMapper::toDTO)
.toList();
Expand All @@ -169,9 +175,9 @@ public CampaignDTO editCampaign(CampaignDTO requestCampaign

AdminDTO adminDTO = adminService.findByAdminCode(requestCampaign.getAdminCode());
Admin admin = adminMapper.toEntity(adminDTO);
log.info("서비스에서 조회하는 adminDTO: {}", adminDTO);

Campaign updatedCampaign = campaignMapper.toEntity(requestCampaign, admin);
log.info("서비스에서 조회하는 toEntity(requestCampaign,admin): {}", updatedCampaign);

campaignRepository.save(updatedCampaign);
editStudent(requestCampaign, requestStudentList, updatedCampaign);

Expand Down Expand Up @@ -209,9 +215,7 @@ private void editCoupon(CampaignDTO requestCampaign
private void editStudent(CampaignDTO requestCampaign
, List<MemberDTO> requestStudentList
, Campaign updatedCampaign) {
log.info("editStuden메서드의 requestCampaign: {}", requestCampaign);
log.info("editStuden메서드의 requestStudentList: {}", requestStudentList);
log.info("editStuden메서드의 updatedCampaign: {}", updatedCampaign);

List<UserPerCampaignDTO> existingStudentList = userPerCampaignService
.findByCampaignCode(updatedCampaign);

Expand Down Expand Up @@ -329,4 +333,15 @@ public List<FindAllCampaignsDTO> findAllCampaignListWithExcel() {

return findAllCampaignsDTOList;
}

@Override
public void updateCampaignSendFlag(Long campaignCode) {
Campaign campaign = campaignRepository.findById(campaignCode)
.orElseThrow(() -> new CommonException(StatusEnum.CAMPAIGN_NOT_FOUND));

campaign.updateSendFlag();

campaignRepository.save(campaign);
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package intbyte4.learnsmate.common.config;

import intbyte4.learnsmate.admin.service.EmailService;
import intbyte4.learnsmate.campaign.domain.dto.CampaignDTO;
import intbyte4.learnsmate.campaign.service.CampaignService;
import intbyte4.learnsmate.member.domain.MemberType;
import intbyte4.learnsmate.member.domain.dto.MemberDTO;
import intbyte4.learnsmate.member.service.MemberService;
import intbyte4.learnsmate.userpercampaign.domain.dto.UserPerCampaignDTO;
import intbyte4.learnsmate.userpercampaign.service.UserPerCampaignService;
import intbyte4.learnsmate.voc.service.VOCAiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
Expand All @@ -17,18 +24,25 @@

@Configuration
@EnableScheduling
@Slf4j
public class SchedulerConfig {

private final VOCAiService vocAiService;
private final CampaignService campaignService;
private final JobLauncher jobLauncher;
private final Job campaignJob;
private final MemberService memberService;
private final EmailService emailService;
private final UserPerCampaignService userPerCampaignService;

public SchedulerConfig(VOCAiService vocAiService, CampaignService campaignService, JobLauncher jobLauncher, Job campaignJob) {
public SchedulerConfig(VOCAiService vocAiService, CampaignService campaignService, JobLauncher jobLauncher, Job campaignJob, MemberService memberService, EmailService emailService , UserPerCampaignService userPerCampaignService) {
this.vocAiService = vocAiService;
this.campaignService = campaignService;
this.jobLauncher = jobLauncher;
this.campaignJob = campaignJob;
this.memberService = memberService;
this.emailService = emailService;
this.userPerCampaignService = userPerCampaignService;
}

@Scheduled(cron = "0 0 9 * * MON")
Expand All @@ -46,6 +60,15 @@ public void scheduleCampaigns() {
.addDate("startTime", new Date())
.toJobParameters();
jobLauncher.run(campaignJob, jobParameters);

List<UserPerCampaignDTO> userPerCampaignDTOList = userPerCampaignService.findUserByCampaignCode(campaign.getCampaignCode());
for (UserPerCampaignDTO userPerCampaignDTO : userPerCampaignDTOList) {
MemberDTO member = memberService.findMemberByMemberCode(userPerCampaignDTO.getStudentCode(), MemberType.STUDENT);
if (member != null) {
emailService.sendCampaignEmail(member.getMemberEmail(), campaign.getCampaignTitle(), campaign.getCampaignContents());
}
}
campaignService.updateCampaignSendFlag(campaign.getCampaignCode());
} catch (Exception e) {
System.err.println("Failed to launch campaign job: " + e.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package intbyte4.learnsmate.userpercampaign.repository;

import intbyte4.learnsmate.campaign.domain.entity.Campaign;
import intbyte4.learnsmate.userpercampaign.domain.dto.UserPerCampaignDTO;
import intbyte4.learnsmate.userpercampaign.domain.entity.UserPerCampaign;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
Expand All @@ -12,4 +15,8 @@ public interface UserPerCampaignRepository extends JpaRepository<UserPerCampaign
List<UserPerCampaign> findByCampaign(Campaign campaign);

void deleteByCampaign_CampaignCode(Long campaignCode);

@Query("SELECT new intbyte4.learnsmate.userpercampaign.domain.dto.UserPerCampaignDTO(u.userPerCampaignCode, u.campaign.campaignCode, u.student.memberCode) " +
"FROM userPerCampaign u WHERE u.campaign.campaignCode = :campaignCode")
List<UserPerCampaignDTO> findStudentsByCampaignCode(@Param("campaignCode") Long campaignCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface UserPerCampaignService {
List<UserPerCampaignDTO> findByCampaignCode(Campaign campaign);
void removeUserPerCampaign(Long userPerCampaignCode);
void removeByCampaignCode(Long campaignCode);
List<UserPerCampaignDTO> findUserByCampaignCode(Long campaignCode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,9 @@ public void removeUserPerCampaign(Long userPerCampaignCode) {
public void removeByCampaignCode(Long campaignCode) {
userPerCampaignRepository.deleteByCampaign_CampaignCode(campaignCode);
}

@Override
public List<UserPerCampaignDTO> findUserByCampaignCode(Long campaignCode) {
return userPerCampaignRepository.findStudentsByCampaignCode(campaignCode);
}
}

0 comments on commit 7df51a5

Please sign in to comment.