From 5e47c398d0d2deb4bc18bce57c293f73cad33009 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:18:11 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20WithDankook=EC=97=90=20=EB=B9=84?= =?UTF-8?q?=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../council/domain/with_dankook/model/entity/WithDankook.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/dku/council/domain/with_dankook/model/entity/WithDankook.java b/src/main/java/com/dku/council/domain/with_dankook/model/entity/WithDankook.java index 554215df..6984778a 100644 --- a/src/main/java/com/dku/council/domain/with_dankook/model/entity/WithDankook.java +++ b/src/main/java/com/dku/council/domain/with_dankook/model/entity/WithDankook.java @@ -53,6 +53,10 @@ public void markAsDeleted(boolean byAdmin) { this.withDankookStatus = byAdmin ? WithDankookStatus.DELETED_BY_ADMIN : WithDankookStatus.DELETED; } + public void markAsFull() { + this.withDankookStatus = WithDankookStatus.FULL; + } + public boolean isClosed() { return withDankookStatus == WithDankookStatus.CLOSED; } From 87d14757165bed2ebb93aafb0b53f8ccd70a52e9 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:18:43 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20Repository=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20ID=EB=A1=9C=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20JPQL=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BearEatsRepository.java | 14 ++++++++++++++ .../with_dankook/repository/StudyRepository.java | 10 ++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/repository/BearEatsRepository.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/repository/BearEatsRepository.java b/src/main/java/com/dku/council/domain/with_dankook/repository/BearEatsRepository.java new file mode 100644 index 00000000..c771069c --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/repository/BearEatsRepository.java @@ -0,0 +1,14 @@ +package com.dku.council.domain.with_dankook.repository; + +import com.dku.council.domain.with_dankook.model.entity.type.BearEats; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface BearEatsRepository extends WithDankookRepository{ + + @Query("select b from BearEats b where b.masterUser.id = :userId and " + + "(b.withDankookStatus='ACTIVE' or b.withDankookStatus='CLOSED') ") + Page findAllBearEatsByUserId(@Param("userId") Long userId, Pageable pageable); +} diff --git a/src/main/java/com/dku/council/domain/with_dankook/repository/StudyRepository.java b/src/main/java/com/dku/council/domain/with_dankook/repository/StudyRepository.java index b4b57200..4463564d 100644 --- a/src/main/java/com/dku/council/domain/with_dankook/repository/StudyRepository.java +++ b/src/main/java/com/dku/council/domain/with_dankook/repository/StudyRepository.java @@ -1,14 +1,16 @@ package com.dku.council.domain.with_dankook.repository; import com.dku.council.domain.with_dankook.model.entity.type.Study; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; public interface StudyRepository extends WithDankookRepository{ - @Query("select s from Study s " + - "join fetch s.tag " + - "where s.tag.name = :name ") - List findAllByStudyTagName(@Param("name") String name); + + @Query("select s from Study s where s.masterUser.id = :userId and " + + "(s.withDankookStatus='ACTIVE' or s.withDankookStatus='CLOSED') ") + Page findAllStudyByUserId(@Param("userId") Long userId, Pageable pageable); } From 102f9587d82dfd852f8eb7c97f9b70eaa1c2cba9 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:19:15 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=EC=B5=9C=EA=B7=BC=EC=97=90=20?= =?UTF-8?q?=EC=83=9D=EA=B8=B4=205=EA=B0=9C=EC=9D=98=20=EA=B8=80=EC=9D=84?= =?UTF-8?q?=20=EC=B0=BE=EB=8A=94=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/with_dankook/repository/WithDankookRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/dku/council/domain/with_dankook/repository/WithDankookRepository.java b/src/main/java/com/dku/council/domain/with_dankook/repository/WithDankookRepository.java index f802460c..6b851a62 100644 --- a/src/main/java/com/dku/council/domain/with_dankook/repository/WithDankookRepository.java +++ b/src/main/java/com/dku/council/domain/with_dankook/repository/WithDankookRepository.java @@ -29,4 +29,8 @@ public interface WithDankookRepository extends JpaReposit @Query("select w from WithDankook w " + "where w.masterUser.id=:userId and (w.withDankookStatus='ACTIVE' or w.withDankookStatus='CLOSED')") Page findAllByUserId(@Param("userId") Long userId, Pageable pageable); + + @Query("select w from WithDankook w " + + "where w.withDankookStatus='ACTIVE' order by w.createdAt desc") + Page findTop5OrderByCreatedAtDesc(Pageable pageable); } From c04ce8c9a995686cfc62c25f837bfa5ac3cf92dc Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:19:57 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20WithDankook=EC=97=90=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=20=EC=B0=B8=EC=97=AC=EC=9E=90=EA=B0=80=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EA=B3=B5=ED=86=B5=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../with_dankook/service/StudyService.java | 17 +++--------- .../service/WithDankookService.java | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/dku/council/domain/with_dankook/service/StudyService.java b/src/main/java/com/dku/council/domain/with_dankook/service/StudyService.java index 2cde7000..186e55d1 100644 --- a/src/main/java/com/dku/council/domain/with_dankook/service/StudyService.java +++ b/src/main/java/com/dku/council/domain/with_dankook/service/StudyService.java @@ -123,7 +123,7 @@ public Page listByStudyTag(String studyTagName, Pageable pag @Transactional(readOnly = true) public Page listMyPosts(Long userId, Pageable pageable) { - return studyRepository.findAllByUserId(userId, pageable) + return studyRepository.findAllStudyByUserId(userId, pageable) .map(study -> new SummarizedStudyDto(withDankookService.makeListDto(50, study), study, withDankookUserService.recruitedCount(withDankookService.makeListDto(50, study).getId()) @@ -135,8 +135,7 @@ public ResponseSingleStudyDto findOne(Long studyId, Long userId, UserRole role) Study study = findStudy(studyRepository, studyId, role); return new ResponseSingleStudyDto(withDankookService.makeSingleDto(userId, study), study, - withDankookUserService.recruitedCount(withDankookService.makeSingleDto(userId, study).getId()) - ); + withDankookUserService.recruitedCount(withDankookService.makeSingleDto(userId, study).getId())); } private Study findStudy(StudyRepository studyRepository, Long studyId, UserRole role) { @@ -154,23 +153,13 @@ public void enter(Long id, Long userId, UserRole userRole) { Study study = findStudy(studyRepository, id, userRole); User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - boolean isValid = isInvalidParticipant(study, user); if (study.getMinStudentId() < Integer.parseInt(String.valueOf(user.getYearOfAdmission()).substring(2))) { throw new InvalidMinStudentIdException(); - } else if(isValid) { - throw new InvalidStatusException(); - } else{ + } else { withDankookService.enter(studyRepository, id, userId, userRole); } } - private boolean isInvalidParticipant(Study study, User user) { - return study.getUsers().stream().anyMatch( - withDankookUser -> withDankookUser.getParticipant().getId().equals(user.getId()) && - withDankookUser.getParticipantStatus().equals(ParticipantStatus.INVALID) - ); - } - @Transactional public void delete(Long studyId, Long userId, boolean isAdmin) { withDankookService.delete(studyRepository, studyId, userId, isAdmin); diff --git a/src/main/java/com/dku/council/domain/with_dankook/service/WithDankookService.java b/src/main/java/com/dku/council/domain/with_dankook/service/WithDankookService.java index fae9b0ce..115c2a2b 100644 --- a/src/main/java/com/dku/council/domain/with_dankook/service/WithDankookService.java +++ b/src/main/java/com/dku/council/domain/with_dankook/service/WithDankookService.java @@ -7,8 +7,11 @@ import com.dku.council.domain.user.repository.UserRepository; import com.dku.council.domain.with_dankook.exception.AlreadyEnteredException; import com.dku.council.domain.with_dankook.exception.AlreadyFullRecruitedException; +import com.dku.council.domain.with_dankook.exception.InvalidStatusException; import com.dku.council.domain.with_dankook.exception.WithDankookNotFoundException; +import com.dku.council.domain.with_dankook.model.ParticipantStatus; import com.dku.council.domain.with_dankook.model.dto.list.SummarizedWithDankookDto; +import com.dku.council.domain.with_dankook.model.dto.request.RequestCreateWithDankookDto; import com.dku.council.domain.with_dankook.model.dto.response.ResponseSingleWithDankookDto; import com.dku.council.domain.with_dankook.model.entity.WithDankook; import com.dku.council.domain.with_dankook.model.entity.WithDankookUser; @@ -132,6 +135,16 @@ private E findWithDankook(WithDankookRepository repository, Long withDankookI return withDankook.orElseThrow(WithDankookNotFoundException::new); } + @Transactional + public Long create(WithDankookRepository repository, Long userId, RequestCreateWithDankookDto dto) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + E withDankook = dto.toEntity(user); + + E result = repository.save(withDankook); + return result.getId(); + } + /** * With-Dankook 게시판 글에 참여를 신청합니다. * @@ -144,10 +157,13 @@ public void enter(WithDankookRepository repository, Long withDankookId, Long User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + boolean isInvalid = isInvalidParticipant(withDankook, user); if (withDankookUserService.isParticipant(withDankookId, user.getId())) { throw new AlreadyEnteredException(); } else if (withDankookUserService.recruitedCount(withDankook.getId()) >= 4){ throw new AlreadyFullRecruitedException(); + } else if (isInvalid) { + throw new InvalidStatusException(); } else { WithDankookUser withDankookUser = WithDankookUser.builder() .user(user) @@ -155,6 +171,10 @@ public void enter(WithDankookRepository repository, Long withDankookId, Long .build(); withDankookUserRepository.save(withDankookUser); } + + if (withDankookUserService.recruitedCount(withDankook.getId()) == 4) { + withDankook.markAsFull(); + } } /** * With-Dankook 게시판 글 삭제. 실제 DB에서 삭제는 하지 않는다. @@ -176,6 +196,13 @@ public void delete(WithDankookRepository repository, Long withDankookId, Long } } + public boolean isInvalidParticipant(E withDankook, User user) { + return withDankook.getUsers().stream().anyMatch( + withDankookUser -> withDankookUser.getParticipant().getId().equals(user.getId()) && + withDankookUser.getParticipantStatus().equals(ParticipantStatus.INVALID) + ); + } + @FunctionalInterface public interface PostResultMapper { T map(D dto, E withDankook); From b02b6f9eec8e1193a6e13bcd03356365614642d4 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:20:15 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20BearEats=20=EB=AA=A9=EB=A1=9D=20dto?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/dto/list/SummarizedBearEatsDto.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/model/dto/list/SummarizedBearEatsDto.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/model/dto/list/SummarizedBearEatsDto.java b/src/main/java/com/dku/council/domain/with_dankook/model/dto/list/SummarizedBearEatsDto.java new file mode 100644 index 00000000..f6be231f --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/model/dto/list/SummarizedBearEatsDto.java @@ -0,0 +1,38 @@ +package com.dku.council.domain.with_dankook.model.dto.list; + +import com.dku.council.domain.with_dankook.model.entity.type.BearEats; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +public class SummarizedBearEatsDto extends SummarizedWithDankookDto { + + @Schema(description = "식당 이름", example = "피자헛") + private final String restaurant; + + @Schema(description = "배달 주문 장소", example = "피자헛") + private final String deliveryPlace; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @Schema(description = "배달 시간", example = "2021-01-01T12:00") + private final LocalDateTime deliveryTime; + + @Schema(description = "내용", example = "피자헛에서 피자를 시켜먹을 사람을 구합니다.") + private final String content; + + @Schema(description = "모집된 인원", example = "1") + private final int recruitedCount; + + public SummarizedBearEatsDto(SummarizedWithDankookDto dto, BearEats bearEats, int recruitedCount) { + super(dto); + this.restaurant = bearEats.getRestaurant(); + this.deliveryPlace = bearEats.getDeliveryPlace(); + this.deliveryTime = bearEats.getDeliveryTime(); + this.content = bearEats.getContent(); + this.recruitedCount = recruitedCount; + } + +} From 3552496c900fdb7f051fa498a296dc484355fde0 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:20:39 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20BearEats=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1=20dto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/RequestCreateBearEatsDto.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/model/dto/request/RequestCreateBearEatsDto.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/model/dto/request/RequestCreateBearEatsDto.java b/src/main/java/com/dku/council/domain/with_dankook/model/dto/request/RequestCreateBearEatsDto.java new file mode 100644 index 00000000..85190eaa --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/model/dto/request/RequestCreateBearEatsDto.java @@ -0,0 +1,53 @@ +package com.dku.council.domain.with_dankook.model.dto.request; + +import com.dku.council.domain.user.model.entity.User; +import com.dku.council.domain.with_dankook.model.entity.type.BearEats; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Getter +public class RequestCreateBearEatsDto extends RequestCreateWithDankookDto{ + + @NotNull + @Schema(description = "음식점", example = "피자헛") + private String restaurant; + + @NotNull + @Schema(description = "배달 주문 장소", example = "피자헛") + private String deliveryPlace; + + @NotNull + @JsonFormat(pattern = "yyyy-MM-dd HH:MM") + @Schema(description = "배달 시간", example = "2023-12-25 17:30") + private LocalDateTime deliveryTime; + + @NotBlank + @Schema(description = "본문", example = "내용") + private String content; + + public RequestCreateBearEatsDto(@NotNull String restaurant, + @NotNull String deliveryPlace, + @NotNull LocalDateTime deliveryTime, + @NotBlank String content) { + this.restaurant = restaurant; + this.deliveryPlace = deliveryPlace; + this.deliveryTime = deliveryTime; + this.content = content; + } + + @Override + public BearEats toEntity(User user) { + return BearEats.builder() + .user(user) + .restaurant(restaurant) + .deliveryPlace(deliveryPlace) + .deliveryTime(deliveryTime) + .content(content) + .build(); + } +} From 31812d6cb766383f022d32eb3463c880b2d91fb3 Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:20:56 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20BearEats=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20dto=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/ResponseSingleBearEatsDto.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/model/dto/response/ResponseSingleBearEatsDto.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/model/dto/response/ResponseSingleBearEatsDto.java b/src/main/java/com/dku/council/domain/with_dankook/model/dto/response/ResponseSingleBearEatsDto.java new file mode 100644 index 00000000..b33382a6 --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/model/dto/response/ResponseSingleBearEatsDto.java @@ -0,0 +1,45 @@ +package com.dku.council.domain.with_dankook.model.dto.response; + +import com.dku.council.domain.with_dankook.model.dto.RecruitedUsersDto; +import com.dku.council.domain.with_dankook.model.entity.type.BearEats; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public class ResponseSingleBearEatsDto extends ResponseSingleWithDankookDto { + + @Schema(description = "식당 이름", example = "피자헛") + private final String restaurant; + + @Schema(description = "배달 주문 장소", example = "피자헛") + private final String deliveryPlace; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + @Schema(description = "배달 시간", example = "2021-01-01 12:00") + private final String deliveryTime; + + @Schema(description = "내용", example = "피자헛에서 피자를 시켜먹을 사람을 구합니다.") + private final String content; + + @Schema(description = "모집된 인원", example = "1") + private final int recruitedCount; + + @Schema(description = "모집된 사용자들") + private final List recruitedUsers; + + public ResponseSingleBearEatsDto(ResponseSingleWithDankookDto dto, BearEats bearEats, int recruitedCount) { + super(dto); + this.restaurant = bearEats.getRestaurant(); + this.deliveryPlace = bearEats.getDeliveryPlace(); + this.deliveryTime = bearEats.getDeliveryTime().toString(); + this.content = bearEats.getContent(); + this.recruitedCount = recruitedCount; + this.recruitedUsers = bearEats.getUsers().stream() + .map(RecruitedUsersDto::new) + .collect(Collectors.toList()); + } +} From f831fc348598eee212ea23c3b101d4a8060e66bb Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:21:13 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20BearEats=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EB=B0=8F=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../with_dankook/service/BearEatsService.java | 108 ++++++++++++++++++ src/main/resources/errors.properties | 1 + src/main/resources/errors_en_US.properties | 1 + 3 files changed, 110 insertions(+) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/service/BearEatsService.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/service/BearEatsService.java b/src/main/java/com/dku/council/domain/with_dankook/service/BearEatsService.java new file mode 100644 index 00000000..0bb863d9 --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/service/BearEatsService.java @@ -0,0 +1,108 @@ +package com.dku.council.domain.with_dankook.service; + +import com.dku.council.domain.post.exception.PostCooltimeException; +import com.dku.council.domain.post.repository.PostTimeMemoryRepository; +import com.dku.council.domain.user.model.entity.User; +import com.dku.council.domain.user.repository.UserRepository; +import com.dku.council.domain.with_dankook.exception.WithDankookNotFoundException; +import com.dku.council.domain.with_dankook.model.dto.list.SummarizedBearEatsDto; +import com.dku.council.domain.with_dankook.model.dto.request.RequestCreateBearEatsDto; +import com.dku.council.domain.with_dankook.model.dto.response.ResponseSingleBearEatsDto; +import com.dku.council.domain.with_dankook.model.entity.WithDankookUser; +import com.dku.council.domain.with_dankook.model.entity.type.BearEats; +import com.dku.council.domain.with_dankook.repository.BearEatsRepository; +import com.dku.council.domain.with_dankook.repository.WithDankookUserRepository; +import com.dku.council.global.auth.role.UserRole; +import com.dku.council.global.error.exception.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +@Slf4j +@Transactional(readOnly = true) +public class BearEatsService { + public static final String BEAR_EATS_KEY = "bearEats"; + + private final WithDankookService withDankookService; + private final WithDankookUserService withDankookuserSerivce; + + private final BearEatsRepository bearEatsRepository; + private final WithDankookUserRepository withDankookUserRepository; + private final UserRepository userRepository; + private final PostTimeMemoryRepository postTimeMemoryRepository; + + private final Clock clock; + + @Value("${app.with-dankook.bear-eats.write-cooltime}") + private final Duration writeCooltime; + + @Transactional + public Long create(Long userId, RequestCreateBearEatsDto dto) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + Instant now = Instant.now(clock); + if (postTimeMemoryRepository.isAlreadyContains(BEAR_EATS_KEY, userId, now)) { + throw new PostCooltimeException("bear-eats"); + } + + Long result = withDankookService.create(bearEatsRepository, userId, dto); + + WithDankookUser withDankookuser = WithDankookUser.builder() + .user(user) + .withDankook(bearEatsRepository.findById(result).orElseThrow(WithDankookNotFoundException::new)) + .build(); + withDankookUserRepository.save(withDankookuser); + + postTimeMemoryRepository.put(BEAR_EATS_KEY, userId, writeCooltime, now); + return result; + } + + public Page list(Pageable pageable, int bodySize) { + Page result = bearEatsRepository.findAll(pageable); + return result.map((bearEats) -> new SummarizedBearEatsDto(withDankookService.makeListDto(bodySize, bearEats), bearEats, + withDankookuserSerivce.recruitedCount(withDankookService.makeListDto(bodySize, bearEats).getId()))); + } + + public Page listMyPosts(Long userId, Pageable pageable) { + return bearEatsRepository.findAllBearEatsByUserId(userId, pageable) + .map(bearEats -> new SummarizedBearEatsDto(withDankookService.makeListDto(50, bearEats), bearEats, + withDankookuserSerivce.recruitedCount(withDankookService.makeListDto(50, bearEats).getId()))); + } + + public ResponseSingleBearEatsDto findOne(Long id, Long userId, UserRole role) { + BearEats bearEats = findBearEats(bearEatsRepository, id, role); + return new ResponseSingleBearEatsDto(withDankookService.makeSingleDto(userId, bearEats), bearEats, + withDankookuserSerivce.recruitedCount(withDankookService.makeSingleDto(userId, bearEats).getId())); + } + + private BearEats findBearEats(BearEatsRepository bearEatsRepository, Long id, UserRole role) { + Optional bearEats; + if (role.isAdmin()) { + bearEats = bearEatsRepository.findWithClosedById(id); + } else { + bearEats = bearEatsRepository.findById(id); + } + return bearEats.orElseThrow(WithDankookNotFoundException::new); + } + + @Transactional + public void enter(Long id, Long userId, UserRole userRole) { + withDankookService.enter(bearEatsRepository, id, userId, userRole); + } + + @Transactional + public void delete(Long id, Long userId, boolean isAdmin) { + withDankookService.delete(bearEatsRepository, id, userId, isAdmin); + } + +} diff --git a/src/main/resources/errors.properties b/src/main/resources/errors.properties index 88fb1711..50bbff58 100644 --- a/src/main/resources/errors.properties +++ b/src/main/resources/errors.properties @@ -86,6 +86,7 @@ cooltime.petition=\uCCAD\uC6D0\uC744 \uC62C\uB9B0 \uB4A4\uB85C 1\uC77C\uC774 \uC cooltime.general-forum=\uAC8C\uC2DC\uAE00\uC744 \uC62C\uB9B0 \uB4A4\uB85C 3\uBD84\uC774 \uC9C0\uB098\uC57C \uB2E4\uC2DC \uAC8C\uC2DC\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. cooltime.trade=\uB2E8\uAD6D \uAC70\uB798 \uAC8C\uC2DC\uAE00\uC744 \uC62C\uB9B0 \uB4A4\uB85C 3\uBD84\uC774 \uC9C0\uB098\uC57C \uB2E4\uC2DC \uAC8C\uC2DC\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. cooltime.study=\uB2E8\uD130\uB514 \uAC8C\uC2DC\uAE00\uC744 \uC62C\uB9B0 \uB4A4\uB85C 3\uBD84\uC774 \uC9C0\uB098\uC57C \uB2E4\uC2DC \uAC8C\uC2DC\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. +cooltime.bear-eats=Bear Eats \uAC8C\uC2DC\uAE00\uC744 \uC62C\uB9B0 \uB4A4\uB85C 3\uBD84\uC774 \uC9C0\uB098\uC57C \uB2E4\uC2DC \uAC8C\uC2DC\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. integrity.tag=\uC774 \uD0DC\uADF8\uB97C \uCC38\uC870\uD558\uB294 \uB2E4\uB978 \uAC8C\uC2DC\uAE00\uB4E4\uC774 \uC788\uC2B5\uB2C8\uB2E4. diff --git a/src/main/resources/errors_en_US.properties b/src/main/resources/errors_en_US.properties index c3cfb505..edc60ada 100644 --- a/src/main/resources/errors_en_US.properties +++ b/src/main/resources/errors_en_US.properties @@ -88,6 +88,7 @@ cooltime.petition=You can't post again until one day after posting the petition. cooltime.general-forum=You can't post again until 3 minutes after posting. cooltime.trade=You can't post again until 3 minutes after posting. cooltime.study=You can't post again until 3 minutes after posting. +cooltime.bear-eats=You can't post again until 3 minutes after posting. integrity.tag=There are other posts referencing this tag. From 036133cd0ce7c1acdf03ed838e333a242375d25e Mon Sep 17 00:00:00 2001 From: ChaHyeonMin Date: Tue, 26 Dec 2023 22:21:20 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20BearEats=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BearEatsController.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main/java/com/dku/council/domain/with_dankook/controller/BearEatsController.java diff --git a/src/main/java/com/dku/council/domain/with_dankook/controller/BearEatsController.java b/src/main/java/com/dku/council/domain/with_dankook/controller/BearEatsController.java new file mode 100644 index 00000000..82829ff3 --- /dev/null +++ b/src/main/java/com/dku/council/domain/with_dankook/controller/BearEatsController.java @@ -0,0 +1,101 @@ +package com.dku.council.domain.with_dankook.controller; + +import com.dku.council.domain.post.model.dto.response.ResponsePage; +import com.dku.council.domain.with_dankook.model.dto.list.SummarizedBearEatsDto; +import com.dku.council.domain.with_dankook.model.dto.request.RequestCreateBearEatsDto; +import com.dku.council.domain.with_dankook.model.dto.response.ResponseSingleBearEatsDto; +import com.dku.council.domain.with_dankook.service.BearEatsService; +import com.dku.council.global.auth.jwt.AppAuthentication; +import com.dku.council.global.auth.role.UserAuth; +import com.dku.council.global.model.dto.ResponseIdDto; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springdoc.api.annotations.ParameterObject; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@Tag(name = "BearEats", description = "단국 BearEats 게시판") +@RestController +@RequestMapping("with-dankook/bear-eats") +@RequiredArgsConstructor +public class BearEatsController { + + private final BearEatsService bearEatsService; + + /** + * BearEats 게시글 목록 조회 + * + * @param bodySize 게시글 본문 길이. (글자 단위) 지정하지 않으면 50 글자. + * @param pageable 페이징 size, sort, page + * @return 페이징된 BearEats 게시판 목록 + */ + @GetMapping + public ResponsePage list(@RequestParam(defaultValue = "50") int bodySize, + @ParameterObject Pageable pageable) { + Page list = bearEatsService.list(pageable, bodySize); + return new ResponsePage<>(list); + } + + /** + * 내가 쓴 BearEats 게시글 목록 조회 + * + * @param pageable 페이징 size, sort, page + * @return 페이징된 내가 쓴 BearEats 게시판 목록 + */ + @GetMapping("/my") + @UserAuth + public ResponsePage listMyPots(AppAuthentication auth, + @ParameterObject Pageable pageable) { + Page list = bearEatsService.listMyPosts(auth.getUserId(), pageable); + return new ResponsePage<>(list); + } + + /** + * BearEats 게시글 상세 조회 + * + * @param id 게시글 id + */ + @GetMapping("/{id}") + @UserAuth + public ResponseSingleBearEatsDto findOne(AppAuthentication auth, + @PathVariable Long id) { + return bearEatsService.findOne(id, auth.getUserId(), auth.getUserRole()); + } + + /** + * BearEats 게시글 작성 + */ + @PostMapping + @UserAuth + public ResponseIdDto create(AppAuthentication auth, + @Valid @RequestBody RequestCreateBearEatsDto dto) { + Long id = bearEatsService.create(auth.getUserId(), dto); + return new ResponseIdDto(id); + } + + /** + * BearEats 게시글 신청 + * + * @param id 게시글 id + */ + @PostMapping("/{id}/enter") + @UserAuth + public void enter(AppAuthentication auth, @PathVariable @Valid Long id) { + bearEatsService.enter(id, auth.getUserId(), auth.getUserRole()); + } + + /** + * BearEats 게시글 삭제 + * + * @param id 게시글 id + */ + @DeleteMapping("/{id}") + @UserAuth + public void delete(AppAuthentication auth, + @PathVariable Long id) { + bearEatsService.delete(id, auth.getUserId(), auth.isAdmin()); + } +}