diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleController.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleController.java index 53f0d56db..76e50cc14 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleController.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleController.java @@ -1,11 +1,12 @@ package gg.calendar.api.user.schedule.publicschedule.controller; - import javax.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,7 +14,10 @@ import gg.auth.UserDto; import gg.auth.argumentresolver.Login; import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleCreateReqDto; +import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleUpdateReqDto; +import gg.calendar.api.user.schedule.publicschedule.controller.response.PublicScheduleUpdateResDto; import gg.calendar.api.user.schedule.publicschedule.service.PublicScheduleService; +import gg.data.calendar.PublicSchedule; import io.swagger.v3.oas.annotations.Parameter; import lombok.RequiredArgsConstructor; @@ -29,5 +33,13 @@ public ResponseEntity publicScheduleCreate(@RequestBody @Valid PublicSched publicScheduleService.createPublicSchedule(req, userDto.getId()); return ResponseEntity.status(HttpStatus.CREATED).build(); } + + @PutMapping("/{id}") + public ResponseEntity publicScheduleUpdate(@PathVariable Long id, + @RequestBody @Valid PublicScheduleUpdateReqDto req, + @Login @Parameter(hidden = true) UserDto userDto) { + PublicSchedule updateSchedule = publicScheduleService.updatePublicSchedule(id, req, userDto.getId()); + return ResponseEntity.ok(PublicScheduleUpdateResDto.toDto(updateSchedule)); + } } diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDto.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDto.java index 8bfc29712..c1e36d133 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDto.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDto.java @@ -2,7 +2,9 @@ import java.time.LocalDateTime; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import gg.data.calendar.PublicSchedule; import gg.data.calendar.type.DetailClassification; @@ -26,12 +28,18 @@ public class PublicScheduleCreateReqDto { private EventTag eventTag; private JobTag jobTag; private TechTag techTag; - @NotNull + @NotBlank private String author; - @NotNull + + @NotBlank + @Size(max = 50, message = "제목은 50자이하로 입력해주세요.") private String title; + + @Size(max = 2000, message = "내용은 2000자이하로 입력해주세요.") private String content; + private String link; + @NotNull private LocalDateTime startTime; @NotNull diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDto.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDto.java deleted file mode 100644 index 71ace1a3a..000000000 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package gg.calendar.api.user.schedule.publicschedule.controller.request; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class PublicScheduleReqDto { - -} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDto.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDto.java index 3feaf7364..be2919f98 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDto.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDto.java @@ -1,11 +1,51 @@ package gg.calendar.api.user.schedule.publicschedule.controller.request; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.springframework.format.annotation.DateTimeFormat; + +import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.EventTag; +import gg.data.calendar.type.JobTag; +import gg.data.calendar.type.ScheduleStatus; +import gg.data.calendar.type.TechTag; import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter +@Builder +@AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) public class PublicScheduleUpdateReqDto { + @NotNull + private DetailClassification classification; + private EventTag eventTag; + private JobTag jobTag; + private TechTag techTag; + @NotBlank + private String author; + + @NotBlank + @Size(max = 50, message = "제목은 50자이하로 입력해주세요.") + private String title; + + @Size(max = 2000, message = "내용은 2000자이하로 입력해주세요.") + private String content; + private String link; + + @NotNull + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + private LocalDateTime startTime; + @NotNull + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + private LocalDateTime endTime; + private ScheduleStatus status; } diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleResDto.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleResDto.java deleted file mode 100644 index d8d501aa7..000000000 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleResDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package gg.calendar.api.user.schedule.publicschedule.controller.response; - -public class PublicScheduleResDto { -} diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDto.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDto.java index 2abb6d988..6c285fcea 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDto.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDto.java @@ -1,11 +1,63 @@ package gg.calendar.api.user.schedule.publicschedule.controller.response; +import gg.data.calendar.PublicSchedule; +import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.EventTag; +import gg.data.calendar.type.JobTag; +import gg.data.calendar.type.TechTag; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class PublicScheduleUpdateResDto { + private Long id; + private DetailClassification classification; + private EventTag eventTag; + private JobTag jobTag; + private TechTag techTag; + private String author; + private String title; + private String content; + private String link; + private String startTime; + private String endTime; + private String status; + @Builder + private PublicScheduleUpdateResDto(Long id, DetailClassification classification, EventTag eventTag, JobTag jobTag, + TechTag techTag, String author, String title, String content, String link, String startTime, String endTime, + String status) { + this.id = id; + this.classification = classification; + this.eventTag = eventTag; + this.jobTag = jobTag; + this.techTag = techTag; + this.author = author; + this.title = title; + this.content = content; + this.link = link; + this.startTime = startTime; + this.endTime = endTime; + this.status = status; + } + + public static PublicScheduleUpdateResDto toDto(PublicSchedule publicSchedule) { + return PublicScheduleUpdateResDto.builder() + .id(publicSchedule.getId()) + .classification(publicSchedule.getClassification()) + .eventTag(publicSchedule.getEventTag()) + .jobTag(publicSchedule.getJobTag()) + .techTag(publicSchedule.getTechTag()) + .author(publicSchedule.getAuthor()) + .title(publicSchedule.getTitle()) + .content(publicSchedule.getContent()) + .link(publicSchedule.getLink()) + .startTime(publicSchedule.getStartTime().toString()) + .endTime(publicSchedule.getEndTime().toString()) + .status(publicSchedule.getStatus().name()) + .build(); + } } diff --git a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java index 8727777a7..62554d935 100644 --- a/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java +++ b/gg-calendar-api/src/main/java/gg/calendar/api/user/schedule/publicschedule/service/PublicScheduleService.java @@ -1,15 +1,20 @@ package gg.calendar.api.user.schedule.publicschedule.service; +import java.time.LocalDateTime; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleCreateReqDto; +import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleUpdateReqDto; import gg.data.calendar.PublicSchedule; import gg.data.user.User; import gg.repo.calendar.PublicScheduleRepository; import gg.repo.user.UserRepository; import gg.utils.exception.ErrorCode; -import gg.utils.exception.custom.CustomRuntimeException; +import gg.utils.exception.custom.ForbiddenException; +import gg.utils.exception.custom.InvalidParameterException; +import gg.utils.exception.custom.NotExistException; import lombok.RequiredArgsConstructor; @Service @@ -23,12 +28,35 @@ public class PublicScheduleService { public void createPublicSchedule(PublicScheduleCreateReqDto req, Long userId) { User user = userRepository.getById(userId); if (!user.getIntraId().equals(req.getAuthor())) { - throw new CustomRuntimeException(ErrorCode.CALENDAR_AUTHOR_NOT_MATCH); - } - if (req.getStartTime().isAfter(req.getEndTime())) { - throw new CustomRuntimeException(ErrorCode.CALENDAR_BEFORE_DATE); + throw new ForbiddenException(ErrorCode.CALENDAR_AUTHOR_NOT_MATCH); } + validateTimeRange(req.getStartTime(), req.getEndTime()); PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), req); publicScheduleRepository.save(publicSchedule); } + + @Transactional + public PublicSchedule updatePublicSchedule(Long scheduleId, PublicScheduleUpdateReqDto req, Long userId) { + User user = userRepository.getById(userId); + PublicSchedule existingSchedule = publicScheduleRepository.findById(scheduleId) + .orElseThrow(() -> new NotExistException(ErrorCode.PUBLIC_SCHEDULE_NOT_FOUND)); + checkAuthor(existingSchedule.getAuthor(), user); + checkAuthor(req.getAuthor(), user); + validateTimeRange(req.getStartTime(), req.getEndTime()); + existingSchedule.update(req.getClassification(), req.getEventTag(), req.getJobTag(), req.getTechTag(), + req.getTitle(), req.getContent(), req.getLink(), req.getStartTime(), req.getEndTime(), req.getStatus()); + return existingSchedule; + } + + private static void checkAuthor(String author, User user) { + if (!user.getIntraId().equals(author)) { + throw new ForbiddenException(ErrorCode.CALENDAR_AUTHOR_NOT_MATCH); + } + } + + public void validateTimeRange(LocalDateTime startTime, LocalDateTime endTime) { + if (endTime.isBefore(startTime)) { + throw new InvalidParameterException(ErrorCode.CALENDAR_BEFORE_DATE); + } + } } diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java index 2b895096b..fdc292262 100644 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/PublicScheduleControllerTest.java @@ -24,9 +24,11 @@ import gg.calendar.api.user.schedule.publicschedule.PublicScheduleMockData; import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleCreateReqDto; +import gg.calendar.api.user.schedule.publicschedule.controller.request.PublicScheduleUpdateReqDto; import gg.data.calendar.PublicSchedule; import gg.data.calendar.type.DetailClassification; import gg.data.calendar.type.EventTag; +import gg.data.calendar.type.ScheduleStatus; import gg.data.user.User; import gg.repo.calendar.PublicScheduleRepository; import gg.repo.user.UserRepository; @@ -69,12 +71,12 @@ void setUp() { } @Nested - @DisplayName("공개일정생성") + @DisplayName("공개일정:생성") class CreatePublicSchedule { @Test - @DisplayName("공개일정 생성 성공") + @DisplayName("공개일정생성성공") void createPublicScheduleSuccess() throws Exception { - // given : reqDto를 생성 + // given PublicScheduleCreateReqDto publicScheduleDto = PublicScheduleCreateReqDto.builder() .classification(DetailClassification.EVENT) .author(user.getIntraId()) @@ -85,21 +87,21 @@ void createPublicScheduleSuccess() throws Exception { .endTime(LocalDateTime.now().plusDays(1)) .build(); - // when : reqDto로 요청 + // when log.info("After mock data creation: {}", publicScheduleRepository.findByAuthor(user.getIntraId()).size()); mockMvc.perform(post("/calendar/public").header("Authorization", "Bearer " + accssToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(publicScheduleDto))).andExpect(status().isCreated()); - // then : 생성된 일정이 반환 + // then List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); assertThat(schedules).hasSize(1); assertThat(schedules.get(0).getTitle()).isEqualTo(publicScheduleDto.getTitle()); } @Test - @DisplayName("공개일정-작성자가 다를 때") - void createPublicScheduleFail() throws Exception { - // given : reqDto를 생성 + @DisplayName("공개일정생성실패-작성자가 다를 때") + void createPublicScheduleFailNotMatchAuthor() throws Exception { + // given PublicScheduleCreateReqDto publicScheduleDto = PublicScheduleCreateReqDto.builder() .classification(DetailClassification.EVENT) .author("another") @@ -109,24 +111,21 @@ void createPublicScheduleFail() throws Exception { .startTime(LocalDateTime.now()) .endTime(LocalDateTime.now().plusDays(1)) .build(); - // when : reqDto로 요청 + // when mockMvc.perform(post("/calendar/public").header("Authorization", "Bearer " + accssToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(publicScheduleDto))) - .andExpect(status().isBadRequest()) - .andExpect(result -> { - status().isBadRequest(); // 처음에 errorcode로 잡았는데, status로 잡음 - }) + .andExpect(status().isForbidden()) .andDo(print()); - // then : 예외가 발생 + // then List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); assertThat(schedules).isEmpty(); } @Test - @DisplayName("공개일정- 기간이 잘못되었을 때/ 종료닐짜가 시작날짜보다 빠를때") - void createPublicScheduleFail2() throws Exception { - // given : reqDto를 생성 + @DisplayName("공개일정생성실패- 기간이 잘못되었을 때(종료닐짜가 시작날짜보다 빠를때)") + void createPublicScheduleFailFalutPeriod() throws Exception { + // given PublicScheduleCreateReqDto publicScheduleDto = PublicScheduleCreateReqDto.builder() .classification(DetailClassification.EVENT) .eventTag(EventTag.ETC) @@ -137,18 +136,287 @@ void createPublicScheduleFail2() throws Exception { .startTime(LocalDateTime.now()) .endTime(LocalDateTime.now().minusDays(1)) .build(); - // when : reqDto로 요청 + // when mockMvc.perform(post("/calendar/public").header("Authorization", "Bearer " + accssToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(publicScheduleDto))) .andExpect(status().isBadRequest()) .andExpect(result -> { - status().isBadRequest(); // 처음에 errorcode로 잡았는데, status로 잡음 + status().isBadRequest(); }) .andDo(print()); - // then : 예외가 발생 + // then List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); assertThat(schedules).isEmpty(); } } + + @Nested + @DisplayName("공개일정:업데이트") + class UpdatePublicSchedule { + + @Test + @DisplayName("공개일정업데이트성공시") + void updatePublicScheduleSuccess() throws Exception { + // given + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + publicScheduleRepository.save(publicSchedule); + + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Updated Title") + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .status(ScheduleStatus.ACTIVATE) + .build(); + + // when + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))).andExpect(status().isOk()); + + // then + List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); + assertThat(schedules).hasSize(1); + assertThat(schedules.get(0).getTitle()).isEqualTo("Updated Title"); + assertThat(schedules.get(0).getContent()).isEqualTo("Updated Content"); + } + + @Test + @DisplayName("공개일정업데이트실패-작성자가 다를 때") + void updatePublicScheduleFailNotMatchAuthor() throws Exception { + // given + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + publicScheduleRepository.save(publicSchedule); + + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author("another") + .title("Updated Title") + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .build(); + + // when + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isForbidden()) + .andDo(print()); + + // then + List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); + assertThat(schedules).hasSize(1); + assertThat(schedules.get(0).getTitle()).isEqualTo("Original Title"); + assertThat(schedules.get(0).getContent()).isEqualTo("Original Content"); + } + + @Test + @DisplayName("공개일정업데이트실패-기존일정작성자가다를때") + void updatePublicScheduleFailExistingAuthorNotMatch() throws Exception { + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity("another", + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author("another") + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + + publicScheduleRepository.save(publicSchedule); + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Updated Title") + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .build(); + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isForbidden()) + .andDo(print()); + + List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); + assertThat(schedules).hasSize(0); + } + + @Test + @DisplayName("공개일정업데이트실패-기간이 잘못되었을 때(종료날짜가 시작날짜보다 빠를 때)") + void updatePublicScheduleFailFaultPeriod() throws Exception { + // given + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + publicScheduleRepository.save(publicSchedule); + + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Updated Title") + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().minusDays(1)) + .build(); + + // when + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isBadRequest()) + .andExpect(result -> { + status().isBadRequest(); + }) + .andDo(print()); + + // then + List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); + assertThat(schedules).hasSize(1); + assertThat(schedules.get(0).getTitle()).isEqualTo("Original Title"); + assertThat(schedules.get(0).getContent()).isEqualTo("Original Content"); + } + + @Test + @DisplayName("공개일정업데이트실패-없는 일정일 때") + void updatePublicScheduleFailNotExist() throws Exception { + // given + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Updated Title") + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .build(); + + // when + mockMvc.perform(put("/calendar/public/9999").header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))).andExpect(status().isNotFound()).andDo(print()); + + // then + List schedules = publicScheduleRepository.findByAuthor(user.getIntraId()); + assertThat(schedules).hasSize(0); + } + + @Test + @DisplayName("공개일정업데이트실패-제목이 50글자 초과일 때") + void updatePublicScheduleFailTitleTooLong() throws Exception { + // given + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + publicScheduleRepository.save(publicSchedule); + + String longTitle = "publicScheduleTest".repeat(20); + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title(longTitle) + .content("Updated Content") + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .build(); + + // when + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isBadRequest()) + .andDo(print()); + + //then + PublicSchedule updatedSchedule = publicScheduleRepository.findById(publicSchedule.getId()).get(); + assertThat(updatedSchedule.getTitle()).isEqualTo("Original Title"); + } + + @Test + @DisplayName("공개일정업데이트실패-내용이 2000글자 초과일 때") + void updatePublicScheduleFailContentTooLong() throws Exception { + // given + PublicSchedule publicSchedule = PublicScheduleCreateReqDto.toEntity(user.getIntraId(), + PublicScheduleCreateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Original Title") + .content("Original Content") + .link("http://original.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .build()); + publicScheduleRepository.save(publicSchedule); + + String longContent = "publicScheduleTest".repeat(200); + PublicScheduleUpdateReqDto updateDto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.EVENT) + .author(user.getIntraId()) + .title("Updated Title") + .content(longContent) + .link("http://updated.com") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(2)) + .build(); + + // when + mockMvc.perform( + put("/calendar/public/" + publicSchedule.getId()).header("Authorization", "Bearer " + accssToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(updateDto))) + .andExpect(status().isBadRequest()) + .andDo(print()); + + //then + PublicSchedule updatedSchedule = publicScheduleRepository.findById(publicSchedule.getId()).get(); + assertThat(updatedSchedule.getContent()).isEqualTo("Original Content"); + } + } } diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDtoTest.java index 6937a8ce5..f4fa96d2c 100644 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDtoTest.java +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleCreateReqDtoTest.java @@ -13,8 +13,6 @@ import gg.data.calendar.type.EventTag; import gg.utils.annotation.UnitTest; - - /*이 테스트는 reqDto의 of()메서드가 정상적으로 엔티티로 변환되는 지 검증하는 테스트*/ @UnitTest @@ -22,7 +20,6 @@ public class PublicScheduleCreateReqDtoTest { @Test @DisplayName("PublicScheduleCreateReqDto 생성 성공") void createPublicScheduleSuccess() { - //given : userDto와 reqDto를 생성 UserDto user = UserDto.builder().intraId("intraId").build(); PublicScheduleCreateReqDto dto = PublicScheduleCreateReqDto.builder() @@ -32,28 +29,21 @@ void createPublicScheduleSuccess() { .author(user.getIntraId()) .content("Test Content") .link("http://test.com") - // .sharedCount(0) => sharedCount는 0으로 고정되기에 dto에서 제외 .startTime(LocalDateTime.now().plusDays(1)) .endTime(LocalDateTime.now().plusDays(2)) .build(); - - // when : dto를 엔티티로 변환 PublicSchedule schedule = dto.toEntity(user.getIntraId(), dto); - // then : dto와 엔티티가 같은지 검증 - assertAll( - () -> assertNotNull(schedule), + assertAll(() -> assertNotNull(schedule), () -> assertEquals(dto.getClassification(), schedule.getClassification()), () -> assertEquals(dto.getEventTag(), schedule.getEventTag()), () -> assertEquals(dto.getTitle(), schedule.getTitle()), () -> assertEquals(user.getIntraId(), schedule.getAuthor()), () -> assertEquals(dto.getContent(), schedule.getContent()), () -> assertEquals(dto.getLink(), schedule.getLink()), - // () -> assertEquals(dto.getSharedCount(), schedule.getSharedCount()), () -> assertEquals(dto.getStartTime(), schedule.getStartTime()), - () -> assertEquals(dto.getEndTime(), schedule.getEndTime()) - ); + () -> assertEquals(dto.getEndTime(), schedule.getEndTime())); } } diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDtoTest.java deleted file mode 100644 index 4cd6b7542..000000000 --- a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleReqDtoTest.java +++ /dev/null @@ -1,6 +0,0 @@ -package gg.calendar.api.user.schedule.publicschedule.controller.request; - -import org.junit.jupiter.api.Test; - -public class PublicScheduleReqDtoTest { -} diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDtoTest.java new file mode 100644 index 000000000..de817702b --- /dev/null +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/request/PublicScheduleUpdateReqDtoTest.java @@ -0,0 +1,41 @@ +package gg.calendar.api.user.schedule.publicschedule.controller.request; + +import static org.junit.jupiter.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.EventTag; +import gg.utils.annotation.UnitTest; + +@UnitTest +public class PublicScheduleUpdateReqDtoTest { + + @Test + @DisplayName("PublicScheduleUpdateReqDto 생성 성공") + void createPublicScheduleSuccess() { + LocalDateTime startTime = LocalDateTime.now().plusDays(1); + LocalDateTime endTime = LocalDateTime.now().plusDays(2); + + PublicScheduleUpdateReqDto dto = PublicScheduleUpdateReqDto.builder() + .classification(DetailClassification.JOB_NOTICE) + .eventTag(EventTag.INSTRUCTION) + .title("Test Schedule") + .author("intraId") + .content("Test Content") + .link("http://test.com") + .startTime(startTime) + .endTime(endTime) + .build(); + + assertAll(() -> assertEquals(DetailClassification.JOB_NOTICE, dto.getClassification()), + () -> assertEquals(EventTag.INSTRUCTION, dto.getEventTag()), + () -> assertEquals("Test Schedule", dto.getTitle()), () -> assertEquals("intraId", dto.getAuthor()), + () -> assertEquals("Test Content", dto.getContent()), () -> assertEquals("http://test.com", dto.getLink()), + () -> assertEquals(startTime, dto.getStartTime()), () -> assertEquals(endTime, dto.getEndTime())); + + } +} diff --git a/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDtoTest.java b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDtoTest.java new file mode 100644 index 000000000..06dbc0ae6 --- /dev/null +++ b/gg-calendar-api/src/test/java/gg/calendar/api/user/schedule/publicschedule/controller/response/PublicScheduleUpdateResDtoTest.java @@ -0,0 +1,56 @@ +package gg.calendar.api.user.schedule.publicschedule.controller.response; + +import static org.junit.jupiter.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import gg.data.calendar.PublicSchedule; +import gg.data.calendar.type.DetailClassification; +import gg.data.calendar.type.EventTag; +import gg.data.calendar.type.ScheduleStatus; +import gg.utils.annotation.UnitTest; + +@UnitTest +public class PublicScheduleUpdateResDtoTest { + + @Test + @DisplayName("PublicSchedule Entity를 ResponseDto로 변환 성공") + void toDto_Success() { + // given + LocalDateTime startTime = LocalDateTime.now().plusDays(1); + LocalDateTime endTime = LocalDateTime.now().plusDays(2); + + PublicSchedule schedule = PublicSchedule.builder() + .classification(DetailClassification.JOB_NOTICE) + .eventTag(EventTag.INSTRUCTION) + .author("testUser") + .title("Test Title") + .content("Test Content") + .link("http://test.com") + .startTime(startTime) + .endTime(endTime) + .status(ScheduleStatus.ACTIVATE) + .build(); + ReflectionTestUtils.setField(schedule, "id", 1L); + // when + PublicScheduleUpdateResDto responseDto = PublicScheduleUpdateResDto.toDto(schedule); + + // then + assertAll( + () -> assertEquals(1L, responseDto.getId()), + () -> assertEquals(DetailClassification.JOB_NOTICE, responseDto.getClassification()), + () -> assertEquals(EventTag.INSTRUCTION, responseDto.getEventTag()), + () -> assertEquals("testUser", responseDto.getAuthor()), + () -> assertEquals("Test Title", responseDto.getTitle()), + () -> assertEquals("Test Content", responseDto.getContent()), + () -> assertEquals("http://test.com", responseDto.getLink()), + () -> assertEquals(startTime.toString(), responseDto.getStartTime()), + () -> assertEquals(endTime.toString(), responseDto.getEndTime()), + () -> assertEquals("ACTIVATE", responseDto.getStatus()) + ); + } +} diff --git a/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java b/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java index 68e40c944..9f3481c1c 100644 --- a/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java +++ b/gg-data/src/main/java/gg/data/calendar/PublicSchedule.java @@ -85,4 +85,21 @@ private PublicSchedule(DetailClassification classification, EventTag eventTag, J this.startTime = startTime; this.endTime = endTime; } + + public void update(DetailClassification classification, EventTag eventTag, JobTag jobTag, + TechTag techTag, + String title, String content, String link, LocalDateTime startTime, LocalDateTime endTime, + ScheduleStatus status) { + this.classification = classification; + this.eventTag = eventTag; + this.jobTag = jobTag; + this.techTag = techTag; + this.title = title; + this.content = content; + this.link = link; + this.startTime = startTime; + this.endTime = endTime; + this.status = status; + } } + diff --git a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java index 8fa62caca..017c51a21 100644 --- a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java +++ b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java @@ -240,7 +240,7 @@ public enum ErrorCode { CALENDAR_BEFORE_DATE(400, "CA201", "종료 시간이 시작 시간보다 빠를 수 없습니다."), CALENDAR_AFTER_DATE(400, "CA202", "시작 시간이 종료 시간보다 늦을 수 없습니다."), CALENDAR_EQUAL_DATE(400, "CA203", "시작 시간과 종료 시간이 같을 수 없습니다."), - CALENDAR_AUTHOR_NOT_MATCH(400, "CA205", "전제하지 않는 사용자입니다."), + CALENDAR_AUTHOR_NOT_MATCH(403, "CA205", "잘못된 사용자입니다."), PRIVATE_SCHEDULE_NOT_FOUND(404, "CA101", "개인 일정을 찾을 수 없습니다."), PUBLIC_SCHEDULE_NOT_FOUND(404, "CA102", "공유 일정을 찾을 수 없습니다."), SCHEDULE_GROUP_NOT_FOUND(404, "CA103", "스캐줄 그룹을 찾을 수 없습니다.");