Skip to content

Commit fa7f0e4

Browse files
authored
Merge pull request #108 from HaruHan-Mail/develop
feat(101) : 주기적으로 구독자들에게 이메일 전송하는 기능 추가
2 parents 6c4e027 + cd5bdaf commit fa7f0e4

16 files changed

Lines changed: 161 additions & 124 deletions

File tree

src/main/java/com/haruhan/HaruHanApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.scheduling.annotation.EnableScheduling;
56

67
@SpringBootApplication
8+
@EnableScheduling
79
public class HaruHanApplication {
810
public static void main(String[] args) {
911
SpringApplication.run(HaruHanApplication.class, args);

src/main/java/com/haruhan/bookmark/entity/Bookmark.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.haruhan.bookmark.entity;
22

3-
import com.haruhan.common.error.entity.Content;
3+
import com.haruhan.content.entity.Content;
44
import com.haruhan.user.entity.User;
55
import jakarta.persistence.*;
66
import lombok.AllArgsConstructor;
@@ -28,7 +28,7 @@ public class Bookmark {
2828
private Content content;
2929

3030
public Bookmark(User user, Content content) {
31-
this.bookmarkId = new BookmarkId(user.getUserId(), content.getContent_id());
31+
this.bookmarkId = new BookmarkId(user.getUserId(), content.getContentId());
3232
this.user = user;
3333
this.content = content;
3434
}

src/main/java/com/haruhan/bookmark/service/BookmarkServiceImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import com.haruhan.bookmark.repository.BookmarkRepository;
88
import com.haruhan.common.error.CustomException;
99
import com.haruhan.common.error.StatusCode;
10-
import com.haruhan.common.error.entity.Content;
11-
import com.haruhan.common.error.repository.ContentRepository;
10+
import com.haruhan.content.entity.Content;
11+
import com.haruhan.content.repository.ContentRepository;
1212
import com.haruhan.user.entity.User;
1313
import com.haruhan.user.repository.UserRepository;
1414
import lombok.RequiredArgsConstructor;
@@ -92,13 +92,13 @@ public List<BookmarkGetResDto> getBookmarkContent(String email, String token) {
9292
// Bookmark를 DTO로 변환 후 반환
9393
return bookmarks.stream()
9494
.map(bookmark -> new BookmarkGetResDto(
95-
bookmark.getContent().getContent_id(),
95+
bookmark.getContent().getContentId(),
9696
bookmark.getContent().getTitle(),
9797
bookmark.getContent().getSummary(),
9898
splitByNewLine(bookmark.getContent().getBackground()),
9999
splitByNewLine(bookmark.getContent().getImportance()),
100100
splitByNewLine(bookmark.getContent().getTip()),
101-
splitByNewLine(bookmark.getContent().getAdditional_resources())
101+
splitByNewLine(bookmark.getContent().getAdditionalResources())
102102
)).collect(Collectors.toList());
103103
}
104104

src/main/java/com/haruhan/common/error/repository/ContentRepository.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/java/com/haruhan/common/error/entity/Content.java renamed to src/main/java/com/haruhan/content/entity/Content.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
package com.haruhan.common.error.entity;
1+
package com.haruhan.content.entity;
22

33
import com.haruhan.bookmark.entity.Bookmark;
44
import jakarta.persistence.*;
5-
import lombok.AllArgsConstructor;
65
import lombok.Getter;
76
import lombok.NoArgsConstructor;
87

@@ -16,7 +15,7 @@ public class Content {
1615
@Id
1716
@GeneratedValue(strategy = GenerationType.IDENTITY)
1817
@Column(name = "content_id", nullable = false)
19-
private Long content_id;
18+
private Long contentId;
2019

2120
@Column(name = "title", nullable = false)
2221
private String title;
@@ -34,10 +33,10 @@ public class Content {
3433
private String tip;
3534

3635
@Column(name = "additional_resources", nullable = false)
37-
private String additional_resources;
36+
private String additionalResources;
3837

3938
@Column(name = "bookmark_count", nullable = false)
40-
private int bookmark_count = 0;
39+
private int bookmarkCount = 0;
4140

4241
@OneToMany(mappedBy = "content", cascade = CascadeType.ALL, orphanRemoval = true)
4342
//orphanRemoval : 연결이 끊어진(null이 된) 북마크 엔티티를 자동 삭제
@@ -49,16 +48,16 @@ public Content(String title, String summary, String background, String importanc
4948
this.background = background;
5049
this.importance = importance;
5150
this.tip = tip;
52-
this.additional_resources = additional_resources;
51+
this.additionalResources = additional_resources;
5352
}
5453

5554
public void increaseBookmarkCount() {
56-
this.bookmark_count++;
55+
this.bookmarkCount++;
5756
}
5857

5958
public void decreaseBookmarkCount() {
60-
if(this.bookmark_count > 0){
61-
this.bookmark_count--;
59+
if(this.bookmarkCount > 0){
60+
this.bookmarkCount--;
6261
}
6362
}
6463
}

src/main/java/com/haruhan/content/entity/UserReceivedContent.java

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.haruhan.content.repository;
2+
3+
import com.haruhan.content.entity.Content;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
7+
8+
import java.util.List;
9+
10+
public interface ContentRepository extends JpaRepository<Content, Long> {
11+
Content findByContentId(Long content_id);
12+
13+
@Query("SELECT c FROM Content c ORDER BY c.bookmarkCount DESC LIMIT 3")
14+
List<Content> findTop5ByBookmarkCount();
15+
16+
@Query("SELECT c FROM Content c WHERE c.contentId <= :end ORDER BY c.contentId ASC")
17+
List<Content> findUpToLastContent(@Param("end") Long lastContentId);
18+
19+
@Query("SELECT c FROM Content c WHERE c.contentId > :lastId ORDER BY c.contentId ASC LIMIT 1")
20+
List<Content> findNextOneAfter(@Param("lastId") Long lastId);
21+
22+
@Query("SELECT c FROM Content c WHERE c.contentId > :lastId ORDER BY c.contentId ASC LIMIT 5")
23+
List<Content> findNextFiveAfter(@Param("lastId") Long lastId);
24+
25+
}

src/main/java/com/haruhan/content/service/ContentServiceImpl.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import com.haruhan.common.error.CustomException;
44
import com.haruhan.common.error.StatusCode;
5-
import com.haruhan.common.error.entity.Content;
6-
import com.haruhan.common.error.repository.ContentRepository;
5+
import com.haruhan.content.entity.Content;
76
import com.haruhan.content.dto.ContentReqDto;
87
import com.haruhan.content.dto.ContentResDto;
98
import com.haruhan.user.entity.User;
@@ -22,7 +21,7 @@
2221
public class ContentServiceImpl implements ContentService {
2322

2423
private final UserRepository userRepository;
25-
private final ContentRepository contentRepository;
24+
private final com.haruhan.content.repository.ContentRepository contentRepository;
2625

2726
@Override
2827
public List<ContentResDto> getUserReceivedContent(String email, String token) {
@@ -84,13 +83,13 @@ private List<String> splitByNewLine(String text) {
8483
//Content -> ContentResDto 변환
8584
private ContentResDto convertToDto(Content content) {
8685
return new ContentResDto(
87-
content.getContent_id(),
86+
content.getContentId(),
8887
content.getTitle(),
8988
content.getSummary(),
9089
splitByNewLine(content.getBackground()),
9190
splitByNewLine(content.getImportance()),
9291
splitByNewLine(content.getTip()),
93-
splitByNewLine(content.getAdditional_resources())
92+
splitByNewLine(content.getAdditionalResources())
9493
);
9594
}
9695

src/main/java/com/haruhan/email/controller/EmailController.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.haruhan.common.error.StatusCode;
44
import com.haruhan.common.error.dto.Message;
5+
import com.haruhan.content.entity.Content;
6+
import com.haruhan.content.repository.ContentRepository;
57
import com.haruhan.email.service.EmailService;
68
import lombok.RequiredArgsConstructor;
79
import org.springframework.http.ResponseEntity;
@@ -14,10 +16,12 @@
1416
public class EmailController {
1517

1618
private final EmailService emailService;
19+
private final ContentRepository contentRepository;
1720

1821
@PostMapping("/{email}")
1922
public ResponseEntity<Message> sendEmail(@PathVariable String email) {
20-
emailService.sendQuestionEmail(email);
23+
Content sampleContent = contentRepository.findByContentId(6L);
24+
emailService.sendContentEmail(email, sampleContent);
2125
return ResponseEntity.ok(new Message(StatusCode.OK));
2226
}
2327

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.haruhan.email.service;
2+
3+
import com.haruhan.content.entity.Content;
4+
import com.haruhan.content.repository.ContentRepository;
5+
import com.haruhan.user.entity.PreferedTime;
6+
import com.haruhan.user.entity.User;
7+
import com.haruhan.user.repository.UserRepository;
8+
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.scheduling.annotation.Scheduled;
11+
import org.springframework.stereotype.Service;
12+
13+
import java.time.DayOfWeek;
14+
import java.time.LocalDate;
15+
import java.util.Collections;
16+
import java.util.List;
17+
18+
@Slf4j
19+
@Service
20+
@RequiredArgsConstructor
21+
public class EmailScheduler {
22+
private final UserRepository userRepository;
23+
private final ContentRepository contentRepository;
24+
private final EmailService emailService;
25+
26+
@Scheduled(cron = "0 0 7 * * MON-FRI") // 오전 7시
27+
public void sendMorningEmails() {
28+
sendEmailsForTime(PreferedTime.MORNING);
29+
}
30+
31+
@Scheduled(cron = "0 0 12 * * MON-FRI") // 오후 12시
32+
public void sendAfternoonEmails() {
33+
sendEmailsForTime(PreferedTime.AFTERNOON);
34+
}
35+
36+
@Scheduled(cron = "0 0 18 * * MON-FRI") // 오후 6시
37+
public void sendEveningEmails() {
38+
sendEmailsForTime(PreferedTime.EVENING);
39+
}
40+
41+
private void sendEmailsForTime(PreferedTime time) {
42+
List<User> users = userRepository.findAllByPreferedTime(time); // 시간에 맞는 설정 값을 선택한 유저를 찾음
43+
for (User user : users) {
44+
List<Content> contents = getNextContents(user);
45+
for (Content content : contents) {
46+
emailService.sendContentEmail(user.getEmail(), content);
47+
updateUserLastContent(user, contents);
48+
}
49+
}
50+
}
51+
52+
private List<Content> getNextContents(User user) {
53+
if (user.getIsDaily()) { // 매일 컨텐츠를 받고 싶은 사람일 경우
54+
return contentRepository.findNextOneAfter(user.getLastReceivedContentId()); // 컨텐츠 1개 보내기
55+
} else if (LocalDate.now().getDayOfWeek() == DayOfWeek.MONDAY) { // 월요일에 몰아서 받고싶은 경우에 월요일인지도 체크
56+
return contentRepository.findNextFiveAfter(user.getLastReceivedContentId()); // 컨텐츠 5개 보내기
57+
}
58+
return Collections.emptyList();
59+
}
60+
61+
private void updateUserLastContent(User user, List<Content> sentContents) {
62+
Long lastId = sentContents.get(sentContents.size() - 1).getContentId();
63+
user.setLastReceivedContentId(lastId);
64+
userRepository.save(user);
65+
}
66+
}

0 commit comments

Comments
 (0)