Skip to content

Commit 563f2b6

Browse files
authored
Merge pull request #174 from Central-MakeUs/release
Release v1.1.0
2 parents 983c4d9 + fcb0b02 commit 563f2b6

File tree

18 files changed

+342
-128
lines changed

18 files changed

+342
-128
lines changed

โ€Ž.github/workflows/deploy.ymlโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Deploy To EC2 (Blue-Green Public)
22

33
on:
44
push:
5-
branches: [ "main", "release" ]
5+
branches: [ "main" ]
66

77
permissions:
88
contents: read

โ€Žsrc/main/java/com/example/ForDay/domain/activity/controller/ActivityController.javaโ€Ž

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.example.ForDay.domain.activity.controller;
22

33
import com.example.ForDay.domain.activity.dto.request.UpdateActivityReqDto;
4+
import com.example.ForDay.domain.activity.dto.response.GetAiRecommendItemsResDto;
45
import com.example.ForDay.domain.activity.service.ActivityService;
56
import com.example.ForDay.global.common.response.dto.MessageResDto;
67
import com.example.ForDay.global.oauth.CustomUserDetails;
@@ -29,4 +30,9 @@ public MessageResDto deleteActivity(@PathVariable(name = "activityId") Long acti
2930
@AuthenticationPrincipal CustomUserDetails user) {
3031
return activityService.deleteActivity(activityId, user);
3132
}
33+
34+
@GetMapping("/ai-recommend/items")
35+
public GetAiRecommendItemsResDto getAiRecommendItems(@AuthenticationPrincipal CustomUserDetails user) {
36+
return activityService.getAiRecommendItems(user);
37+
}
3238
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.example.ForDay.domain.activity.dto.response;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.util.List;
8+
9+
@Data
10+
@AllArgsConstructor
11+
@NoArgsConstructor
12+
public class GetAiRecommendItemsResDto {
13+
private MessageDto message;
14+
private List<ItemDto> activityItems;
15+
16+
@Data
17+
@AllArgsConstructor
18+
@NoArgsConstructor
19+
public static class MessageDto {
20+
private String message;
21+
}
22+
23+
@Data
24+
@AllArgsConstructor
25+
@NoArgsConstructor
26+
public static class ItemDto {
27+
private Long itemId;
28+
private Long hobbyId;
29+
private String hobbyName;
30+
private String content;
31+
private String description;
32+
}
33+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.example.ForDay.domain.activity.entity;
2+
3+
import com.example.ForDay.domain.hobby.entity.Hobby;
4+
import com.example.ForDay.global.common.mapped.BaseTimeEntity;
5+
import jakarta.persistence.*;
6+
import lombok.*;
7+
8+
@Entity
9+
@Table(name = "activity_recommend_items")
10+
@Getter
11+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
12+
@AllArgsConstructor
13+
@Builder
14+
public class ActivityRecommendItem extends BaseTimeEntity {
15+
@Id
16+
@GeneratedValue(strategy = GenerationType.IDENTITY)
17+
@Column(name = "activity_recommend_item_id")
18+
private Long id;
19+
20+
@ManyToOne(fetch = FetchType.LAZY)
21+
@JoinColumn(name = "user_hobby_id", nullable = false)
22+
private Hobby hobby;
23+
24+
private String content;
25+
private String description;
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.example.ForDay.domain.activity.repository;
2+
3+
import com.example.ForDay.domain.activity.entity.ActivityRecommendItem;
4+
import com.example.ForDay.domain.hobby.entity.Hobby;
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.data.jpa.repository.Modifying;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
10+
import java.time.LocalDateTime;
11+
import java.util.List;
12+
13+
public interface ActivityRecommendItemRepository extends JpaRepository<ActivityRecommendItem, Long> {
14+
@Query("SELECT a FROM ActivityRecommendItem a " +
15+
"JOIN FETCH a.hobby " +
16+
"WHERE a.hobby IN :hobbies " +
17+
"AND a.createdAt >= :start AND a.createdAt <= :end")
18+
List<ActivityRecommendItem> findAllByHobbiesAndDate(
19+
@Param("hobbies") List<Hobby> hobbies,
20+
@Param("start") LocalDateTime start,
21+
@Param("end") LocalDateTime end
22+
);
23+
24+
@Modifying
25+
@Query("DELETE FROM ActivityRecommendItem a WHERE a.createdAt < :targetDate")
26+
void deleteOldItems(@Param("targetDate") LocalDateTime targetDate);
27+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.example.ForDay.domain.activity.service;
2+
3+
import com.example.ForDay.domain.activity.repository.ActivityRecommendItemRepository;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.scheduling.annotation.Scheduled;
7+
import org.springframework.stereotype.Component;
8+
import org.springframework.transaction.annotation.Transactional;
9+
10+
import java.time.LocalDateTime;
11+
12+
@Component
13+
@RequiredArgsConstructor
14+
@Slf4j
15+
public class ActivityItemScheduler {
16+
17+
private final ActivityRecommendItemRepository activityRecommendItemRepository;
18+
19+
/**
20+
* ๋งค์ผ ์ƒˆ๋ฒฝ 3์‹œ์— ์‹คํ–‰ (cron: ์ดˆ ๋ถ„ ์‹œ ์ผ ์›” ์š”์ผ)
21+
* ์˜ค๋Š˜ ๊ธฐ์ค€์œผ๋กœ ์ดํ‹€(48์‹œ๊ฐ„) ์ „ ์ƒ์„ฑ๋œ ์•„์ดํ…œ ์‚ญ์ œ
22+
*/
23+
@Scheduled(cron = "0 0 3 * * *")
24+
@Transactional
25+
public void deleteOldRecommendItems() {
26+
// ๊ธฐ์ค€ ์‹œ๊ฐ„ ๊ณ„์‚ฐ: ํ˜„์žฌ ์‹œ๊ฐ„ - 2์ผ
27+
LocalDateTime targetDate = LocalDateTime.now().minusDays(2);
28+
29+
log.info("[Scheduler] ์ถ”์ฒœ ์•„์ดํ…œ ์‚ญ์ œ ์‹œ์ž‘ (๊ธฐ์ค€ ์‹œ๊ฐ„: {})", targetDate);
30+
31+
try {
32+
activityRecommendItemRepository.deleteOldItems(targetDate);
33+
log.info("[Scheduler] ์ถ”์ฒœ ์•„์ดํ…œ ์‚ญ์ œ ์™„๋ฃŒ");
34+
} catch (Exception e) {
35+
log.error("[Scheduler] ์‚ญ์ œ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {}", e.getMessage());
36+
}
37+
}
38+
}

โ€Žsrc/main/java/com/example/ForDay/domain/activity/service/ActivityService.javaโ€Ž

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
import com.example.ForDay.domain.activity.dto.FastAPIHobbyCardReqDto;
55
import com.example.ForDay.domain.activity.dto.request.UpdateActivityReqDto;
66
import com.example.ForDay.domain.activity.dto.response.FastAPIHobbyCardResDto;
7+
import com.example.ForDay.domain.activity.dto.response.GetAiRecommendItemsResDto;
78
import com.example.ForDay.domain.activity.entity.Activity;
9+
import com.example.ForDay.domain.activity.entity.ActivityRecommendItem;
10+
import com.example.ForDay.domain.activity.repository.ActivityRecommendItemRepository;
811
import com.example.ForDay.domain.friend.repository.FriendRelationRepository;
912
import com.example.ForDay.domain.friend.type.FriendRelationStatus;
1013
import com.example.ForDay.domain.hobby.dto.request.FastAPIRecommendReqDto;
@@ -36,6 +39,11 @@
3639
import org.springframework.util.StringUtils;
3740
import org.springframework.web.client.RestTemplate;
3841

42+
import java.time.LocalDate;
43+
import java.time.LocalDateTime;
44+
import java.time.LocalTime;
45+
import java.util.Collections;
46+
import java.util.List;
3947
import java.util.Objects;
4048

4149
@Slf4j
@@ -52,6 +60,7 @@ public class ActivityService {
5260
private final HobbyRepository hobbyRepository;
5361
private final FriendRelationRepository friendRelationRepository;
5462
private final RestTemplate restTemplate;
63+
private final ActivityRecommendItemRepository recommendItemRepository;
5564

5665
@Value("${fastapi.url}")
5766
private String fastApiBaseUrl;
@@ -353,6 +362,46 @@ public CollectActivityResDto collectActivity(Long hobbyId, Long activityId, Cust
353362
return new CollectActivityResDto(hobby.getId(), hobby.getHobbyName(), build.getId(), build.getContent(), "ํ™œ๋™์ด ์ •์ƒ์ ์œผ๋กœ ๋‹ด๊ฒผ์Šต๋‹ˆ๋‹ค.");
354363
}
355364

365+
@Transactional(readOnly = true)
366+
public GetAiRecommendItemsResDto getAiRecommendItems(CustomUserDetails user) {
367+
User currentUser = userUtil.getCurrentUser(user);
368+
String currentUserId = currentUser.getId();
369+
370+
// ๋ฉ”์„ธ์ง€ ์กฐํšŒ -> ๋…ผ์˜ ํ•œ ํ›„ ์ˆ˜์ • ์˜ˆ์ •
371+
372+
// 1. ํ˜„์žฌ ์œ ์ €์˜ ํ˜„์žฌ ์ง„ํ–‰ ์ค‘์ธ ์ทจ๋ฏธ ์กฐํšŒ
373+
List<Hobby> progressHobbies = hobbyRepository.findAllByUserIdAndStatusOrderByIdDesc(
374+
currentUserId,
375+
HobbyStatus.IN_PROGRESS
376+
);
377+
378+
if (progressHobbies.isEmpty()) {
379+
return new GetAiRecommendItemsResDto(new GetAiRecommendItemsResDto.MessageDto(), Collections.emptyList());
380+
}
381+
382+
// 2. ์˜ค๋Š˜ ๋‚ ์งœ ๋ฒ”์œ„ ์„ค์ •
383+
LocalDateTime startOfToday = LocalDate.now().atStartOfDay();
384+
LocalDateTime endOfToday = LocalDate.now().atTime(LocalTime.MAX);
385+
386+
// 3. ์˜ค๋Š˜ ์ƒ์„ฑ๋œ ์ถ”์ฒœ ์•„์ดํ…œ ์กฐํšŒ
387+
List<ActivityRecommendItem> items = recommendItemRepository.findAllByHobbiesAndDate(
388+
progressHobbies, startOfToday, endOfToday
389+
);
390+
391+
// 4. DTO ๋ณ€ํ™˜
392+
List<GetAiRecommendItemsResDto.ItemDto> itemDtos = items.stream()
393+
.map(item -> new GetAiRecommendItemsResDto.ItemDto(
394+
item.getId(),
395+
item.getHobby().getId(),
396+
item.getHobby().getHobbyName(),
397+
item.getContent(),
398+
item.getDescription()
399+
))
400+
.toList();
401+
402+
return new GetAiRecommendItemsResDto(new GetAiRecommendItemsResDto.MessageDto(), itemDtos);
403+
}
404+
356405
// ์œ ํ‹ธ ํด๋ž˜์Šค
357406
private Activity getActivityByUserId(Long activityId, String userId) {
358407
return activityRepository.findByIdAndUserId(activityId, userId).orElseThrow(() -> new CustomException(ErrorCode.ACTIVITY_NOT_FOUND));

โ€Žsrc/main/java/com/example/ForDay/domain/app/type/ImageUsageType.javaโ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@
33
public enum ImageUsageType {
44
ACTIVITY_RECORD,
55
PROFILE_IMAGE,
6-
COVER_IMAGE
6+
COVER_IMAGE,
7+
8+
TEST_ACTIVITY_RECORD,
9+
TEST_PROFILE_IMAGE,
10+
TEST_COVER_IMAGE
711
}

โ€Žsrc/main/java/com/example/ForDay/domain/auth/service/AuthService.javaโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public GuestLoginResDto guestLogin(GuestLoginReqDto reqDto) {
119119
String guestUserId = reqDto.getGuestUserId();
120120
boolean newUser;
121121

122-
if(reqDto.getGuestUserId().startsWith("withdrawn")) {
122+
if(guestUserId != null && StringUtils.hasText(guestUserId) && guestUserId.startsWith("withdrawn")) {
123123
throw new CustomException(ErrorCode.USER_NOT_FOUND);
124124
}
125125

โ€Žsrc/main/java/com/example/ForDay/domain/hobby/controller/HobbyController.javaโ€Ž

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,6 @@ public CollectActivityResDto collectActivity(@PathVariable(name = "hobbyId") Lon
168168
return activityService.collectActivity(hobbyId, activityId, user);
169169
}
170170

171-
@Override
172-
@GetMapping("/stories/tabs")
173-
public GetHobbyStoryTabsResDto getHobbyStoryTabs(@AuthenticationPrincipal CustomUserDetails user) {
174-
return hobbyService.getHobbyStoryTabs(user);
175-
}
176-
177171
@Override
178172
@GetMapping("/check")
179173
public CanCreateHobbyResDto canCreateHobby(@RequestParam(value = "name") String name,

0 commit comments

Comments
ย (0)