Skip to content

Commit 7ca286d

Browse files
committed
[refector] 캘린더 서비스/컨트롤러 V2 명명 규칙 적용
1 parent 33ad385 commit 7ca286d

4 files changed

Lines changed: 779 additions & 0 deletions

File tree

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package store.lastdance.controller.calendar;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
5+
import io.swagger.v3.oas.annotations.tags.Tag;
6+
import jakarta.validation.Valid;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.springframework.data.domain.Pageable;
10+
import org.springframework.format.annotation.DateTimeFormat;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.http.ResponseEntity;
13+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
14+
import org.springframework.web.bind.annotation.*;
15+
import store.lastdance.dto.calender.request.CreateCalendarRequestDTO;
16+
import store.lastdance.dto.calender.request.UpdateCalendarRequestDTO;
17+
import store.lastdance.dto.calender.response.CalendarResponseDTO;
18+
import store.lastdance.dto.response.ApiResponse;
19+
import store.lastdance.exception.CustomException;
20+
import store.lastdance.exception.ErrorCode;
21+
import store.lastdance.security.oauth.CustomOAuth2User;
22+
import store.lastdance.service.calendar.CalendarV2Service;
23+
24+
import java.time.LocalDateTime;
25+
import java.util.List;
26+
import java.util.UUID;
27+
28+
@Tag(name = "Calender", description = "캘린더 관리 API")
29+
@RestController
30+
@RequestMapping("/api/v2/calendars")
31+
@RequiredArgsConstructor
32+
@Slf4j
33+
public class CalendarV2Controller {
34+
35+
private final CalendarV2Service calendarService;
36+
37+
@Operation(
38+
summary = "캘린더 생성",
39+
description = "새로운 일정을 생성합니다.",
40+
security = @SecurityRequirement(name = "bearerAuth")
41+
)
42+
@PostMapping
43+
public ResponseEntity<ApiResponse<CalendarResponseDTO>> createCalendar(
44+
@Valid @RequestBody CreateCalendarRequestDTO request,
45+
@RequestParam(required = false) UUID groupId,
46+
@AuthenticationPrincipal CustomOAuth2User user) {
47+
48+
try {
49+
CalendarResponseDTO calendar = calendarService.createCalendar(request, user.getUserId(), groupId);
50+
51+
return ResponseEntity.status(HttpStatus.CREATED)
52+
.body(ApiResponse.success(calendar));
53+
54+
} catch (Exception e) {
55+
log.error("일정 생성 실패 - 사용자: {}, 에러: {}", user.getUserId(), e.getMessage(), e);
56+
throw new CustomException(ErrorCode.CALENDAR_CREATE_FAILED);
57+
}
58+
}
59+
60+
@Operation(
61+
summary = "내 일정 목록 조회",
62+
description = "사용자의 모든 일정을 조회합니다. (필터링 가능)",
63+
security = @SecurityRequirement(name = "bearerAuth")
64+
)
65+
@GetMapping("/me")
66+
public ResponseEntity<ApiResponse<List<CalendarResponseDTO>>> getMyCalendars(
67+
@RequestParam(required = false, defaultValue = "MONTHLY") String viewType,
68+
@RequestParam(required = false) LocalDateTime dateTime,
69+
@RequestParam(required = false) String type,
70+
@RequestParam(required = false) String category,
71+
@RequestParam(required = false) UUID groupId,
72+
@AuthenticationPrincipal CustomOAuth2User user,
73+
Pageable pageable) {
74+
75+
try {
76+
List<CalendarResponseDTO> responses = calendarService.getCalendarsByUser(
77+
user.getUserId(), viewType, dateTime, type, category, groupId, pageable);
78+
79+
return ResponseEntity.ok(ApiResponse.success(responses));
80+
} catch (Exception e) {
81+
log.error("일정 조회 실패 - 사용자: {}, 에러: {}", user.getUserId(), e.getMessage());
82+
throw new CustomException(ErrorCode.CALENDAR_FOUND_FAILED);
83+
}
84+
}
85+
86+
@Operation(
87+
summary = "특정 일정 상세 조회",
88+
description = "특정 일정의 상세 정보를 조회합니다.",
89+
security = @SecurityRequirement(name = "bearerAuth")
90+
)
91+
@GetMapping("/{calendarId}")
92+
public ResponseEntity<ApiResponse<CalendarResponseDTO>> getCalendar(
93+
@PathVariable Long calendarId,
94+
@AuthenticationPrincipal CustomOAuth2User user) {
95+
96+
try {
97+
CalendarResponseDTO calendar = calendarService.getCalendarById(calendarId, user.getUserId());
98+
99+
return ResponseEntity.ok(ApiResponse.success(calendar));
100+
101+
} catch (CustomException e) {
102+
log.warn("일정 조회 실패 - 권한 없음: 사용자 {}, 일정 ID: {}", user.getUserId(), calendarId);
103+
throw new CustomException(ErrorCode.CALENDAR_ACCESS_DENIED);
104+
} catch (Exception e) {
105+
log.error("일정 조회 실패 - 일정 ID: {}, 에러: {}", calendarId, e.getMessage());
106+
throw new CustomException(ErrorCode.CALENDAR_FOUND_FAILED);
107+
}
108+
}
109+
110+
@Operation(
111+
summary = "일정 수정",
112+
description = "기존 일정의 정보를 수정합니다.",
113+
security = @SecurityRequirement(name = "bearerAuth")
114+
)
115+
@PatchMapping("/{calendarId}")
116+
public ResponseEntity<ApiResponse<CalendarResponseDTO>> updateCalendar(
117+
@PathVariable Long calendarId,
118+
@Valid @RequestBody UpdateCalendarRequestDTO request,
119+
@AuthenticationPrincipal CustomOAuth2User user) {
120+
121+
try {
122+
CalendarResponseDTO calendar = calendarService.updateCalendar(calendarId, request, user.getUserId());
123+
124+
return ResponseEntity.ok(ApiResponse.success(calendar));
125+
126+
} catch (CustomException e) {
127+
log.warn("일정 수정 실패 - 권한 없음: 사용자 {}, 일정 ID: {}", user.getUserId(), calendarId);
128+
throw new CustomException(ErrorCode.CALENDAR_ACCESS_DENIED);
129+
130+
} catch (Exception e) {
131+
log.error("일정 수정 실패 - 일정 ID: {}, 에러: {}", calendarId, e.getMessage());
132+
throw new CustomException(ErrorCode.CALENDAR_UPDATE_FAILED);
133+
}
134+
}
135+
136+
@Operation(
137+
summary = "일정 삭제",
138+
description = "기존 일정을 삭제합니다.",
139+
security = @SecurityRequirement(name = "bearerAuth")
140+
)
141+
@DeleteMapping("/{calendarId}")
142+
public ResponseEntity<ApiResponse<Void>> deleteCalendar(
143+
@PathVariable Long calendarId,
144+
@RequestParam(required = false)
145+
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
146+
LocalDateTime instanceDate,
147+
@AuthenticationPrincipal CustomOAuth2User user) {
148+
149+
try {
150+
calendarService.deleteCalendar(calendarId, instanceDate, user.getUserId());
151+
152+
return ResponseEntity.ok(ApiResponse.success());
153+
154+
} catch (CustomException e) {
155+
log.warn("일정 삭제 실패 - 권한 없음: 사용자 {}, 일정 ID: {}",
156+
user.getUserId(), calendarId);
157+
throw new CustomException(ErrorCode.CALENDAR_ACCESS_DENIED);
158+
159+
} catch (Exception e) {
160+
log.error("일정 삭제 실패 - 일정 ID: {}, 에러: {}", calendarId, e.getMessage());
161+
throw new CustomException(ErrorCode.CALENDAR_DELETE_FAILED);
162+
}
163+
}
164+
165+
@Operation(
166+
summary = "그룹 일정 목록 조회",
167+
description = "특정 그룹의 모든 일정을 조회합니다. (필터링 가능)",
168+
security = @SecurityRequirement(name = "bearerAuth")
169+
)
170+
@GetMapping("/groups/{groupId}")
171+
public ResponseEntity<ApiResponse<List<CalendarResponseDTO>>> getGroupCalendars(
172+
@PathVariable UUID groupId,
173+
@RequestParam(required = false, defaultValue = "MONTHLY") String viewType,
174+
@RequestParam(required = false) LocalDateTime dateTime,
175+
@RequestParam(required = false) String type,
176+
@RequestParam(required = false) String category,
177+
@AuthenticationPrincipal CustomOAuth2User user,
178+
Pageable pageable) {
179+
180+
try {
181+
if (!calendarService.isGroupMember(groupId, user.getUserId())) {
182+
throw new CustomException(ErrorCode.CALENDAR_ACCESS_DENIED);
183+
}
184+
185+
List<CalendarResponseDTO> responses = calendarService.getCalendarsByUser(
186+
user.getUserId(), viewType, dateTime, type, category, groupId, pageable);
187+
188+
return ResponseEntity.ok(ApiResponse.success(responses));
189+
190+
} catch (Exception e) {
191+
log.error("그룹 일정 조회 실패 - 그룹 ID: {}, 에러: {}", groupId, e.getMessage());
192+
throw new CustomException(ErrorCode.CALENDAR_FOUND_FAILED);
193+
}
194+
}
195+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package store.lastdance.converter.calendar;
2+
3+
import org.springframework.stereotype.Component;
4+
import store.lastdance.domain.calendar.Calendar;
5+
import store.lastdance.domain.calendar.CalendarType;
6+
import store.lastdance.domain.group.Group;
7+
import store.lastdance.domain.user.User;
8+
import store.lastdance.dto.calender.request.CreateCalendarRequestDTO;
9+
import store.lastdance.dto.calender.response.CalendarResponseDTO;
10+
11+
import java.time.Duration;
12+
import java.time.LocalDateTime;
13+
14+
@Component
15+
public class CalendarConverter {
16+
public Calendar toEntity(CreateCalendarRequestDTO request, User user, Group group, CalendarType type) {
17+
return Calendar.builder()
18+
.title(request.getTitle())
19+
.description(request.getDescription())
20+
.startDate(request.getStartDate())
21+
.endDate(request.getEndDate())
22+
.isAllDay(request.getIsAllDay())
23+
.type(type)
24+
.category(request.getCategory())
25+
.group(group)
26+
.user(user)
27+
.repeatType(request.getRepeatType())
28+
.repeatEndDate(request.getRepeatEndDate())
29+
.build();
30+
}
31+
32+
public Calendar toEntity(Calendar base, LocalDateTime newStartDate, Duration duration) {
33+
return Calendar.builder()
34+
.title(base.getTitle())
35+
.description(base.getDescription())
36+
.startDate(newStartDate)
37+
.endDate(newStartDate.plus(duration))
38+
.isAllDay(base.getIsAllDay())
39+
.type(base.getType())
40+
.category(base.getCategory())
41+
.group(base.getGroup())
42+
.user(base.getUser())
43+
.repeatType(base.getRepeatType())
44+
.repeatEndDate(base.getRepeatEndDate())
45+
.build();
46+
}
47+
48+
public CalendarResponseDTO toDto(Calendar calendar, User user, Group group, String groupName) {
49+
return CalendarResponseDTO.builder()
50+
.calendarId(calendar.getCalendarId())
51+
.title(calendar.getTitle())
52+
.description(calendar.getDescription())
53+
.startDate(calendar.getStartDate())
54+
.endDate(calendar.getEndDate())
55+
.isAllDay(calendar.getIsAllDay())
56+
.type(calendar.getType())
57+
.category(calendar.getCategory())
58+
.groupId(group != null ? group.getGroupId() : null)
59+
.groupName(groupName)
60+
.userId(user.getUserId())
61+
.repeatType(calendar.getRepeatType())
62+
.repeatEndDate(calendar.getRepeatEndDate())
63+
.createdAt(calendar.getCreatedAt())
64+
.build();
65+
}
66+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package store.lastdance.service.calendar;
2+
3+
import org.springframework.data.domain.Pageable;
4+
import store.lastdance.dto.calender.request.CreateCalendarRequestDTO;
5+
import store.lastdance.dto.calender.request.UpdateCalendarRequestDTO;
6+
import store.lastdance.dto.calender.response.CalendarResponseDTO;
7+
8+
import java.time.LocalDateTime;
9+
import java.util.List;
10+
import java.util.UUID;
11+
12+
public interface CalendarV2Service {
13+
14+
CalendarResponseDTO createCalendar(CreateCalendarRequestDTO request, UUID userId, UUID groupId);
15+
16+
List<CalendarResponseDTO> getCalendarsByUser(UUID userId, String viewType, LocalDateTime dateTime, String type, String category, UUID groupId, Pageable pageable);
17+
18+
CalendarResponseDTO getCalendarById(Long calendarId, UUID userId);
19+
20+
CalendarResponseDTO updateCalendar(Long calendarId, UpdateCalendarRequestDTO request, UUID userId);
21+
22+
void deleteCalendar(Long calendarId, LocalDateTime instanceDate, UUID userId);
23+
24+
boolean isGroupMember(UUID groupId, UUID userId);
25+
}

0 commit comments

Comments
 (0)