diff --git a/.gitignore b/.gitignore index 9bf4c60..3449457 100644 --- a/.gitignore +++ b/.gitignore @@ -181,4 +181,4 @@ Temporary Items # 설정 파일 /src/main/resources/**.yml -/src/main/resources +/src/main/resources/**.properties \ No newline at end of file diff --git a/build.gradle b/build.gradle index af90392..bbde385 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,7 @@ configurations { compileOnly { extendsFrom annotationProcessor } + asciidoctorExt } repositories { @@ -25,7 +26,7 @@ repositories { } ext { - set('snippetsDir', file("build/generated-snippets")) + set('snippetsDir', file("src/dos")) // 변경된 경로 } dependencies { @@ -34,7 +35,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'io.jsonwebtoken:jjwt-api:0.12.6' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6' @@ -48,13 +48,12 @@ dependencies { annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' -// queryDsl 라이브러리 annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" runtimeOnly 'com.mysql:mysql-connector-j' - + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' testImplementation 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' @@ -68,9 +67,25 @@ tasks.named('test') { tasks.named('asciidoctor') { inputs.dir snippetsDir - dependsOn test + // dependsOn test 를 제거하여 순환 종속성을 피합니다. +} + +asciidoctor { + configurations 'asciidoctorExt' + baseDirFollowsSourceFile() + inputs.dir snippetsDir +} + +asciidoctor.doFirst { + delete file('src/main/resources/docs') +} + +task copyDocument(type: Copy) { + from file("build/docs/asciidoc") + into file("src/main/resources/docs") } -//clean { -// delete file('src/main/generated') -//} \ No newline at end of file +// build 작업에 copyDocument를 추가합니다. +build { + dependsOn copyDocument +} \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc new file mode 100644 index 0000000..e8aebec --- /dev/null +++ b/src/docs/asciidoc/index.adoc @@ -0,0 +1,11 @@ += Solitour -Resource + +:doctype: book +:toc: left +:toclevels: 3 +:sectnums: +:numbered: + + +// [[api]] +// includ::ee.adoc[] \ No newline at end of file diff --git a/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java b/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java index 8bec21b..607502a 100644 --- a/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java +++ b/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java @@ -85,7 +85,6 @@ public ResponseEntity logout(HttpServletResponse response, @Authentication return ResponseEntity.ok().build(); } - @PostMapping("/token/refresh") public ResponseEntity reissueAccessToken(HttpServletResponse response, @AuthenticationRefreshPrincipal Long memberId) { diff --git a/src/main/java/solitour_backend/solitour/auth/entity/Term.java b/src/main/java/solitour_backend/solitour/auth/entity/Term.java new file mode 100644 index 0000000..9397192 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/auth/entity/Term.java @@ -0,0 +1,45 @@ +package solitour_backend.solitour.auth.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import solitour_backend.solitour.user.entity.User; + +@Getter +@NoArgsConstructor +@Entity +@Builder +@AllArgsConstructor +@Table(name = "term") +public class Term { + + @Id + @Column(name = "term_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(nullable = false, name = "term_condition_agreement") + private Boolean termCondition; + + @Column(nullable = false, name = "term_privacy_agreement") + private Boolean termPrivacy; + + @Column(name="term_created_at") + private LocalDateTime createdAt; + +} diff --git a/src/main/java/solitour_backend/solitour/auth/entity/TermRepository.java b/src/main/java/solitour_backend/solitour/auth/entity/TermRepository.java new file mode 100644 index 0000000..5dcc6ff --- /dev/null +++ b/src/main/java/solitour_backend/solitour/auth/entity/TermRepository.java @@ -0,0 +1,15 @@ +package solitour_backend.solitour.auth.entity; + +import java.util.Optional; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.query.Param; +import solitour_backend.solitour.user.entity.User; + +public interface TermRepository extends Repository { + void save(Term term); + + @Query("SELECT t FROM Term t WHERE t.user = :user") + Optional findByUser(User user); +} diff --git a/src/main/java/solitour_backend/solitour/auth/service/OauthService.java b/src/main/java/solitour_backend/solitour/auth/service/OauthService.java index f507a2a..55d6cb3 100644 --- a/src/main/java/solitour_backend/solitour/auth/service/OauthService.java +++ b/src/main/java/solitour_backend/solitour/auth/service/OauthService.java @@ -222,6 +222,15 @@ private void checkUserStatus(User user) { } } + private void saveToken(KakaoTokenResponse tokenResponse, User user) { + Token token = Token.builder() + .user(user) + .oauthToken(tokenResponse.getRefreshToken()) + .build(); + + tokenRepository.save(token); + } + private User saveGoogleUser(GoogleUserResponse response) { String imageUrl = getGoogleUserImage(response); UserImage savedUserImage = userImageService.saveUserImage(imageUrl); @@ -258,7 +267,7 @@ private User saveActiveKakaoUser(KakaoUserResponse kakaoUserResponse, CreateUser UserImage savedUserImage = userImageService.saveUserImage(imageUrl); User user = User.builder() - .userStatus(UserStatus.ACTIVATE) + .userStatus(UserStatus.PENDING) .oauthId(String.valueOf(kakaoUserResponse.getId())) .provider("kakao") .isAdmin(false) @@ -279,7 +288,7 @@ private User saveKakaoUser(KakaoUserResponse response) { UserImage savedUserImage = userImageService.saveUserImage(imageUrl); User user = User.builder() - .userStatus(UserStatus.INACTIVATE) + .userStatus(UserStatus.PENDING) .oauthId(String.valueOf(response.getId())) .provider("kakao") .isAdmin(false) @@ -337,7 +346,6 @@ private void deleteCookie(String name, String value, HttpServletResponse respons response.addCookie(cookie); } - public void revokeToken(String type, String token) throws IOException { HttpStatusCode responseCode; switch (type) { @@ -376,15 +384,15 @@ private String getDefaultProfile(User user) { return USER_PROFILE_NONE; } - private void deleteUserProfileFromS3 (UserImage userImage, String defaultImageUrl){ - String userImageUrl = userImage.getAddress(); - if (userImageUrl.equals(USER_PROFILE_MALE) || userImageUrl.equals(USER_PROFILE_FEMALE) - || userImageUrl.equals( - USER_PROFILE_NONE)) { - return; - } - s3Uploader.deleteImage(userImageUrl); - userImage.changeToDefaultProfile(defaultImageUrl); + private void deleteUserProfileFromS3(UserImage userImage, String defaultImageUrl) { + String userImageUrl = userImage.getAddress(); + if (userImageUrl.equals(USER_PROFILE_MALE) || userImageUrl.equals(USER_PROFILE_FEMALE) + || userImageUrl.equals( + USER_PROFILE_NONE)) { + return; } - + s3Uploader.deleteImage(userImageUrl); + userImage.changeToDefaultProfile(defaultImageUrl); } + +} diff --git a/src/main/java/solitour_backend/solitour/diary/service/DiaryService.java b/src/main/java/solitour_backend/solitour/diary/service/DiaryService.java index eb71af5..7c90983 100644 --- a/src/main/java/solitour_backend/solitour/diary/service/DiaryService.java +++ b/src/main/java/solitour_backend/solitour/diary/service/DiaryService.java @@ -94,7 +94,8 @@ public void updateDiary(Long userId, Long diaryId, DiaryUpdateRequest request) { } private void updateDiary(Long diaryId, DiaryUpdateRequest request) { - Diary diary = diaryRepository.findById(diaryId).orElseThrow(() -> new DiaryNotExistsException("해당 일기가 존재하지 않습니다.")); + Diary diary = diaryRepository.findById(diaryId) + .orElseThrow(() -> new DiaryNotExistsException("해당 일기가 존재하지 않습니다.")); deleteDiaryImage(request); diary.getDiaryDayContent().clear(); diary.updateDiary(request); @@ -103,6 +104,7 @@ private void updateDiary(Long diaryId, DiaryUpdateRequest request) { private void saveDiaryDayContent(Diary savedDiary, DiaryCreateRequest request) { for (DiaryDayRequest dayRequest : request.getDiaryDayRequests()) { + makeDiaryImagePermanent(dayRequest.getDiaryDayContentImages()); DiaryDayContent diaryDayContent = DiaryDayContent.builder() .diary(savedDiary) .content(dayRequest.getContent()) @@ -114,6 +116,15 @@ private void saveDiaryDayContent(Diary savedDiary, DiaryCreateRequest request) { } } + private void makeDiaryImagePermanent(String diaryDayContentImages) { + if (!diaryDayContentImages.isEmpty()) { + String[] contentImages = diaryDayContentImages.split(","); + for (String contentImage : contentImages) { + s3Uploader.markImagePermanent(contentImage); + } + } + } + private void updateDiaryDayContent(Diary savedDiary, DiaryUpdateRequest request) { diaryDayContentRepository.deleteById(savedDiary.getId()); for (DiaryUpdateDayRequest dayRequest : request.getDiaryDayRequests()) { diff --git a/src/main/java/solitour_backend/solitour/information/controller/InformationController.java b/src/main/java/solitour_backend/solitour/information/controller/InformationController.java index fda6368..2953616 100644 --- a/src/main/java/solitour_backend/solitour/information/controller/InformationController.java +++ b/src/main/java/solitour_backend/solitour/information/controller/InformationController.java @@ -20,7 +20,6 @@ import solitour_backend.solitour.auth.config.Authenticated; import solitour_backend.solitour.auth.config.AuthenticationPrincipal; import solitour_backend.solitour.auth.exception.TokenNotExistsException; -import solitour_backend.solitour.auth.exception.TokenNotValidException; import solitour_backend.solitour.auth.support.CookieExtractor; import solitour_backend.solitour.auth.support.JwtTokenProvider; import solitour_backend.solitour.error.Utils; diff --git a/src/main/java/solitour_backend/solitour/information/dto/response/InformationBriefResponse.java b/src/main/java/solitour_backend/solitour/information/dto/response/InformationBriefResponse.java index c833211..2478487 100644 --- a/src/main/java/solitour_backend/solitour/information/dto/response/InformationBriefResponse.java +++ b/src/main/java/solitour_backend/solitour/information/dto/response/InformationBriefResponse.java @@ -2,9 +2,11 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.ToString; @Getter @AllArgsConstructor +@ToString public class InformationBriefResponse { private Long informationId; diff --git a/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryCustom.java b/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryCustom.java index 4100ea6..0076f59 100644 --- a/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryCustom.java +++ b/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryCustom.java @@ -14,10 +14,11 @@ public interface InformationRepositoryCustom { String LIKE_COUNT_SORT = "likes"; String VIEW_COUNT_SORT = "views"; + Page getPageInformationFilterAndOrder(Pageable pageable, InformationPageRequest informationPageRequest, Long userId, Long parentCategoryId); - Page getInformationPageFilterAndOrder(Pageable pageable, - InformationPageRequest informationPageRequest, - Long userId, Long parentCategoryId); +// Page getInformationPageFilterAndOrder(Pageable pageable, +// InformationPageRequest informationPageRequest, +// Long userId, Long parentCategoryId); List getInformationRank(); diff --git a/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryImpl.java b/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryImpl.java index 67a2657..c7799cb 100644 --- a/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryImpl.java +++ b/src/main/java/solitour_backend/solitour/information/repository/InformationRepositoryImpl.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Objects; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -29,6 +30,7 @@ import solitour_backend.solitour.information.entity.QInformation; import solitour_backend.solitour.zone_category.entity.QZoneCategory; +@Slf4j public class InformationRepositoryImpl extends QuerydslRepositorySupport implements InformationRepositoryCustom { public InformationRepositoryImpl() { @@ -42,47 +44,48 @@ public InformationRepositoryImpl() { QImage image = QImage.image; QGreatInformation greatInformation = QGreatInformation.greatInformation; QCategory category = QCategory.category; + QCategory categoryParent = new QCategory("categoryParent"); QInfoTag infoTag = QInfoTag.infoTag; - - @Override - public Page getInformationPageFilterAndOrder(Pageable pageable, - InformationPageRequest informationPageRequest, - Long userId, Long parentCategoryId) { + public Page getPageInformationFilterAndOrder(Pageable pageable, InformationPageRequest informationPageRequest, Long userId, Long parentCategoryId) { BooleanBuilder whereClause = new BooleanBuilder(); - if (Objects.nonNull(informationPageRequest.getZoneCategoryId())) { whereClause.and( - information.zoneCategory.parentZoneCategory.id.eq(informationPageRequest.getZoneCategoryId())); + zoneCategoryParent.id.eq(informationPageRequest.getZoneCategoryId()) + ); } - BooleanBuilder categoryCondition = new BooleanBuilder(); - if (Objects.nonNull(informationPageRequest.getChildCategoryId())) { - whereClause.and(information.category.id.eq(informationPageRequest.getChildCategoryId())); + whereClause.and(category.id.eq(informationPageRequest.getChildCategoryId())); } else { - categoryCondition.and(category.parentCategory.id.eq(parentCategoryId)); + whereClause.and(categoryParent.id.eq(parentCategoryId)); } - if (Objects.nonNull(informationPageRequest.getSearch())) { String searchKeyword = informationPageRequest.getSearch().trim().replace(" ", ""); whereClause.and(information.title.trim().containsIgnoreCase(searchKeyword)); } - long total = from(information) + .leftJoin(zoneCategoryChild).on(zoneCategoryChild.id.eq(information.zoneCategory.id)) + .leftJoin(zoneCategoryParent).on(zoneCategoryChild.parentZoneCategory.id.eq(zoneCategoryParent.id)) + .leftJoin(category).on(category.id.eq(information.category.id)) + .leftJoin(categoryParent).on(categoryParent.id.eq(category.parentCategory.id)) + .join(image).on(image.information.id.eq(information.id).and(image.imageStatus.eq(ImageStatus.THUMBNAIL))) .where(whereClause) - .select(information.id).fetchCount(); + .distinct() + .fetchCount(); List list = from(information) - .join(zoneCategoryChild).on(zoneCategoryChild.id.eq(information.zoneCategory.id)) - .leftJoin(zoneCategoryParent).on(zoneCategoryParent.id.eq(zoneCategoryChild.parentZoneCategory.id)) - .leftJoin(image) - .on(image.information.id.eq(information.id).and(image.imageStatus.eq(ImageStatus.THUMBNAIL))) - .join(category).on(category.id.eq(information.category.id).and(categoryCondition)) + .leftJoin(zoneCategoryChild).on(zoneCategoryChild.id.eq(information.zoneCategory.id)) + .leftJoin(zoneCategoryParent).on(zoneCategoryChild.parentZoneCategory.id.eq(zoneCategoryParent.id)) + .leftJoin(category).on(category.id.eq(information.category.id)) + .leftJoin(categoryParent).on(categoryParent.id.eq(category.parentCategory.id)) + .leftJoin(image).on(image.information.id.eq(information.id).and(image.imageStatus.eq(ImageStatus.THUMBNAIL))) + .leftJoin(bookMarkInformation).on(bookMarkInformation.information.id.eq(information.id).and(bookMarkInformation.user.id.eq(userId))) + .leftJoin(greatInformation).on(greatInformation.information.id.eq(information.id)) .where(whereClause) - .groupBy(information.id, zoneCategoryChild.id, zoneCategoryParent.id, image.id) - .orderBy(getOrderSpecifier(informationPageRequest.getSort(), information.id)) + .groupBy(information.id, information.createdDate, information.viewCount, zoneCategoryChild.name, bookMarkInformation.id, image.address) + .orderBy(getOrderSpecifiers(informationPageRequest.getSort())) .select(Projections.constructor( InformationBriefResponse.class, information.id, @@ -91,17 +94,104 @@ public Page getInformationPageFilterAndOrder(Pageable zoneCategoryChild.name, information.category.name, information.viewCount, - isInformationBookmark(userId, information.id), + isBookMarkBooleanExpression(bookMarkInformation), image.address, - countGreatInformationByInformationById(information.id), - isUserGreatInformation(userId) + countGreatInformation(greatInformation), + isGreatBooleanExpression(userId, greatInformation) )).offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); - + log.info("정보 페이지 네이션 총 갯수 : " + total + "\n"); + log.info("정보 들 : "); + log.info(list.toString()); return new PageImpl<>(list, pageable, total); } + private OrderSpecifier getOrderSpecifiers(String sort) { + if (Objects.nonNull(sort)) { + if (Objects.equals(LIKE_COUNT_SORT, sort)) { + return countGreatInformation(greatInformation).desc(); + } else if (Objects.equals(VIEW_COUNT_SORT, sort)) { + return information.viewCount.desc(); + } + } + return information.createdDate.desc(); + } + + private BooleanExpression isBookMarkBooleanExpression(QBookMarkInformation bookMarkInformation) { + return new CaseBuilder() + .when(bookMarkInformation.id.isNotNull()) + .then(true) + .otherwise(false); + } + + private BooleanExpression isGreatBooleanExpression(Long userId, QGreatInformation greatInformation) { + return greatInformation.user.id.eq(userId).count().gt(0); + } + + private NumberExpression countGreatInformation(QGreatInformation greatInformation) { + return greatInformation.id.count().intValue(); + } + +// @Override +// public Page getInformationPageFilterAndOrder(Pageable pageable, +// InformationPageRequest informationPageRequest, +// Long userId, Long parentCategoryId) { +// BooleanBuilder whereClause = new BooleanBuilder(); +// +// if (Objects.nonNull(informationPageRequest.getZoneCategoryId())) { +// whereClause.and( +// information.zoneCategory.parentZoneCategory.id.eq(informationPageRequest.getZoneCategoryId())); +// } +// +// BooleanBuilder categoryCondition = new BooleanBuilder(); +// +// if (Objects.nonNull(informationPageRequest.getChildCategoryId())) { +// whereClause.and(information.category.id.eq(informationPageRequest.getChildCategoryId())); +// } else { +// categoryCondition.and(category.parentCategory.id.eq(parentCategoryId)); +// } +// +// if (Objects.nonNull(informationPageRequest.getSearch())) { +// String searchKeyword = informationPageRequest.getSearch().trim().replace(" ", ""); +// whereClause.and(information.title.trim().containsIgnoreCase(searchKeyword)); +// } +// +// +// long total = from(information) +// .where(whereClause) +// .select(information.id).fetchCount(); +// System.out.println("page 네이션 총 데이터 갯수 : " + total); +// List list = from(information) +// .join(zoneCategoryChild).on(zoneCategoryChild.id.eq(information.zoneCategory.id)) +// .leftJoin(zoneCategoryParent).on(zoneCategoryParent.id.eq(zoneCategoryChild.parentZoneCategory.id)) +// .leftJoin(image) +// .on(image.information.id.eq(information.id).and(image.imageStatus.eq(ImageStatus.THUMBNAIL))) +// .join(category).on(category.id.eq(information.category.id).and(categoryCondition)) +// .where(whereClause) +// .groupBy(information.id, zoneCategoryChild.id, zoneCategoryParent.id, image.id) +// .orderBy(getOrderSpecifier(informationPageRequest.getSort(), information.id)) +// .select(Projections.constructor( +// InformationBriefResponse.class, +// information.id, +// information.title, +// zoneCategoryParent.name, +// zoneCategoryChild.name, +// information.category.name, +// information.viewCount, +// isInformationBookmark(userId, information.id), +// image.address, +// countGreatInformationByInformationById(information.id), +// isUserGreatInformation(userId) +// )).offset(pageable.getOffset()) +// .limit(pageable.getPageSize()) +// .fetch(); +// System.out.println(list.size()); +// System.out.println(list); +// +// return new PageImpl<>(list, pageable, total); +// } + @Override public List getInformationLikeCountFromCreatedIn3(Long userId) { @@ -112,7 +202,7 @@ public List getInformationLikeCountFromCreatedIn3(Long .leftJoin(category).on(category.id.eq(information.category.id)) .where(information.createdDate.after(LocalDateTime.now().minusMonths(3))) .groupBy(information.id, zoneCategoryParent.name, zoneCategoryChild.name, image.address) - .orderBy(countGreatInformationByInformationById(information.id).desc()) + .orderBy(countGreatInformationByInformationByIdSubQuery(information.id).desc()) .select(Projections.constructor( InformationMainResponse.class, information.id, @@ -121,10 +211,10 @@ public List getInformationLikeCountFromCreatedIn3(Long zoneCategoryChild.name, category.parentCategory.name, information.viewCount, - isInformationBookmark(userId, information.id), + isInformationBookmarkSubQuery(userId, information.id), image.address, - countGreatInformationByInformationById(information.id), // 파라미터 전달 - isUserGreatInformation(userId) + countGreatInformationByInformationByIdSubQuery(information.id), // 파라미터 전달 + isUserGreatInformationSubQuery(userId) )).limit(6).fetch(); } @@ -147,17 +237,18 @@ public List getInformationRecommend(Long informationId zoneCategoryChild.name, information.category.name, information.viewCount, - isInformationBookmark(userId, information.id), + isInformationBookmarkSubQuery(userId, information.id), image.address, - countGreatInformationByInformationById(information.id), - isUserGreatInformation(userId) + countGreatInformationByInformationByIdSubQuery(information.id), + isUserGreatInformationSubQuery(userId) )) .limit(3L) .fetch(); } @Override - public Page getInformationPageByTag(Pageable pageable, Long userId, Long parentCategoryId, + public Page getInformationPageByTag(Pageable pageable, Long userId, Long + parentCategoryId, InformationPageRequest informationPageRequest, String decodedTag) { BooleanBuilder whereClause = new BooleanBuilder(); @@ -213,8 +304,8 @@ public Page getInformationPageByTag(Pageable pageable, information.viewCount, bookMarkInformation.user.id.isNotNull(), image.address, - countGreatInformationByInformationById(information.id), - isUserGreatInformation(userId) + countGreatInformationByInformationByIdSubQuery(information.id), + isUserGreatInformationSubQuery(userId) )).offset(pageable.getOffset()) .limit(pageable.getPageSize()) .fetch(); @@ -228,7 +319,7 @@ public List getInformationRank() { .leftJoin(greatInformation) .on(greatInformation.information.id.eq(information.id)) .groupBy(information.id, information.title) - .orderBy(countGreatInformationByInformationById(information.id).desc()) + .orderBy(countGreatInformationByInformationByIdSubQuery(information.id).desc()) .limit(5) .select(Projections.constructor( InformationRankResponse.class, @@ -240,7 +331,7 @@ public List getInformationRank() { private OrderSpecifier getOrderSpecifier(String sort, NumberPath informationId) { if (Objects.nonNull(sort)) { if (Objects.equals(LIKE_COUNT_SORT, sort)) { - return countGreatInformationByInformationById(informationId).desc(); + return countGreatInformationByInformationByIdSubQuery(informationId).desc(); } else if (Objects.equals(VIEW_COUNT_SORT, sort)) { return information.viewCount.desc(); } @@ -248,7 +339,7 @@ private OrderSpecifier getOrderSpecifier(String sort, NumberPath inform return information.createdDate.desc(); } - private NumberExpression countGreatInformationByInformationById(NumberPath informationId) { + private NumberExpression countGreatInformationByInformationByIdSubQuery(NumberPath informationId) { QGreatInformation greatInformationSub = QGreatInformation.greatInformation; JPQLQuery likeCountSubQuery = JPAExpressions .select(greatInformationSub.count()) @@ -260,7 +351,7 @@ private NumberExpression countGreatInformationByInformationById(NumberP .intValue(); } - private BooleanExpression isUserGreatInformation(Long userId) { + private BooleanExpression isUserGreatInformationSubQuery(Long userId) { return new CaseBuilder() .when(JPAExpressions.selectOne() .from(greatInformation) @@ -271,7 +362,7 @@ private BooleanExpression isUserGreatInformation(Long userId) { .otherwise(false); } - private BooleanExpression isInformationBookmark(Long userId, NumberPath informationId) { + private BooleanExpression isInformationBookmarkSubQuery(Long userId, NumberPath informationId) { return new CaseBuilder() .when(JPAExpressions.selectOne() .from(bookMarkInformation) diff --git a/src/main/java/solitour_backend/solitour/information/service/InformationService.java b/src/main/java/solitour_backend/solitour/information/service/InformationService.java index 8cfef9e..f0b04ec 100644 --- a/src/main/java/solitour_backend/solitour/information/service/InformationService.java +++ b/src/main/java/solitour_backend/solitour/information/service/InformationService.java @@ -458,7 +458,7 @@ public Page getPageInformation(Pageable pageable, Long } } - return informationRepository.getInformationPageFilterAndOrder(pageable, informationPageRequest, userId, parentCategoryId); + return informationRepository.getPageInformationFilterAndOrder(pageable, informationPageRequest, userId, parentCategoryId); } public List getRankInformation() { diff --git a/src/main/java/solitour_backend/solitour/user/controller/UserController.java b/src/main/java/solitour_backend/solitour/user/controller/UserController.java index 6287361..8f586a2 100644 --- a/src/main/java/solitour_backend/solitour/user/controller/UserController.java +++ b/src/main/java/solitour_backend/solitour/user/controller/UserController.java @@ -22,7 +22,8 @@ import solitour_backend.solitour.gathering.dto.response.GatheringMypageResponse; import solitour_backend.solitour.information.dto.response.InformationBriefResponse; import solitour_backend.solitour.user.dto.UpdateNicknameRequest; -import solitour_backend.solitour.user.dto.request.UpdateUserInfoRequest; +import solitour_backend.solitour.user.dto.request.AgreeUserInfoRequest; +import solitour_backend.solitour.user.dto.request.DisagreeUserInfoRequest; import solitour_backend.solitour.user.exception.NicknameAlreadyExistsException; import solitour_backend.solitour.user.exception.UserNotExistsException; import solitour_backend.solitour.user.service.UserService; @@ -44,10 +45,18 @@ public ResponseEntity retrieveUserInfo(@AuthenticationPrincipa return ResponseEntity.ok(response); } - @PutMapping("/info") - public ResponseEntity updateUserInfo(@AuthenticationPrincipal Long userId, - @RequestBody UpdateUserInfoRequest request) { - userService.updateUserInfo(userId, request); + @PutMapping("/info/agree") + public ResponseEntity agreeUserInfo(@AuthenticationPrincipal Long userId, + @RequestBody AgreeUserInfoRequest request) { + userService.agreeUserInfo(userId, request); + + return ResponseEntity.noContent().build(); + } + + @PutMapping("/info/disagree") + public ResponseEntity disagreeUserInfo(@AuthenticationPrincipal Long userId, + @RequestBody DisagreeUserInfoRequest request) { + userService.disagreeUserInfo(userId, request); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/solitour_backend/solitour/user/dto/request/UpdateUserInfoRequest.java b/src/main/java/solitour_backend/solitour/user/dto/request/AgreeUserInfoRequest.java similarity index 62% rename from src/main/java/solitour_backend/solitour/user/dto/request/UpdateUserInfoRequest.java rename to src/main/java/solitour_backend/solitour/user/dto/request/AgreeUserInfoRequest.java index 704c56e..d1b2c5e 100644 --- a/src/main/java/solitour_backend/solitour/user/dto/request/UpdateUserInfoRequest.java +++ b/src/main/java/solitour_backend/solitour/user/dto/request/AgreeUserInfoRequest.java @@ -5,7 +5,9 @@ @NoArgsConstructor @Getter -public class UpdateUserInfoRequest { +public class AgreeUserInfoRequest { + private Boolean termConditionAgreement; + private Boolean privacyPolicyAgreement; private String name; private String age; private String sex; diff --git a/src/main/java/solitour_backend/solitour/user/dto/request/DisagreeUserInfoRequest.java b/src/main/java/solitour_backend/solitour/user/dto/request/DisagreeUserInfoRequest.java new file mode 100644 index 0000000..0acb13d --- /dev/null +++ b/src/main/java/solitour_backend/solitour/user/dto/request/DisagreeUserInfoRequest.java @@ -0,0 +1,11 @@ +package solitour_backend.solitour.user.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class DisagreeUserInfoRequest { + private Boolean termConditionAgreement; + private Boolean privacyPolicyAgreement; +} diff --git a/src/main/java/solitour_backend/solitour/user/entity/User.java b/src/main/java/solitour_backend/solitour/user/entity/User.java index 3be3753..f5196a0 100644 --- a/src/main/java/solitour_backend/solitour/user/entity/User.java +++ b/src/main/java/solitour_backend/solitour/user/entity/User.java @@ -1,5 +1,6 @@ package solitour_backend.solitour.user.entity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.Entity; @@ -15,7 +16,9 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import solitour_backend.solitour.user.dto.request.UpdateUserInfoRequest; +import solitour_backend.solitour.auth.entity.Term; +import solitour_backend.solitour.user.dto.request.AgreeUserInfoRequest; +import solitour_backend.solitour.user.dto.request.DisagreeUserInfoRequest; import solitour_backend.solitour.user.user_status.UserStatus; import solitour_backend.solitour.user.user_status.UserStatusConverter; import solitour_backend.solitour.user_image.entity.UserImage; @@ -47,6 +50,9 @@ public class User { @JoinColumn(name = "user_image_id") private UserImage userImage; + @OneToOne(mappedBy = "user",cascade = CascadeType.ALL) + private Term term; + @Column(name = "user_nickname") private String nickname; @@ -105,10 +111,14 @@ public void updateLoginTime() { this.latestLoginAt = LocalDateTime.now(); } - public void updateUserInfo(UpdateUserInfoRequest request) { + public void agreeUserInfo(AgreeUserInfoRequest request) { this.name = request.getName(); this.userStatus = UserStatus.ACTIVATE; this.age = Integer.valueOf(request.getAge()); this.sex = request.getSex(); } + + public void disagreeUserInfo(DisagreeUserInfoRequest request) { + this.userStatus = UserStatus.INACTIVATE; + } } diff --git a/src/main/java/solitour_backend/solitour/user/repository/UserRepository.java b/src/main/java/solitour_backend/solitour/user/repository/UserRepository.java index 059014d..e518bdb 100644 --- a/src/main/java/solitour_backend/solitour/user/repository/UserRepository.java +++ b/src/main/java/solitour_backend/solitour/user/repository/UserRepository.java @@ -7,10 +7,10 @@ public interface UserRepository extends JpaRepository, UserRepositoryCustom { - @Query("SELECT u FROM User u JOIN FETCH u.userImage WHERE u.id = :userId AND (u.userStatus = '활성화' OR u.userStatus = '비활성화')") + @Query("SELECT u FROM User u JOIN FETCH u.userImage WHERE u.id = :userId AND u.userStatus NOT IN ('차단', '휴먼','삭제')") User findByUserId(Long userId); - @Query("SELECT u FROM User u JOIN FETCH u.userImage WHERE u.oauthId = :oauthId AND (u.userStatus = '활성화' OR u.userStatus = '비활성화')") + @Query("SELECT u FROM User u JOIN FETCH u.userImage WHERE u.oauthId = :oauthId AND u.userStatus NOT IN ('차단', '휴먼','삭제')") Optional findByOauthId(String oauthId); boolean existsByNickname(String nickname); diff --git a/src/main/java/solitour_backend/solitour/user/service/UserService.java b/src/main/java/solitour_backend/solitour/user/service/UserService.java index 92bcd34..03d06b0 100644 --- a/src/main/java/solitour_backend/solitour/user/service/UserService.java +++ b/src/main/java/solitour_backend/solitour/user/service/UserService.java @@ -1,5 +1,6 @@ package solitour_backend.solitour.user.service; +import java.time.LocalDateTime; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; @@ -7,11 +8,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import solitour_backend.solitour.auth.entity.Term; +import solitour_backend.solitour.auth.entity.TermRepository; import solitour_backend.solitour.gathering.dto.response.GatheringApplicantResponse; import solitour_backend.solitour.gathering.dto.response.GatheringMypageResponse; import solitour_backend.solitour.image.s3.S3Uploader; import solitour_backend.solitour.information.dto.response.InformationBriefResponse; -import solitour_backend.solitour.user.dto.request.UpdateUserInfoRequest; +import solitour_backend.solitour.user.dto.request.AgreeUserInfoRequest; +import solitour_backend.solitour.user.dto.request.DisagreeUserInfoRequest; import solitour_backend.solitour.user.entity.User; import solitour_backend.solitour.user.exception.NicknameAlreadyExistsException; import solitour_backend.solitour.user.repository.UserRepository; @@ -26,6 +30,7 @@ public class UserService { private final UserRepository userRepository; private final UserImageService userImageService; + private final TermRepository termRepository; private final S3Uploader s3Uploader; @Value("${user.profile.url.female}") private String femaleProfileUrl; @@ -84,13 +89,33 @@ public Page retrieveGatheringApplicant(Pageable page } @Transactional - public void updateUserInfo(Long userId, UpdateUserInfoRequest request) { + public void agreeUserInfo(Long userId, AgreeUserInfoRequest request) { User user = userRepository.findByUserId(userId); changeUserProfile(user, request); - user.updateUserInfo(request); + if(!termRepository.findByUser(user).isPresent()){ + saveTerm(user, request.getTermConditionAgreement(),request.getPrivacyPolicyAgreement()); + } + user.agreeUserInfo(request); + } + + @Transactional + public void disagreeUserInfo(Long userId, DisagreeUserInfoRequest request) { + User user = userRepository.findByUserId(userId); + saveTerm(user, request.getTermConditionAgreement(),request.getPrivacyPolicyAgreement()); + user.disagreeUserInfo(request); + } + + private void saveTerm(User user, Boolean termCondition, Boolean termPrivacy) { + Term term = Term.builder() + .user(user) + .termCondition(termCondition) + .termPrivacy(termPrivacy) + .createdAt(LocalDateTime.now()) + .build(); + termRepository.save(term); } - private void changeUserProfile(User user, UpdateUserInfoRequest request) { + private void changeUserProfile(User user, AgreeUserInfoRequest request) { String sex = request.getSex(); if(user.getUserImage().equals(noneProfileUrl) && sex.equals("male")){ diff --git a/src/main/java/solitour_backend/solitour/user/user_status/UserStatus.java b/src/main/java/solitour_backend/solitour/user/user_status/UserStatus.java index 3e6759c..a18f459 100644 --- a/src/main/java/solitour_backend/solitour/user/user_status/UserStatus.java +++ b/src/main/java/solitour_backend/solitour/user/user_status/UserStatus.java @@ -5,6 +5,7 @@ @Getter public enum UserStatus { + PENDING("대기"), ACTIVATE("활성화"), INACTIVATE("비활성화"), BLOCK("차단"), diff --git a/src/main/java/solitour_backend/solitour/user_image/service/UserImageService.java b/src/main/java/solitour_backend/solitour/user_image/service/UserImageService.java index 6f50992..4881516 100644 --- a/src/main/java/solitour_backend/solitour/user_image/service/UserImageService.java +++ b/src/main/java/solitour_backend/solitour/user_image/service/UserImageService.java @@ -32,6 +32,7 @@ public UserImage saveUserImage(String imageUrl) { public UserImageResponse updateUserProfile(Long userId, MultipartFile userImage) { String userImageUrl = s3Uploader.upload(userImage, IMAGE_PATH, userId); + s3Uploader.markImagePermanent(userImageUrl); return new UserImageResponse(userImageUrl); } diff --git a/src/main/resources/docs/index.html b/src/main/resources/docs/index.html new file mode 100644 index 0000000..b6b1bc2 --- /dev/null +++ b/src/main/resources/docs/index.html @@ -0,0 +1,456 @@ + + + + + + + +Solitour -Resource + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 80fd873..f4e92b0 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -19,6 +19,7 @@ DROP TABLE IF EXISTS `banner`; DROP TABLE IF EXISTS `notice`; DROP TABLE IF EXISTS `qna_message`; DROP TABLE IF EXISTS `qna`; +DROP TABLE IF EXISTS `term`; DROP TABLE IF EXISTS `user`; DROP TABLE IF EXISTS `user_image`; DROP TABLE IF EXISTS `diary_day_content`; @@ -311,4 +312,16 @@ CREATE TABLE `diary_day_content` `diary_day_content_image` TEXT DEFAULT NULL, PRIMARY KEY (`diary_day_content_id`), CONSTRAINT `FK_diary_day_content_TO_diary` FOREIGN KEY (`diary_id`) REFERENCES `diary` (`diary_id`) -); \ No newline at end of file +); + + +CREATE TABLE `term` +( + `term_id` BIGINT NOT NULL AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `term_condition_agreement` BOOLEAN NOT NULL, + `term_privacy_agreement` BOOLEAN NOT NULL, + `term_created_at` DATETIME NOT NULL, + PRIMARY KEY (`term_id`), + CONSTRAINT `FK_term_TO_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) +); diff --git a/src/main/resources/schema_test.sql b/src/main/resources/schema_test.sql index b1b3576..e05c3e1 100644 --- a/src/main/resources/schema_test.sql +++ b/src/main/resources/schema_test.sql @@ -23,233 +23,268 @@ DROP TABLE IF EXISTS "qna_message"; DROP TABLE IF EXISTS "notice"; DROP TABLE IF EXISTS "diary"; DROP TABLE IF EXISTS "diary_day_content"; +DROP TABLE IF EXISTS `term`; -- 테이블 생성 -CREATE TABLE "user_image" ( - "user_image_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_image_address" VARCHAR(200) NOT NULL, - "user_image_created_date" DATE NOT NULL -); - -CREATE TABLE "user" ( - "user_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_image_id" BIGINT NOT NULL, - "user_status_id" VARCHAR(20) NOT NULL, - "user_oauth_id" VARCHAR(100), - "provider" VARCHAR(10), - "user_nickname" VARCHAR(30), - "user_name" VARCHAR(20), - "user_age" INT, - "user_sex" VARCHAR(10), - "user_email" VARCHAR(30), - "user_phone_number" VARCHAR(13), - "is_admin" BOOLEAN NOT NULL, - "user_latest_login_at" DATETIME, - "user_created_at" DATETIME NOT NULL, - "user_deleted_at" DATETIME, - FOREIGN KEY ("user_image_id") REFERENCES "user_image" ("user_image_id") -); - -CREATE TABLE "token" ( - "token_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "refresh_token" VARCHAR(250) NOT NULL, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") -); - -CREATE TABLE "place" ( - "place_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "place_search_id" VARCHAR(30), - "place_name" VARCHAR(30) NOT NULL, - "place_x_axis" DECIMAL(10, 7) NOT NULL, - "place_y_axis" DECIMAL(10, 7) NOT NULL, - "place_address" VARCHAR(50) NOT NULL -); - -CREATE TABLE "zone_category" ( - "zone_category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "parent_zone_category_id" BIGINT, - "zone_category_name" VARCHAR(20) NOT NULL, - FOREIGN KEY ("parent_zone_category_id") REFERENCES "zone_category" ("zone_category_id") -); - -CREATE TABLE "category" ( - "category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "parent_category_id" BIGINT, - "category_name" VARCHAR(20) NOT NULL, - FOREIGN KEY ("parent_category_id") REFERENCES "category" ("category_id") -); - -CREATE TABLE "gathering_category" ( - "gathering_category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "gathering_category_name" VARCHAR(20) NOT NULL -); - -CREATE TABLE "information" ( - "information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "category_id" BIGINT NOT NULL, - "zone_category_id" BIGINT NOT NULL, - "user_id" BIGINT NOT NULL, - "place_id" BIGINT NOT NULL, - "information_title" VARCHAR(50) NOT NULL, - "information_address" VARCHAR(50) NOT NULL, - "information_created_date" DATETIME NOT NULL, - "information_view_count" INT NOT NULL DEFAULT 0, - "information_content" TEXT, - "information_tip" TEXT, - FOREIGN KEY ("category_id") REFERENCES "category" ("category_id"), - FOREIGN KEY ("zone_category_id") REFERENCES "zone_category" ("zone_category_id"), - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("place_id") REFERENCES "place" ("place_id") -); - -CREATE TABLE "gathering" ( - "gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "zone_category_id" BIGINT NOT NULL, - "gathering_category_id" BIGINT NOT NULL, - "place_id" BIGINT NOT NULL, - "gathering_title" VARCHAR(50), - "gathering_content" TEXT, - "gathering_person_count" INT, - "gathering_view_count" INT, - "gathering_created_at" DATETIME, - "gathering_edited_at" DATETIME, - "gathering_schedule_start_date" DATETIME, - "gathering_schedule_end_date" DATETIME, - "gathering_is_finish" BOOLEAN, - "gathering_deadline" DATETIME, - "gathering_allowed_sex" VARCHAR(30) NOT NULL, - "gathering_start_age" INT NOT NULL, - "gathering_end_age" INT NOT NULL, - "gathering_is_deleted" BOOLEAN NOT NULL DEFAULT FALSE, - "gathering_open_chatting_url" VARCHAR(255), - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("gathering_category_id") REFERENCES "gathering_category" ("gathering_category_id"), - FOREIGN KEY ("zone_category_id") REFERENCES "zone_category" ("zone_category_id"), - FOREIGN KEY ("place_id") REFERENCES "place" ("place_id") -); - -CREATE TABLE "gathering_applicants" ( - "gathering_applicants_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "gathering_id" BIGINT NOT NULL, - "user_id" BIGINT NOT NULL, - "gathering_applicants_state" VARCHAR(20) NOT NULL, - FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") -); - -CREATE TABLE "image" ( - "image_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "image_status_id" VARCHAR(20) NOT NULL, - "information_id" BIGINT NOT NULL, - "image_address" VARCHAR(200) NOT NULL, - "image_created_date" DATE NOT NULL, - FOREIGN KEY ("information_id") REFERENCES "information" ("information_id") -); - -CREATE TABLE "great_information" ( - "great_information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "information_id" BIGINT NOT NULL, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), - UNIQUE ("user_id", "information_id") -); - -CREATE TABLE "great_gathering" ( - "great_gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "gathering_id" BIGINT NOT NULL, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), - UNIQUE ("user_id", "gathering_id") -); - -CREATE TABLE "book_mark_information" ( - "book_mark_information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "information_id" BIGINT NOT NULL, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), - UNIQUE ("user_id", "information_id") -); - -CREATE TABLE "book_mark_gathering" ( - "book_mark_gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "gathering_id" BIGINT NOT NULL, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), - FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), - UNIQUE ("user_id", "gathering_id") -); - -CREATE TABLE "tag" ( - "tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "tag_name" VARCHAR(16) NOT NULL -); - -CREATE TABLE "info_tag" ( - "info_tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "tag_id" BIGINT NOT NULL, - "information_id" BIGINT NOT NULL, - FOREIGN KEY ("tag_id") REFERENCES "tag" ("tag_id"), - FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), - UNIQUE ("tag_id", "information_id") -); - -CREATE TABLE "gathering_tag" ( - "gathering_tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "tag_id" BIGINT NOT NULL, - "gathering_id" BIGINT NOT NULL, - FOREIGN KEY ("tag_id") REFERENCES "tag" ("tag_id"), - FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), - UNIQUE ("tag_id", "gathering_id") -); - -CREATE TABLE "banner" ( - "id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "name" VARCHAR(255) NOT NULL, - "url" VARCHAR(255) NOT NULL -); - -CREATE TABLE "qna" ( - "qna_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "qna_category_name" VARCHAR(255), - "qna_created_at" DATETIME, - "qna_status" VARCHAR(255), - "qna_title" VARCHAR(255), - "qna_updated_at" DATETIME, - "user_id" BIGINT, - FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") -); - -CREATE TABLE "qna_message" ( - "id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "qna_message_content" TEXT, - "qna_message_created_at" DATETIME, - "qna_message_user_id" BIGINT, - "qna_id" BIGINT, - FOREIGN KEY ("qna_id") REFERENCES "qna" ("qna_id"), - FOREIGN KEY ("qna_message_user_id") REFERENCES "user" ("user_id") -); - -CREATE TABLE "notice" ( - "notice_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "notice_category_name" VARCHAR(255), - "notice_content" TEXT, - "notice_created_at" DATETIME, - "notice_is_deleted" BOOLEAN DEFAULT FALSE, - "notice_title" VARCHAR(255) -); - -CREATE TABLE "diary" ( - "diary_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, - "user_id" BIGINT NOT NULL, - "diary_title" VARCHAR(50) NOT NULL, - "diary_title_image" VARCHAR(200) DEFAULT NULL, - "diary_start_date" DATETIME NOT NULL, - "diary_end_date" DATETIME NOT NULL, - "diary_created_date" DATETIME NOT NULL, - "diary_edited_date" DATETIME DEFAULT NULL -); \ No newline at end of file +CREATE TABLE "user_image" +( + "user_image_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_image_address" VARCHAR(200) NOT NULL, + "user_image_created_date" DATE NOT NULL +); + +CREATE TABLE "user" +( + "user_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_image_id" BIGINT NOT NULL, + "user_status_id" VARCHAR(20) NOT NULL, + "user_oauth_id" VARCHAR(100), + "provider" VARCHAR(10), + "user_nickname" VARCHAR(30), + "user_name" VARCHAR(20), + "user_age" INT, + "user_sex" VARCHAR(10), + "user_email" VARCHAR(30), + "user_phone_number" VARCHAR(13), + "is_admin" BOOLEAN NOT NULL, + "user_latest_login_at" DATETIME, + "user_created_at" DATETIME NOT NULL, + "user_deleted_at" DATETIME, + FOREIGN KEY ("user_image_id") REFERENCES "user_image" ("user_image_id") +); + +CREATE TABLE "token" +( + "token_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "refresh_token" VARCHAR(250) NOT NULL, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") +); + +CREATE TABLE "place" +( + "place_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "place_search_id" VARCHAR(30), + "place_name" VARCHAR(30) NOT NULL, + "place_x_axis" DECIMAL(10, 7) NOT NULL, + "place_y_axis" DECIMAL(10, 7) NOT NULL, + "place_address" VARCHAR(50) NOT NULL +); + +CREATE TABLE "zone_category" +( + "zone_category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "parent_zone_category_id" BIGINT, + "zone_category_name" VARCHAR(20) NOT NULL, + FOREIGN KEY ("parent_zone_category_id") REFERENCES "zone_category" ("zone_category_id") +); + +CREATE TABLE "category" +( + "category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "parent_category_id" BIGINT, + "category_name" VARCHAR(20) NOT NULL, + FOREIGN KEY ("parent_category_id") REFERENCES "category" ("category_id") +); + +CREATE TABLE "gathering_category" +( + "gathering_category_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "gathering_category_name" VARCHAR(20) NOT NULL +); + +CREATE TABLE "information" +( + "information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "category_id" BIGINT NOT NULL, + "zone_category_id" BIGINT NOT NULL, + "user_id" BIGINT NOT NULL, + "place_id" BIGINT NOT NULL, + "information_title" VARCHAR(50) NOT NULL, + "information_address" VARCHAR(50) NOT NULL, + "information_created_date" DATETIME NOT NULL, + "information_view_count" INT NOT NULL DEFAULT 0, + "information_content" TEXT, + "information_tip" TEXT, + FOREIGN KEY ("category_id") REFERENCES "category" ("category_id"), + FOREIGN KEY ("zone_category_id") REFERENCES "zone_category" ("zone_category_id"), + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("place_id") REFERENCES "place" ("place_id") +); + +CREATE TABLE "gathering" +( + "gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "zone_category_id" BIGINT NOT NULL, + "gathering_category_id" BIGINT NOT NULL, + "place_id" BIGINT NOT NULL, + "gathering_title" VARCHAR(50), + "gathering_content" TEXT, + "gathering_person_count" INT, + "gathering_view_count" INT, + "gathering_created_at" DATETIME, + "gathering_edited_at" DATETIME, + "gathering_schedule_start_date" DATETIME, + "gathering_schedule_end_date" DATETIME, + "gathering_is_finish" BOOLEAN, + "gathering_deadline" DATETIME, + "gathering_allowed_sex" VARCHAR(30) NOT NULL, + "gathering_start_age" INT NOT NULL, + "gathering_end_age" INT NOT NULL, + "gathering_is_deleted" BOOLEAN NOT NULL DEFAULT FALSE, + "gathering_open_chatting_url" VARCHAR(255), + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("gathering_category_id") REFERENCES "gathering_category" ("gathering_category_id"), + FOREIGN KEY ("zone_category_id") REFERENCES "zone_category" ("zone_category_id"), + FOREIGN KEY ("place_id") REFERENCES "place" ("place_id") +); + +CREATE TABLE "gathering_applicants" +( + "gathering_applicants_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "gathering_id" BIGINT NOT NULL, + "user_id" BIGINT NOT NULL, + "gathering_applicants_state" VARCHAR(20) NOT NULL, + FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") +); + +CREATE TABLE "image" +( + "image_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "image_status_id" VARCHAR(20) NOT NULL, + "information_id" BIGINT NOT NULL, + "image_address" VARCHAR(200) NOT NULL, + "image_created_date" DATE NOT NULL, + FOREIGN KEY ("information_id") REFERENCES "information" ("information_id") +); + +CREATE TABLE "great_information" +( + "great_information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "information_id" BIGINT NOT NULL, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), + UNIQUE ("user_id", "information_id") +); + +CREATE TABLE "great_gathering" +( + "great_gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "gathering_id" BIGINT NOT NULL, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), + UNIQUE ("user_id", "gathering_id") +); + +CREATE TABLE "book_mark_information" +( + "book_mark_information_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "information_id" BIGINT NOT NULL, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), + UNIQUE ("user_id", "information_id") +); + +CREATE TABLE "book_mark_gathering" +( + "book_mark_gathering_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "gathering_id" BIGINT NOT NULL, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"), + FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), + UNIQUE ("user_id", "gathering_id") +); + +CREATE TABLE "tag" +( + "tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "tag_name" VARCHAR(16) NOT NULL +); + +CREATE TABLE "info_tag" +( + "info_tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "tag_id" BIGINT NOT NULL, + "information_id" BIGINT NOT NULL, + FOREIGN KEY ("tag_id") REFERENCES "tag" ("tag_id"), + FOREIGN KEY ("information_id") REFERENCES "information" ("information_id"), + UNIQUE ("tag_id", "information_id") +); + +CREATE TABLE "gathering_tag" +( + "gathering_tag_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "tag_id" BIGINT NOT NULL, + "gathering_id" BIGINT NOT NULL, + FOREIGN KEY ("tag_id") REFERENCES "tag" ("tag_id"), + FOREIGN KEY ("gathering_id") REFERENCES "gathering" ("gathering_id"), + UNIQUE ("tag_id", "gathering_id") +); + +CREATE TABLE "banner" +( + "id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "name" VARCHAR(255) NOT NULL, + "url" VARCHAR(255) NOT NULL +); + +CREATE TABLE "qna" +( + "qna_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "qna_category_name" VARCHAR(255), + "qna_created_at" DATETIME, + "qna_status" VARCHAR(255), + "qna_title" VARCHAR(255), + "qna_updated_at" DATETIME, + "user_id" BIGINT, + FOREIGN KEY ("user_id") REFERENCES "user" ("user_id") +); + +CREATE TABLE "qna_message" +( + "id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "qna_message_content" TEXT, + "qna_message_created_at" DATETIME, + "qna_message_user_id" BIGINT, + "qna_id" BIGINT, + FOREIGN KEY ("qna_id") REFERENCES "qna" ("qna_id"), + FOREIGN KEY ("qna_message_user_id") REFERENCES "user" ("user_id") +); + +CREATE TABLE "notice" +( + "notice_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "notice_category_name" VARCHAR(255), + "notice_content" TEXT, + "notice_created_at" DATETIME, + "notice_is_deleted" BOOLEAN DEFAULT FALSE, + "notice_title" VARCHAR(255) +); + +CREATE TABLE "diary" +( + "diary_id" BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + "user_id" BIGINT NOT NULL, + "diary_title" VARCHAR(50) NOT NULL, + "diary_title_image" VARCHAR(200) DEFAULT NULL, + "diary_start_date" DATETIME NOT NULL, + "diary_end_date" DATETIME NOT NULL, + "diary_created_date" DATETIME NOT NULL, + "diary_edited_date" DATETIME DEFAULT NULL +); + +CREATE TABLE `term` +( + `term_id` BIGINT NOT NULL AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `term_condition_agreement` BOOLEAN NOT NULL, + `term_privacy_agreement` BOOLEAN NOT NULL, + `term_created_at` DATETIME NOT NULL, + PRIMARY KEY (`term_id`), + CONSTRAINT `FK_term_TO_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) +); diff --git a/src/test/java/solitour_backend/solitour/information/controller/InformationControllerTest.java b/src/test/java/solitour_backend/solitour/information/controller/InformationControllerTest.java new file mode 100644 index 0000000..f85f4be --- /dev/null +++ b/src/test/java/solitour_backend/solitour/information/controller/InformationControllerTest.java @@ -0,0 +1,42 @@ +package solitour_backend.solitour.information.controller; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import solitour_backend.solitour.information.service.InformationService; + +import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.modifyUris; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; + +@WebMvcTest(InformationController.class) +@ExtendWith({MockitoExtension.class, RestDocumentationExtension.class}) +class InformationControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private InformationService informationService; + + @BeforeEach + void setUp(WebApplicationContext webApplicationContext, + RestDocumentationContextProvider restDocumentation) { + + this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) + .apply(documentationConfiguration(restDocumentation) + .operationPreprocessors() + .withRequestDefaults(modifyUris(), prettyPrint()) + .withResponseDefaults(prettyPrint())) + .build(); + } +} \ No newline at end of file