Skip to content

Commit

Permalink
YEL-183 [feat] 유저 구독 정보 조회 API
Browse files Browse the repository at this point in the history
YEL-183 [feat] 유저 구독 정보 조회 API
  • Loading branch information
hyeonjeongs authored Jan 23, 2024
2 parents a17874e + 6bd30a0 commit edd14b1
Show file tree
Hide file tree
Showing 31 changed files with 340 additions and 67 deletions.
29 changes: 29 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}

plugins {
id 'java'
id 'org.springframework.boot' version '2.7.4'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id "org.asciidoctor.jvm.convert" version "3.3.2"
id 'jacoco'
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

group = 'com.yello'
Expand Down Expand Up @@ -88,6 +95,11 @@ dependencies {

// AOP
implementation 'org.springframework.boot:spring-boot-starter-aop'

// querydsl
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
implementation "com.querydsl:querydsl-core:${queryDslVersion}"
}

asciidoctor {
Expand All @@ -112,6 +124,7 @@ configurations {
compileOnly {
extendsFrom annotationProcessor
}
querydsl.extendsFrom compileClasspath
}

jar.enabled = false
Expand All @@ -128,6 +141,22 @@ jacocoTestReport {
}
// finalizedBy 'jacocoTestCoverageVerification'
}

// QueryDsl
def querydslDir = "$buildDir/generated/querydsl"

querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}

compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}

//jacocoTestCoverageVerification {
// violationRules {
// rule {
Expand Down
2 changes: 1 addition & 1 deletion src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@

=== Purchase API

* 🆕 link:purchase-info.html[유저 구독 정보 (명세), 2024-01-09]
* 🆕 link:purchase-info.html[유저 구독 정보, 2024-01-23]

* link:apple.html[Apple 결제 관련 API]

Expand Down
3 changes: 2 additions & 1 deletion src/docs/asciidoc/purchase-info.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
== 유저 구독 정보 (명세)
== 유저 구독 정보

=== 요청

Expand Down Expand Up @@ -40,4 +40,5 @@ Content-Type: application/json

=== CHANGELOG

- 2024.01.23 API 릴리즈
- 2024.01.09 명세 작성
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.yello.server.domain.notice.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import com.yello.server.domain.notice.entity.Notice;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -10,6 +13,7 @@
public class NoticeRepositoryImpl implements NoticeRepository {

private final NoticeJpaRepository noticeJpaRepository;
private final JPAQueryFactory jpaQueryFactory;


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface PurchaseJpaRepository extends JpaRepository<Purchase, Long> {

Expand All @@ -17,4 +19,11 @@ public interface PurchaseJpaRepository extends JpaRepository<Purchase, Long> {

Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user,
ProductType productType);

@Query("select p from Purchase p "
+ "where p.state = 'active' "
+ "and p.user = :user "
+ "and p.productType = 'yello_plus' "
+ "order by p.updatedAt DESC")
Optional<Purchase> findTopByStateAndUser(@Param("user") User user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user,
ProductType productType);

void delete(Purchase purchase);

Purchase getTopByStateAndUserId(User user);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.yello.server.domain.purchase.repository;

import static com.yello.server.global.common.ErrorCode.NOT_FOUND_USER_SUBSCRIBE_EXCEPTION;

import com.yello.server.domain.purchase.entity.ProductType;
import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.purchase.exception.PurchaseNotFoundException;
import com.yello.server.domain.user.entity.User;
import com.yello.server.global.common.ErrorCode;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -50,4 +54,10 @@ public Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User u
public void delete(Purchase purchase) {
purchaseJpaRepository.delete(purchase);
}

@Override
public Purchase getTopByStateAndUserId(User user) {
return purchaseJpaRepository.findTopByStateAndUser(user)
.orElseThrow(() -> new PurchaseNotFoundException(NOT_FOUND_USER_SUBSCRIBE_EXCEPTION));
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.yello.server.domain.user.controller;

import static com.yello.server.global.common.SuccessCode.DELETE_USER_SUCCESS;
import static com.yello.server.global.common.SuccessCode.READ_USER_SUBSCRIBE_SUCCESS;
import static com.yello.server.global.common.SuccessCode.READ_USER_SUCCESS;
import static com.yello.server.global.common.SuccessCode.UPDATE_DEVICE_TOKEN_USER_SUCCESS;

import com.yello.server.domain.user.dto.request.UserDeviceTokenRequest;
import com.yello.server.domain.user.dto.response.UserDetailResponse;
import com.yello.server.domain.user.dto.response.UserDetailV2Response;
import com.yello.server.domain.user.dto.response.UserResponse;
import com.yello.server.domain.user.dto.response.UserSubscribeDetailResponse;
import com.yello.server.domain.user.entity.User;
import com.yello.server.domain.user.service.UserService;
import com.yello.server.global.common.annotation.AccessTokenUser;
Expand Down Expand Up @@ -62,4 +64,10 @@ public BaseResponse deleteUser(@AccessTokenUser User user) {
userService.delete(user);
return BaseResponse.success(DELETE_USER_SUCCESS);
}

@GetMapping("/v1/user/subscribe")
public BaseResponse<UserSubscribeDetailResponse> getUserSubscribe(@AccessTokenUser User user) {
val data = userService.getUserSubscribe(user.getId());
return BaseResponse.success(READ_USER_SUBSCRIBE_SUCCESS, data);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.yello.server.domain.user.dto.response;

import static com.yello.server.global.common.factory.TimeFactory.toYearAndMonthFormattedString;

import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.user.entity.Subscribe;
import com.yello.server.domain.user.entity.User;
import lombok.Builder;

@Builder
public record UserSubscribeDetailResponse(
Long id,
Subscribe subscribe,
String expiredData
) {
public static UserSubscribeDetailResponse of(Purchase purchase) {
return UserSubscribeDetailResponse.builder()
.id(purchase.getUser().getId())
.subscribe(purchase.getUser().getSubscribe())
.expiredData(toYearAndMonthFormattedString(purchase.getUpdatedAt()))
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import com.yello.server.domain.friend.entity.Friend;
import com.yello.server.domain.friend.repository.FriendRepository;
import com.yello.server.domain.group.repository.UserGroupRepository;
import com.yello.server.domain.purchase.entity.Purchase;
import com.yello.server.domain.purchase.repository.PurchaseRepository;
import com.yello.server.domain.user.dto.request.UserDeviceTokenRequest;
import com.yello.server.domain.user.dto.response.UserDetailResponse;
import com.yello.server.domain.user.dto.response.UserDetailV2Response;
import com.yello.server.domain.user.dto.response.UserResponse;
import com.yello.server.domain.user.dto.response.UserSubscribeDetailResponse;
import com.yello.server.domain.user.entity.User;
import com.yello.server.domain.user.exception.UserConflictException;
import com.yello.server.domain.user.repository.UserRepository;
Expand Down Expand Up @@ -89,4 +91,11 @@ public void delete(User user) {
cooldownRepository.findByUserId(target.getId())
.ifPresent(Cooldown::delete);
}

public UserSubscribeDetailResponse getUserSubscribe(Long userId) {
final User user = userRepository.getById(userId);
final Purchase purchase = purchaseRepository.getTopByStateAndUserId(user);

return UserSubscribeDetailResponse.of(purchase);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public enum ErrorCode {
USER_ADMIN_NOT_FOUND_EXCEPTION(NOT_FOUND, "해당 Admin이 존재하지 않습니다."),
NOT_EQUAL_TRANSACTION_EXCEPTION(NOT_FOUND, "동일하지 않은 거래입니다."),
NOT_FOUND_NOTIFICATION_TYPE_EXCEPTION(NOT_FOUND, "존재하지 않는 알림 타입 입니다"),
NOT_FOUND_USER_SUBSCRIBE_EXCEPTION(NOT_FOUND, "유저의 구독정보가 존재하지 않습니다."),

/**
* 409 CONFLICT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public enum SuccessCode {
READ_QUESTION_DETAIL_ADMIN_SUCCESS(OK, "어드민 페이지 질문 상세 조회에 성공하였습니다."),
DELETE_QUESTION_ADMIN_SUCCESS(OK, "어드민 권환으로 질문지 삭제에 성공하였습니다."),
CLASS_NAME_SEARCH_BY_SCHOOL_NAME_SCHOOL_SUCCESS(OK, "학반 검색에 성공했습니다."),
READ_USER_SUBSCRIBE_SUCCESS(OK, "구독 정보 조회에 성공하였습니다."),

/**
* 201 CREATED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ public static LocalDateTime plusTime(LocalDateTime localDateTime, int time) {
public static LocalDateTime minusTime(LocalDateTime localDateTime, int time) {
return localDateTime.minusMinutes(time);
}

public static String toYearAndMonthFormattedString(LocalDateTime localDateTime) {
if (localDateTime == null) {
return "";
}
LocalDateTime dateTimePlusSevenDays = localDateTime.plusDays(7);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
return dateTimePlusSevenDays.format(dateTimeFormatter);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.yello.server.global.configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class QueryDslConfiguration {

@PersistenceContext
private final EntityManager entityManager;

@Bean
public JPAQueryFactory queryFactory() {
return new JPAQueryFactory(entityManager);
}

}
2 changes: 1 addition & 1 deletion src/main/resources/static/docs/check-vote-available.html
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ <h3 id="_응답">응답</h3>
"data" : {
"isPossible" : false,
"point" : 200,
"createdAt" : "2024-01-19 00:36:55",
"createdAt" : "2024-01-23 22:38:13",
"friendStatus" : 1
}
}</code></pre>
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/static/docs/google.html
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ <h3 id="_응답">응답</h3>
"message" : "구글 구독 결제 검증 및 반영에 성공하였습니다.",
"data" : {
"productId" : "productId",
"expiredAt" : "2024-01-19T00:36:45.411094"
"expiredAt" : "2024-01-23T22:38:00.081341"
}
}</code></pre>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/static/docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ <h3 id="_purchase_api"><a class="link" href="#_purchase_api">Purchase API</a></h
<div class="ulist">
<ul>
<li>
<p>🆕 <a href="purchase-info.html">유저 구독 정보 (명세), 2024-01-09</a></p>
<p>🆕 <a href="purchase-info.html">유저 구독 정보, 2024-01-23</a></p>
</li>
<li>
<p><a href="apple.html">Apple 결제 관련 API</a></p>
Expand Down Expand Up @@ -643,7 +643,7 @@ <h3 id="_notice_api"><a class="link" href="#_notice_api">Notice API</a></h3>
<div id="footer">
<div id="footer-text">
Version 0.0.1-SNAPSHOT<br>
Last updated 2024-01-18 23:12:29 +0900
Last updated 2024-01-23 01:29:53 +0900
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/github.min.css">
Expand Down
9 changes: 6 additions & 3 deletions src/main/resources/static/docs/purchase-info.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<title>유저 구독 정보 (명세)</title>
<title>유저 구독 정보</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
Expand Down Expand Up @@ -441,7 +441,7 @@
</div>
<div id="content">
<div class="sect1">
<h2 id="_유저_구독_정보_명세">유저 구독 정보 (명세)</h2>
<h2 id="_유저_구독_정보">유저 구독 정보</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_요청">요청</h3>
Expand Down Expand Up @@ -506,6 +506,9 @@ <h3 id="_changelog">CHANGELOG</h3>
<div class="ulist">
<ul>
<li>
<p>2024.01.23 API 릴리즈</p>
</li>
<li>
<p>2024.01.09 명세 작성</p>
</li>
</ul>
Expand All @@ -517,7 +520,7 @@ <h3 id="_changelog">CHANGELOG</h3>
<div id="footer">
<div id="footer-text">
Version 0.0.1-SNAPSHOT<br>
Last updated 2024-01-19 00:35:48 +0900
Last updated 2024-01-23 01:26:43 +0900
</div>
</div>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import com.yello.server.domain.friend.FakeFriendRepository;
import com.yello.server.domain.friend.repository.FriendRepository;
import com.yello.server.domain.group.entity.UserGroupType;
import com.yello.server.domain.purchase.FakePurchaseRepository;
import com.yello.server.domain.purchase.repository.PurchaseRepository;
import com.yello.server.domain.question.FakeQuestionGroupTypeRepository;
import com.yello.server.domain.question.FakeQuestionRepository;
import com.yello.server.domain.question.repository.QuestionGroupTypeRepository;
Expand Down Expand Up @@ -48,12 +50,14 @@ public class AuthManagerTest {
private final UserRepository userRepository = new FakeUserRepository(friendRepository);
private final VoteRepository voteRepository = new FakeVoteRepository();
private final QuestionGroupTypeRepository questionGroupTypeRepository = new FakeQuestionGroupTypeRepository(questionRepository);
private final PurchaseRepository purchaseRepository = new FakePurchaseRepository();
private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil(
userRepository,
voteRepository,
questionRepository,
friendRepository,
questionGroupTypeRepository
questionGroupTypeRepository,
purchaseRepository
);
private AuthManager authManager;

Expand Down
Loading

0 comments on commit edd14b1

Please sign in to comment.