Skip to content

Commit 7d806cc

Browse files
author
Lee Euije
authored
YEL-98 [feat] 구독 연장 유도 필요 여부 확인 API 추가
YEL-98 [feat] 구독 연장 유도 필요 여부 확인 API 추가
2 parents d02cd81 + 9258e83 commit 7d806cc

File tree

12 files changed

+256
-2
lines changed

12 files changed

+256
-2
lines changed

src/main/java/com/yello/server/domain/purchase/controller/PurchaseController.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
package com.yello.server.domain.purchase.controller;
22

3+
import static com.yello.server.global.common.SuccessCode.USER_SUBSCRIBE_NEEDED_READ_SUCCESS;
4+
5+
import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse;
36
import com.yello.server.domain.purchase.service.PurchaseService;
7+
import com.yello.server.domain.user.entity.User;
8+
import com.yello.server.global.common.annotation.AccessTokenUser;
9+
import com.yello.server.global.common.dto.BaseResponse;
10+
import io.swagger.v3.oas.annotations.Operation;
11+
import io.swagger.v3.oas.annotations.media.Content;
12+
import io.swagger.v3.oas.annotations.media.Schema;
13+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
414
import io.swagger.v3.oas.annotations.tags.Tag;
15+
import java.time.LocalDateTime;
516
import lombok.RequiredArgsConstructor;
17+
import lombok.val;
18+
import org.springframework.web.bind.annotation.GetMapping;
619
import org.springframework.web.bind.annotation.RequestMapping;
720
import org.springframework.web.bind.annotation.RestController;
821

@@ -14,4 +27,15 @@ public class PurchaseController {
1427

1528
private final PurchaseService purchaseService;
1629

30+
@Operation(summary = "구독 연장 유도 필요 여부 확인 API", responses = {
31+
@ApiResponse(
32+
responseCode = "200",
33+
content = @Content(mediaType = "application/json", schema = @Schema(implementation = UserSubscribeNeededResponse.class))
34+
)
35+
})
36+
@GetMapping("/subscribe_need")
37+
public BaseResponse<UserSubscribeNeededResponse> getUserSubscribeNeeded(@AccessTokenUser User user) {
38+
val data = purchaseService.getUserSubscribe(user, LocalDateTime.now());
39+
return BaseResponse.success(USER_SUBSCRIBE_NEEDED_READ_SUCCESS, data);
40+
}
1741
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.yello.server.domain.purchase.dto.response;
2+
3+
import com.yello.server.domain.user.entity.Subscribe;
4+
import com.yello.server.domain.user.entity.User;
5+
import lombok.Builder;
6+
7+
@Builder
8+
public record UserSubscribeNeededResponse(
9+
Subscribe subscribe,
10+
Boolean isSubscribeNeeded
11+
) {
12+
13+
public static UserSubscribeNeededResponse of(User user, Boolean isSubscribeNeeded) {
14+
return UserSubscribeNeededResponse.builder()
15+
.subscribe(user.getSubscribe())
16+
.isSubscribeNeeded(isSubscribeNeeded)
17+
.build();
18+
}
19+
}

src/main/java/com/yello/server/domain/purchase/entity/Purchase.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
import javax.persistence.ManyToOne;
1414
import lombok.AccessLevel;
1515
import lombok.AllArgsConstructor;
16-
import lombok.Builder;
1716
import lombok.Getter;
1817
import lombok.NoArgsConstructor;
18+
import lombok.experimental.SuperBuilder;
19+
import org.hibernate.annotations.DynamicInsert;
1920

2021
@Entity
2122
@Getter
22-
@Builder
23+
@SuperBuilder
24+
@DynamicInsert
2325
@AllArgsConstructor
2426
@NoArgsConstructor(access = AccessLevel.PROTECTED)
2527
public class Purchase extends AuditingTimeEntity {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package com.yello.server.domain.purchase.repository;
22

3+
import com.yello.server.domain.purchase.entity.ProductType;
34
import com.yello.server.domain.purchase.entity.Purchase;
5+
import com.yello.server.domain.user.entity.User;
6+
import java.util.List;
7+
import java.util.Optional;
48
import org.springframework.data.jpa.repository.JpaRepository;
59

610
public interface PurchaseJpaRepository extends JpaRepository<Purchase, Long> {
711

12+
List<Purchase> findAllByUser(User user);
13+
14+
Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user, ProductType productType);
815
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
package com.yello.server.domain.purchase.repository;
22

3+
import com.yello.server.domain.purchase.entity.ProductType;
4+
import com.yello.server.domain.purchase.entity.Purchase;
5+
import com.yello.server.domain.user.entity.User;
6+
import java.util.List;
7+
import java.util.Optional;
8+
39
public interface PurchaseRepository {
410

11+
Purchase save(Purchase purchase);
12+
13+
Optional<Purchase> findById(Long purchaseId);
14+
15+
List<Purchase> findAllByUser(User user);
16+
17+
Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user, ProductType productType);
518
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
package com.yello.server.domain.purchase.repository;
22

3+
import com.yello.server.domain.purchase.entity.ProductType;
4+
import com.yello.server.domain.purchase.entity.Purchase;
5+
import com.yello.server.domain.user.entity.User;
6+
import java.util.List;
7+
import java.util.Optional;
38
import lombok.RequiredArgsConstructor;
49
import org.springframework.stereotype.Repository;
510

611
@Repository
712
@RequiredArgsConstructor
813
public class PurchaseRepositoryImpl implements PurchaseRepository {
914

15+
public final PurchaseJpaRepository purchaseJpaRepository;
16+
17+
@Override
18+
public Purchase save(Purchase purchase) {
19+
return purchaseJpaRepository.save(purchase);
20+
}
21+
22+
@Override
23+
public Optional<Purchase> findById(Long purchaseId) {
24+
return purchaseJpaRepository.findById(purchaseId);
25+
}
26+
27+
@Override
28+
public List<Purchase> findAllByUser(User user) {
29+
return purchaseJpaRepository.findAllByUser(user);
30+
}
31+
32+
@Override
33+
public Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user, ProductType productType) {
34+
return purchaseJpaRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc(user, productType);
35+
}
1036
}

src/main/java/com/yello/server/domain/purchase/service/PurchaseService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
package com.yello.server.domain.purchase.service;
22

3+
import com.yello.server.domain.purchase.dto.response.UserSubscribeNeededResponse;
4+
import com.yello.server.domain.purchase.entity.ProductType;
5+
import com.yello.server.domain.purchase.entity.Purchase;
36
import com.yello.server.domain.purchase.repository.PurchaseRepository;
7+
import com.yello.server.domain.user.entity.Subscribe;
8+
import com.yello.server.domain.user.entity.User;
49
import com.yello.server.domain.user.repository.UserRepository;
10+
import java.time.Duration;
11+
import java.time.LocalDateTime;
12+
import java.util.Optional;
13+
import lombok.Builder;
514
import lombok.RequiredArgsConstructor;
615
import org.springframework.stereotype.Service;
716
import org.springframework.transaction.annotation.Transactional;
817

18+
@Builder
919
@Service
1020
@RequiredArgsConstructor
1121
@Transactional(readOnly = true)
@@ -14,4 +24,13 @@ public class PurchaseService {
1424
private final UserRepository userRepository;
1525
private final PurchaseRepository purchaseRepository;
1626

27+
public UserSubscribeNeededResponse getUserSubscribe(User user, LocalDateTime time) {
28+
final Optional<Purchase> mostRecentPurchase = purchaseRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc(
29+
user, ProductType.YELLO_PLUS);
30+
final Boolean isSubscribeNeeded = user.getSubscribe() == Subscribe.CANCELED
31+
&& mostRecentPurchase.isPresent()
32+
&& Duration.between(mostRecentPurchase.get().getCreatedAt(), time).getSeconds() < 1 * 24 * 60 * 60;
33+
34+
return UserSubscribeNeededResponse.of(user, isSubscribeNeeded);
35+
}
1736
}

src/main/java/com/yello/server/domain/user/service/UserService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.yello.server.domain.cooldown.repository.CooldownRepository;
55
import com.yello.server.domain.friend.entity.Friend;
66
import com.yello.server.domain.friend.repository.FriendRepository;
7+
import com.yello.server.domain.purchase.repository.PurchaseRepository;
78
import com.yello.server.domain.user.dto.response.UserDetailResponse;
89
import com.yello.server.domain.user.dto.response.UserResponse;
910
import com.yello.server.domain.user.entity.User;
@@ -26,6 +27,7 @@ public class UserService {
2627
private final VoteRepository voteRepository;
2728
private final CooldownRepository cooldownRepository;
2829
private final TokenRepository tokenRepository;
30+
private final PurchaseRepository purchaseRepository;
2931

3032
public UserDetailResponse findMyProfile(Long userId) {
3133
final User user = userRepository.getById(userId);

src/main/java/com/yello/server/global/common/SuccessCode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public enum SuccessCode {
1818
YELLOID_VALIDATION_SUCCESS(OK, "옐로 아이디 중복 여부 조회에 성공했습니다."),
1919
READ_FRIEND_SUCCESS(OK, "친구 조회에 성공했습니다."),
2020
READ_USER_SUCCESS(OK, "유저 조회에 성공했습니다."),
21+
USER_SUBSCRIBE_NEEDED_READ_SUCCESS(OK, "유저 구독 연장 유도 필요 여부 확인 조회에 성공하였습니다."),
2122
ADD_FRIEND_SUCCESS(OK, "친구 추가에 성공했습니다."),
2223
SHUFFLE_FRIEND_SUCCESS(OK, "친구 셔플에 성공했습니다."),
2324
CHECK_KEYWORD_SUCCESS(OK, "키워드 확인에 성공했습니다."),
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.yello.server.small.domain.purchase;
2+
3+
import com.yello.server.domain.purchase.entity.ProductType;
4+
import com.yello.server.domain.purchase.entity.Purchase;
5+
import com.yello.server.domain.purchase.repository.PurchaseRepository;
6+
import com.yello.server.domain.user.entity.User;
7+
import java.util.ArrayList;
8+
import java.util.Comparator;
9+
import java.util.List;
10+
import java.util.Objects;
11+
import java.util.Optional;
12+
13+
public class FakePurchaseRepository implements PurchaseRepository {
14+
15+
private final List<Purchase> data = new ArrayList<>();
16+
private Long id = 0L;
17+
18+
19+
@Override
20+
public Purchase save(Purchase purchase) {
21+
if (purchase.getId() != null && purchase.getId() > id) {
22+
id = purchase.getId();
23+
}
24+
25+
final Purchase newPurchase = Purchase.builder()
26+
.id(purchase.getId() == null ? ++id : purchase.getId())
27+
.price(purchase.getPrice())
28+
.user(purchase.getUser())
29+
.gateway(purchase.getGateway())
30+
.productType(purchase.getProductType())
31+
.createdAt(purchase.getCreatedAt())
32+
.updatedAt(purchase.getUpdatedAt())
33+
.build();
34+
35+
data.add(newPurchase);
36+
return newPurchase;
37+
}
38+
39+
@Override
40+
public Optional<Purchase> findById(Long purchaseId) {
41+
return data.stream()
42+
.filter(purchase -> Objects.equals(purchase.getId(), purchaseId))
43+
.findFirst();
44+
}
45+
46+
@Override
47+
public List<Purchase> findAllByUser(User user) {
48+
return data.stream()
49+
.filter(purchase -> purchase.getUser().equals(user))
50+
.toList();
51+
}
52+
53+
@Override
54+
public Optional<Purchase> findTopByUserAndProductTypeOrderByCreatedAtDesc(User user, ProductType productType) {
55+
return data.stream()
56+
.filter(purchase -> {
57+
return purchase.getUser().getId().equals(user.getId())
58+
&& purchase.getProductType().equals(productType);
59+
}
60+
)
61+
.sorted(Comparator.comparing(Purchase::getCreatedAt).reversed())
62+
.findFirst();
63+
}
64+
}

0 commit comments

Comments
 (0)