Skip to content

Commit a9254a3

Browse files
authored
Merge pull request #114 from UMCWegg/feature/#7
Feature/#7
2 parents 93d61fd + 6b3342c commit a9254a3

File tree

9 files changed

+65
-22
lines changed

9 files changed

+65
-22
lines changed

src/main/java/umc/wegg/controller/NotificationController.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import umc.wegg.domain.User;
1919
import umc.wegg.domain.apiPayload.ApiResponse;
2020
import umc.wegg.domain.enums.AccountVisibility;
21+
import umc.wegg.domain.enums.FollowStatus;
2122
import umc.wegg.dto.*;
23+
import umc.wegg.repository.FollowRepository;
2224
import umc.wegg.repository.UserRepository;
2325
import umc.wegg.service.NotificationService.NotificationService;
2426
import umc.wegg.service.UserService.UserCommandService;
@@ -32,6 +34,7 @@ public class NotificationController {
3234

3335
private final NotificationService notificationService;
3436
private final UserRepository userRepository;
37+
private final FollowRepository followRepository;
3538

3639
//Last-Event-ID는 SSE 연결이 끊어졌을 경우, 클라이언트가 수신한 마지막 데이터의 id 값을 의미합니다. 항상 존재하는 것이 아니기 때문에 false
3740
@GetMapping(value = "/subscribe", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@@ -54,10 +57,18 @@ public ApiResponse<NotificationResponseDTO.NotificationListDTO> getUserNotificat
5457
.map(NotificationConverter::toResultDTO)
5558
.toList();
5659

57-
// 🔹 accountVisibility와 알림 리스트를 포함한 DTO 반환
60+
// 🔹 followStatus가 WAITING인 요청 개수 조회
61+
Long waitingFollowRequests = followRepository.countByFolloweeIdAndFollowStatus(userId, FollowStatus.WAITING);
62+
63+
// 🔹 updatedAt이 가장 최신인 follower의 accountId 조회
64+
String latestFollowerAccountId = followRepository.findLatestFollowerAccountIdByFolloweeId(userId).orElse(null);
65+
66+
// 🔹 DTO 생성 및 응답 반환
5867
NotificationResponseDTO.NotificationListDTO response = NotificationResponseDTO.NotificationListDTO.builder()
5968
.accountVisibility(AccountVisibility.valueOf(accountVisibility))
6069
.notifications(result)
70+
.latestFollowerAccountId(latestFollowerAccountId)
71+
.waitingFollowRequests(waitingFollowRequests)
6172
.build();
6273

6374
return ApiResponse.onSuccess(response);

src/main/java/umc/wegg/converter/PlanConverter.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import umc.wegg.domain.Plan;
55
import umc.wegg.domain.User;
66
import umc.wegg.domain.Address;
7+
import umc.wegg.domain.apiPayload.ApiResponse;
78
import umc.wegg.domain.enums.LateStatus;
89
import umc.wegg.domain.enums.PlanStatus;
910
import umc.wegg.dto.PlanRequestDTO;
@@ -38,25 +39,26 @@ public static PlanResponseDTO.PlanUpdateResultDTO toPlanUpdateResultDTO(Plan pla
3839
.build();
3940
}
4041

41-
public static List<Plan> toPlan(PlanRequestDTO.PlanAddDTO request,
42-
UserRepository userRepository,
43-
Address address,
44-
PlanRepository planRepository) {
42+
public static ApiResponse<List<Plan>> toPlan(PlanRequestDTO.PlanAddDTO request,
43+
UserRepository userRepository,
44+
Address address,
45+
PlanRepository planRepository) {
4546
PlanStatus status = request.getStatus() != null ? request.getStatus() : PlanStatus.YET;
4647
User user = userRepository.findById(request.getUserId())
4748
.orElseThrow(() -> new RuntimeException("User not found"));
4849

4950
List<Plan> planList = new ArrayList<>();
50-
LocalDate today = LocalDate.now(); // 오늘 날짜
51-
LocalDate maxAllowedDate = today.plusDays(14); // 2주 후까지만 허용
51+
LocalDate today = LocalDate.now();
52+
LocalDate maxAllowedDate = today.plusDays(14);
5253

53-
request.getPlanDates().forEach(planDate -> {
54-
// ✅ 날짜 검증 (과거 및 15일 초과)
54+
for (LocalDate planDate : request.getPlanDates()) {
55+
// ✅ 과거 날짜 체크
5556
if (planDate.isBefore(today)) {
56-
throw new IllegalArgumentException("이미 날짜가 지났습니다.");
57+
return ApiResponse.onFailure("FAIL", "이미 날짜가 지났습니다.", null);
5758
}
59+
// ✅ 2주 후 초과 체크
5860
if (planDate.isAfter(maxAllowedDate)) {
59-
throw new IllegalArgumentException("2주 뒤까지의 계획만 설정 가능합니다.");
61+
return ApiResponse.onFailure("FAIL", "2주 뒤까지의 계획만 설정 가능합니다.", null);
6062
}
6163

6264
LocalDateTime startTime = LocalDateTime.of(planDate, request.getStartTime().truncatedTo(ChronoUnit.MINUTES));
@@ -66,12 +68,12 @@ public static List<Plan> toPlan(PlanRequestDTO.PlanAddDTO request,
6668
finishTime = finishTime.plusDays(1);
6769
}
6870

69-
// ✅ 겹치는 일정 확인
71+
// ✅ 일정 겹침 체크
7072
boolean hasConflict = planRepository.existsByUserAndStartTimeBeforeAndFinishTimeAfter(
7173
user, finishTime, startTime);
7274

7375
if (hasConflict) {
74-
throw new IllegalStateException("해당 시간대에 이미 일정이 존재합니다.");
76+
return ApiResponse.onFailure("FAIL", "해당 시간대에 이미 일정이 존재합니다.", null);
7577
}
7678

7779
// Plan 객체 생성 및 저장
@@ -86,11 +88,11 @@ public static List<Plan> toPlan(PlanRequestDTO.PlanAddDTO request,
8688
.planDate(planDate)
8789
.build();
8890

89-
planRepository.save(newPlan); // Plan 저장
90-
planList.add(newPlan); // 저장된 Plan 추가
91-
});
91+
planRepository.save(newPlan);
92+
planList.add(newPlan);
93+
}
9294

93-
return planList; // Plan 리스트 반환
95+
return ApiResponse.onSuccess(planList); // 성공 응답
9496
}
9597
// PlanRequestDTO를 사용하여 기존 Plan을 업데이트하는 메서드 추가
9698
public static Plan toPlanUpdate(PlanRequestDTO.PlanUpdateDTO requestDTO, Plan existingPlan, AddressRepository addressRepository) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package umc.wegg.domain.enums;
22

33
public enum NotificationType {
4-
POST, EMOJI, COMMENT, PLAN_REMINDER, PLACE_VERIFY, RANDOM_VERIFY, EGG
4+
POST, EMOJI, COMMENT, FOLLOW, PLAN_REMINDER, PLACE_VERIFY, RANDOM_VERIFY, EGG
55
}

src/main/java/umc/wegg/dto/NotificationResponseDTO.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ public class NotificationResponseDTO {
1818
@AllArgsConstructor
1919
public static class NotificationListDTO {
2020
AccountVisibility accountVisibility; // 🔹 로그인한 유저의 accountVisibility 추가
21+
String latestFollowerAccountId;
22+
Long waitingFollowRequests;
2123
List<ResultDTO> notifications; // 🔹 기존의 알림 리스트
24+
2225
}
2326

2427
@Builder

src/main/java/umc/wegg/repository/FollowRepository.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
public interface FollowRepository extends JpaRepository<Follow, Long> {
1515
Optional<Follow> findById(Long id);
1616

17+
//웨이팅 개수 세기
18+
Long countByFolloweeIdAndFollowStatus(Long followeeId, FollowStatus followStatus);
19+
//한명의 어카운트아이디 가져오기
20+
@Query("SELECT f.follower.accountId FROM Follow f WHERE f.followee.id = :followeeId ORDER BY f.updatedAt DESC LIMIT 1")
21+
Optional<String> findLatestFollowerAccountIdByFolloweeId(@Param("followeeId") Long followeeId);
22+
1723
boolean existsByFollowerAndFolloweeAndFollowStatus(User follower, User followee, FollowStatus status);
1824

1925
@Query("SELECT COUNT(f) FROM Follow f WHERE f.followee.id = :userId")

src/main/java/umc/wegg/service/FollowService/FollowCommandServiceImpl.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import lombok.RequiredArgsConstructor;
44
import org.springframework.data.domain.PageRequest;
55
import org.springframework.stereotype.Service;
6+
import umc.wegg.domain.Setting;
67
import umc.wegg.domain.User;
78
import umc.wegg.domain.enums.AccountVisibility;
89
import umc.wegg.domain.enums.FollowStatus;
@@ -11,7 +12,9 @@
1112
import umc.wegg.dto.FollowResponseDTO;
1213
import umc.wegg.repository.ContactFriendsRepository;
1314
import umc.wegg.repository.FollowRepository;
15+
import umc.wegg.repository.SettingRepository;
1416
import umc.wegg.repository.UserRepository;
17+
import umc.wegg.service.NotificationService.NotificationService;
1518

1619
import java.util.*;
1720
import java.util.stream.Collectors;
@@ -23,7 +26,7 @@ public class FollowCommandServiceImpl implements FollowCommandService {
2326
private final FollowRepository followRepository;
2427
private final UserRepository userRepository;
2528
private final ContactFriendsRepository contactFriendsRepository; // 연락처 친구 조회를 위해 필요
26-
29+
private final NotificationService notificationService;
2730
/**
2831
* 팔로우 요청 생성
2932
* @param requestDTO 팔로우 요청 데이터
@@ -47,6 +50,10 @@ public FollowStatus createFollowRequest(FollowRequestDTO.CreateFollowRequestDTO
4750
AccountVisibility visibility = followee.getSetting().getAccountVisibility();
4851
FollowStatus followStatus = (visibility == AccountVisibility.PUBLIC) ? FollowStatus.SUCCEEDED : FollowStatus.WAITING;
4952

53+
// 알림 메시지 작성
54+
String message = (visibility == AccountVisibility.PUBLIC) ? follower.getAccountId() + "님이 팔로우를 시작합니다." : follower.getAccountId() + "님이 팔로우를 요청했습니다.";
55+
notificationService.sendNotificationToFollowee(followee, follower.getId(), message, "FOLLOW", follower.getProfileImage());
56+
5057
// 팔로우 요청 저장
5158
Follow follow = Follow.builder()
5259
.follower(follower)

src/main/java/umc/wegg/service/NotificationService/NotificationService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public interface NotificationService {
1414
void send(User receiver, NotificationType notificationType, String content, String url, String profileImage);
1515
void sendNotificationToPostOwner(User postOwner, Long postId, String message, String notificationType, String profileImage);
1616
void sendNotificationToEggOwner(User planUser, String content, String notificationType, String profileImage);
17+
void sendNotificationToFollowee(User followee, Long followerId, String content, String notificationType, String profileImage);
1718
void scheduleNotification(User user, NotificationType type, LocalDateTime notificationTime, String content, String url, String profileImage);
1819
List<Notification> getUserNotifications(Long userId);
1920
Notification readNotification(Long notificationId, NotificationRequestDTO.ReadDTO request);

src/main/java/umc/wegg/service/NotificationService/NotificationServiceImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ public void sendNotificationToFollower(User follower, Long postId, String conten
128128
NotificationType type = NotificationType.valueOf(notificationType.toUpperCase());
129129
send(follower, type, content, "/posts/" + postId + "/view", profileImage);
130130
}
131+
public void sendNotificationToFollowee(User followee, Long followerId, String content, String notificationType, String profileImage) {
132+
NotificationType type = NotificationType.valueOf(notificationType.toUpperCase());
133+
send(followee, type, content, "/home/month/" + followerId, profileImage);
134+
}
131135

132136
public void scheduleNotification(User user, NotificationType type, LocalDateTime notificationTime, String content, String url, String profileImage) {
133137
long delay = notificationTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - System.currentTimeMillis();

src/main/java/umc/wegg/service/PlanService/PlanCommandServiceImpl.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import umc.wegg.domain.Egg;
99
import umc.wegg.domain.Address;
1010
import umc.wegg.domain.Plan;
11+
import umc.wegg.domain.apiPayload.ApiResponse;
12+
import umc.wegg.domain.apiPayload.code.status.SuccessStatus;
1113
import umc.wegg.domain.enums.EggStatus;
1214
import umc.wegg.domain.enums.NotificationType;
1315
import umc.wegg.dto.MapResponseDTO;
@@ -23,6 +25,7 @@
2325
import java.time.Instant;
2426
import java.time.LocalDateTime;
2527
import java.time.ZoneId;
28+
import java.util.Collections;
2629
import java.util.List;
2730
import java.util.stream.Collectors;
2831

@@ -50,7 +53,7 @@ public List<PlanResponseDTO.PlanAddResultDTO> addPlan(PlanRequestDTO.PlanAddDTO
5053
}
5154
} catch (Exception e) {
5255
e.printStackTrace();
53-
return null; // 변환 실패 시 처리
56+
return Collections.emptyList(); // 변환 실패 시 빈 리스트 반환
5457
}
5558

5659
Address address = addressRepository.findByPlaceName(request.getPlaceName()).orElse(null);
@@ -60,8 +63,14 @@ public List<PlanResponseDTO.PlanAddResultDTO> addPlan(PlanRequestDTO.PlanAddDTO
6063
addressRepository.save(address);
6164
}
6265

63-
// ✅ 컨버터가 이제 List<Plan>을 반환함
64-
List<Plan> newPlans = PlanConverter.toPlan(request, userRepository, address, planRepository);
66+
// ✅ 컨버터가 이제 ApiResponse<List<Plan>>을 반환함
67+
ApiResponse<List<Plan>> response = PlanConverter.toPlan(request, userRepository, address, planRepository);
68+
69+
if (!response.getCode().equals(SuccessStatus._OK.getCode())) {
70+
return List.of(new PlanResponseDTO.PlanAddResultDTO(null, null, response.getMessage()));
71+
}
72+
73+
List<Plan> newPlans = response.getResult();
6574

6675
// ✅ 응답용 DTO 생성
6776
List<PlanResponseDTO.PlanAddResultDTO> resultDTOList = newPlans.stream()

0 commit comments

Comments
 (0)