Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ dependencies {

// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

// mapstruct
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ public interface JoinCrewRepository extends JpaRepository<JoinCrew, Long> {
boolean existsByMemberAndJoinStatus(Member member, JoinStatus joinStatus);

@Query("""
SELECT jc.member
FROM JoinCrew jc
JOIN Crew c ON jc.crew = c
WHERE jc.role = :role
""")
SELECT jc.member
FROM JoinCrew jc
JOIN Crew c ON jc.crew = c
WHERE jc.role = :role
""")
Member findCrewLeader(@Param("role") Role role, Crew crew);

@Query("SELECT jc FROM JoinCrew jc WHERE jc.member.id = :memberId AND jc.joinStatus = :status")
Optional<JoinCrew> findByMemberIdAndJoinStatus(@Param("memberId") Long memberId,
@Param("status") JoinStatus status);
@Param("status") JoinStatus status);

@Query("""
SELECT new run.backend.domain.event.dto.response.EventCreationValidationDto(
Expand All @@ -41,8 +41,21 @@ Optional<JoinCrew> findByMemberIdAndJoinStatus(@Param("memberId") Long memberId,
AND captainJoin.joinStatus = :status
""")
Optional<EventCreationValidationDto> validateEventCreation(
@Param("requesterId") Long requesterId,
@Param("requesterId") Long requesterId,
@Param("runningCaptainId") Long runningCaptainId,
@Param("status") JoinStatus status
);

@Query("""
SELECT captainJoin.member
FROM JoinCrew captainJoin
WHERE captainJoin.member.id = :runningCaptainId
AND captainJoin.crew.id = :crewId
AND captainJoin.joinStatus = :status
""")
Optional<Member> findCrewMemberById(
@Param("runningCaptainId") Long runningCaptainId,
@Param("crewId") Long crewId,
@Param("status") JoinStatus status
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import run.backend.domain.event.dto.request.EventInfoRequest;
import run.backend.domain.event.service.EventServiceImpl;
import run.backend.domain.event.service.EventService;
import run.backend.domain.member.entity.Member;
import run.backend.global.annotation.member.Login;
import run.backend.global.common.response.CommonResponse;
Expand All @@ -19,18 +21,31 @@
@RequestMapping("/api/v1/events")
@Tag(name = "Events", description = "일정 관련 API")
public class EventController {
private final EventServiceImpl eventService;

private final EventService eventService;

@PostMapping
@PreAuthorize("hasRole('MANAGER') or hasRole('LEADER')")
@Operation(summary = "일정 생성", description = "러닝 일정를 생성합니다. LEADER 또는 MANAGER 권한이 필요합니다.")
@Operation(summary = "일정 생성", description = "러닝 일정을 생성합니다. LEADER 또는 MANAGER 권한이 필요합니다.")
public CommonResponse<Void> createEvent(
@RequestBody EventInfoRequest eventInfoRequest,
@Login Member member
@RequestBody EventInfoRequest eventInfoRequest,
@Login Member member
) {

eventService.createEvent(eventInfoRequest, member);
return new CommonResponse<>("일정 생성 성공");
return new CommonResponse<>("러닝 일정 생성 성공");
}

@PatchMapping("/{eventId}")
@PreAuthorize("hasRole('MANAGER') or hasRole('LEADER')")
@Operation(summary = "일정 수정", description = "러닝 일정을 수정합니다. LEADER 또는 MANAGER 권한이 필요합니다.")
public CommonResponse<Void> updateEvent(
@PathVariable Long eventId,
@RequestBody EventInfoRequest eventUpdateRequest,
@Login Member member
) {

eventService.updateEvent(eventId, eventUpdateRequest, member);
return new CommonResponse<>("러닝 일정 수정 성공");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,27 @@
import run.backend.domain.event.enums.WeekDay;

public record EventInfoRequest(
@Schema(description = "일정 제목")
String title,

@Schema(description = "일정 날짜")
LocalDate baseDate,

@Schema(description = "반복 주기", example = "NONE / WEEKLY")
RepeatCycle repeatCycle,

@Schema(description = "반복 요일", example = "MONDAY / TUESDAY / WEDNESDAY / THURSDAY / FRIDAY / SATURDAY / SUNDAY", nullable = true)
WeekDay repeatDays,

@Schema(description = "시작 시간")
LocalTime startTime,

@Schema(description = "종료 시간")
LocalTime endTime,

@Schema(description = "장소")
String place,

@Schema(description = "러닝캡틴 ID", example = "1")
Long runningCaptainId
) {
Expand Down
44 changes: 36 additions & 8 deletions src/main/java/run/backend/domain/event/entity/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ public class Event extends BaseEntity {

@Builder
public Event(
String title,
LocalDate date,
LocalTime startTime,
LocalTime endTime,
String place,
Crew crew,
CrewRecord record,
Member member
String title,
LocalDate date,
LocalTime startTime,
LocalTime endTime,
String place,
Crew crew,
CrewRecord record,
Member member
) {
this.title = title;
this.date = date;
Expand All @@ -84,4 +84,32 @@ public void incrementExpectedParticipants() {
public void incrementActualParticipants() {
this.actualParticipants++;
}

public void updateEvent(
String title,
LocalDate date,
LocalTime startTime,
LocalTime endTime,
String place,
Member runningCaptain
) {
if (title != null) {
this.title = title;
}
if (date != null) {
this.date = date;
}
if (startTime != null) {
this.startTime = startTime;
}
if (endTime != null) {
this.endTime = endTime;
}
if (place != null) {
this.place = place;
}
if (runningCaptain != null) {
this.member = runningCaptain;
}
}
}
54 changes: 45 additions & 9 deletions src/main/java/run/backend/domain/event/entity/PeriodicEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ public class PeriodicEvent extends BaseEntity {

@Builder
public PeriodicEvent(
String title,
LocalDate baseDate,
RepeatCycle repeatCycle,
WeekDay repeatDays,
LocalTime startTime,
LocalTime endTime,
String place,
Crew crew,
Member member
String title,
LocalDate baseDate,
RepeatCycle repeatCycle,
WeekDay repeatDays,
LocalTime startTime,
LocalTime endTime,
String place,
Crew crew,
Member member
) {
this.title = title;
this.baseDate = baseDate;
Expand All @@ -75,4 +75,40 @@ public PeriodicEvent(
this.crew = crew;
this.member = member;
}

public void updatePeriodicEvent(
String title,
LocalDate baseDate,
RepeatCycle repeatCycle,
WeekDay repeatDays,
LocalTime startTime,
LocalTime endTime,
String place,
Member runningCaptain
) {
if (title != null) {
this.title = title;
}
if (baseDate != null) {
this.baseDate = baseDate;
}
if (repeatCycle != null) {
this.repeatCycle = repeatCycle;
}
if (repeatDays != null) {
this.repeatDays = repeatDays;
}
if (startTime != null) {
this.startTime = startTime;
}
if (endTime != null) {
this.endTime = endTime;
}
if (place != null) {
this.place = place;
}
if (runningCaptain != null) {
this.member = runningCaptain;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
@AllArgsConstructor
public enum EventErrorCode implements ErrorCode {

RUNNING_CAPTAIN_NOT_CREW_MEMBER(6001, "러닝캡이 크루원이 아닙니다.");
RUNNING_CAPTAIN_NOT_CREW_MEMBER(6001, "러닝캡이 크루원이 아닙니다."),
EVENT_NOT_FOUND(6002, "일정을 찾을 수 없습니다.");

private final int errorCode;
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ public InvalidEventCreationRequest() {
super(EventErrorCode.RUNNING_CAPTAIN_NOT_CREW_MEMBER);
}
}

public static class EventNotFound extends EventException {
public EventNotFound() {
super(EventErrorCode.EVENT_NOT_FOUND);
}
}
}
60 changes: 41 additions & 19 deletions src/main/java/run/backend/domain/event/mapper/EventMapper.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@
package run.backend.domain.event.mapper;

import org.springframework.stereotype.Component;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
import run.backend.domain.crew.dto.response.EventProfileResponse;
import run.backend.domain.crew.entity.Crew;
import run.backend.domain.event.dto.request.EventInfoRequest;
import run.backend.domain.event.entity.Event;
import run.backend.domain.event.entity.JoinEvent;
import run.backend.domain.event.entity.PeriodicEvent;
import run.backend.domain.member.entity.Member;

import java.util.List;
import java.util.stream.Collectors;
@Mapper(
componentModel = "spring",
unmappedTargetPolicy = ReportingPolicy.IGNORE
)
public interface EventMapper {

@Component
public class EventMapper {
@Mapping(target = "date", source = "request.baseDate")
@Mapping(target = "member", source = "runningCaptain")
Event toEvent(EventInfoRequest request, Crew crew, Member runningCaptain);

public List<EventProfileResponse> toEventProfileList(List<Event> events) {
return events.stream()
.map(this::toEventProfile)
.collect(Collectors.toList());
}
@Mapping(target = "member", source = "runningCaptain")
PeriodicEvent toPeriodicEvent(EventInfoRequest request, Crew crew, Member runningCaptain);

@Mapping(target = "member", source = "runningCaptain")
@Mapping(target = "event", source = "event")
JoinEvent toJoinEvent(Event event, Member runningCaptain);

@Mapping(target = "eventId", source = "id")
@Mapping(target = "participants", source = "expectedParticipants")
EventProfileResponse toEventProfile(Event event);
Comment on lines +32 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우와 이렇게만 하면 자동으로 매칭이 되는거군요..!


List<EventProfileResponse> toEventProfileList(List<Event> events);

public EventProfileResponse toEventProfile(Event event) {
return EventProfileResponse.builder()
.eventId(event.getId())
.title(event.getTitle())
.date(event.getDate())
.startTime(event.getStartTime())
.endTime(event.getEndTime())
.participants(event.getExpectedParticipants())
.build();
default EventInfoRequest toEventInfoRequest(EventInfoRequest updateRequest, Event event) {
return new EventInfoRequest(
updateRequest.title() != null ? updateRequest.title() : event.getTitle(),
updateRequest.baseDate() != null ? updateRequest.baseDate() : event.getDate(),
updateRequest.repeatCycle(),
updateRequest.repeatDays(),
updateRequest.startTime() != null ? updateRequest.startTime() : event.getStartTime(),
updateRequest.endTime() != null ? updateRequest.endTime() : event.getEndTime(),
updateRequest.place() != null ? updateRequest.place() : event.getPlace(),
updateRequest.runningCaptainId() != null ? updateRequest.runningCaptainId()
: event.getMember().getId()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package run.backend.domain.event.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import run.backend.domain.event.entity.Event;
import run.backend.domain.event.entity.JoinEvent;
import run.backend.domain.member.entity.Member;

public interface JoinEventRepository extends JpaRepository<JoinEvent, Long> {


void deleteByEventAndMember(Event event, Member member);

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
package run.backend.domain.event.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import run.backend.domain.crew.entity.Crew;
import run.backend.domain.event.entity.PeriodicEvent;

import java.time.LocalTime;
import java.util.Optional;

public interface PeriodicEventRepository extends JpaRepository<PeriodicEvent, Long> {

@Query("""
SELECT pe
FROM PeriodicEvent pe
WHERE pe.crew = :crew
AND pe.title = :title
AND pe.startTime = :startTime
AND pe.endTime = :endTime
""")
Optional<PeriodicEvent> findByCrewAndTitleAndTime(
@Param("crew") Crew crew,
@Param("title") String title,
@Param("startTime") LocalTime startTime,
@Param("endTime") LocalTime endTime
);
}
Loading