Skip to content

Commit

Permalink
feat: 포인트 기능 추가 (#32)
Browse files Browse the repository at this point in the history
* feat : 게시글 열람 작성할떄 포인트 로직 생성

* refactor : 좋아요 마이페이지 조건 수정

* feat : 유저별포인트 리스트 출력 API

* refactor : user가 가진 Point 도 추가

* docs : 포인트 리스트 API 문서정리

* docs : 자료실 정보가져오기 문서 수정
  • Loading branch information
MyunghyunNero authored Nov 20, 2023
1 parent 11840b3 commit 118a55c
Show file tree
Hide file tree
Showing 15 changed files with 429 additions and 68 deletions.
4 changes: 3 additions & 1 deletion src/main/java/kusitms/gallae/config/BaseResponseStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public enum BaseResponseStatus {
FORBIDDEN(false, HttpStatus.FORBIDDEN, 403, "권한이 없습니다."),
NOT_FOUND(false, HttpStatus.NOT_FOUND, 404, "대상을 찾을 수 없습니다."),

ALEADY_EXIST(false, HttpStatus.BAD_REQUEST, 410, "이미 존재합니다.");
ALEADY_EXIST(false, HttpStatus.BAD_REQUEST, 410, "이미 존재합니다."),

POINT_TRIBE(false, HttpStatus.BAD_REQUEST, 1001, "포인트가 부족합니다.");

private final boolean isSuccess;
@JsonIgnore
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/kusitms/gallae/config/SpringSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ public SecurityFilterChain SecurityFilterChain(HttpSecurity httpSecurity) throws
.authorizeHttpRequests()
.requestMatchers("/manager/**").hasRole(Role.MANAGER.getValue())
.requestMatchers("/reviews/saveReview").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/reviews/detail").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/archives/saveArchive").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/archives/detail").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/favorite/**").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/users/myPosts/**").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.requestMatchers("/point/list/**").hasAnyRole(Role.USER.getValue(),Role.MANAGER.getValue())
.anyRequest().permitAll().and()
.exceptionHandling()
.authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/kusitms/gallae/controller/ArchiveController.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ public ResponseEntity<BaseResponse<Long>> saveArchive(

}

@Operation(summary = "자료실 정보 가져오기", description = """
포인트가 부족하면
\n
"isSuccess": false,\n
"code": 1001,\n
"message": "포인트가 부족합니다."\n
이 반환합니다.
\n
로그인한 유저는 포인트 15포인트 차감되고 포인트 컬럼 생성됩니다.\n
*주의* 자료실 작성한 유저가 열람 할때는 포인트 차감이 되지 않습니다.
""")
@GetMapping("/detail")
public ResponseEntity<BaseResponse<ArchiveDetailRes>> getArchiveDetail(
Principal principal,
Expand Down
72 changes: 72 additions & 0 deletions src/main/java/kusitms/gallae/controller/PointController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package kusitms.gallae.controller;


import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Positive;
import kusitms.gallae.config.BaseResponse;
import kusitms.gallae.domain.Program;
import kusitms.gallae.dto.point.PointPageListRes;
import kusitms.gallae.dto.program.ProgramManagerReq;
import kusitms.gallae.dto.program.ProgramPageMangagerRes;
import kusitms.gallae.service.point.PointService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;

@RequiredArgsConstructor
@RestController
@RequestMapping("/point")
public class PointController {

@Autowired
private PointService pointService;


@Operation(summary = "사용자별 포인트 목록 가져오기", description = """
로그인이 되어있어야합니다.\n
type : 적립/사용 -> null이면 전체 \n
period: 1주일/한달/3개월/6개월/1년 -> null이면 전체\n
반환에서 userPoint는 현재 유저가 가지고있는 포인트
totalpage 가 1인 것은 말그대로 페이지 1밖에 없다는 뜻
size를 10으로 주고 데이터가 92개 이면 페이지는 totalpage는 10
10*9 9개와 나머지 2개를 가진 1페이지
""")
@GetMapping("/list")
public ResponseEntity<BaseResponse<PointPageListRes>> findProgramManagerProgress(
Principal principal,

@Parameter(description = "타입",example = "적립,사용")
@RequestParam(value = "type", required = false)
String type,

@Parameter(description = "기간",example = "1주일,1달,3개월,6개월,1년")
@RequestParam(value = "period", required = false)
String period,

@Parameter(description = "페이지 번호")
@Positive(message = "must be greater than 0")
@RequestParam(value = "page", defaultValue = "0")
Integer pageNumber,

@Parameter(description = "페이징 사이즈 (최대 100)")
@Min(value = 1, message = "must be greater than or equal to 1")
@Max(value = 100, message = "must be less than or equal to 100")
@RequestParam(value = "size", defaultValue = "20")
Integer pagingSize
){
PageRequest pageRequest = PageRequest.of(pageNumber,pagingSize);
return ResponseEntity.ok(new BaseResponse<>(this.pointService.getPointList(type,period,
principal.getName(),pageRequest)));
}
}
18 changes: 13 additions & 5 deletions src/main/java/kusitms/gallae/controller/ReviewController.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ public ResponseEntity<BaseResponse<Long>> saveReview(

}


@Operation(summary = "지원후기 정보 가져오기", description = """
포인트가 부족하면
\n
"isSuccess": false,\n
"code": 1001,\n
"message": "포인트가 부족합니다."\n
이 반환합니다.
\n
로그인한 유저는 포인트 10포인트 차감되고 포인트 컬럼 생성됩니다.\n
*주의* 지원후기 작성한 유저가 열람 할때는 포인트 차감이 되지 않습니다.
""")
@GetMapping("/detail")
public ResponseEntity<BaseResponse<ReviewDetailRes>> getReviewDetail(
Principal principal,
Expand All @@ -100,11 +112,7 @@ public ResponseEntity<BaseResponse<ReviewDetailRes>> getReviewDetail(
@RequestParam(value = "reviewId", required = false)
Long reviewId
) {
String username = null;
if(principal != null) {
username = principal.getName();
}
ReviewDetailRes reviewDetail = reviewService.getReviewById(reviewId, username);
ReviewDetailRes reviewDetail = reviewService.getReviewById(reviewId, principal.getName());
return ResponseEntity.ok(new BaseResponse<>(reviewDetail));
}

Expand Down
11 changes: 9 additions & 2 deletions src/main/java/kusitms/gallae/domain/Point.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

@Entity
@Table(name = "points")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Setter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class Point {
@Id
Expand All @@ -34,4 +37,8 @@ public class Point {
@ManyToOne
@JoinColumn(name = "user_id")
private User user;

@Column
@CreationTimestamp
private LocalDateTime createdAt;
}
26 changes: 26 additions & 0 deletions src/main/java/kusitms/gallae/dto/point/PointListRes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package kusitms.gallae.dto.point;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.time.LocalDate;
import java.time.LocalTime;

@Data
public class PointListRes {


private Long id;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
private LocalDate date;

@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "HH:mm:ss", timezone = "Asia/Seoul")
private LocalTime time;

private String type;

private String activityDetails;

private Integer pointScore;
}
17 changes: 17 additions & 0 deletions src/main/java/kusitms/gallae/dto/point/PointPageListRes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package kusitms.gallae.dto.point;


import lombok.Data;

import java.util.List;

@Data
public class PointPageListRes {

private Integer totalPage;

private Long userPoint;

private List<PointListRes> points;

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ private BooleanBuilder createFavoriteCondition(FavoriteSearchReq favoriteSearchR
}

if(favoriteSearchReq.getStatus() != null){
booleanBuilder.and(program.status.eq(Program.ProgramStatus.FINISH));
}else{
booleanBuilder.and(program.status.eq(Program.ProgramStatus.SAVE));
if(favoriteSearchReq.getStatus().contains("모집 중")) {
booleanBuilder.and(program.status.eq(Program.ProgramStatus.SAVE));
}else{
booleanBuilder.and(program.status.eq(Program.ProgramStatus.FINISH));
}
}

return booleanBuilder;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kusitms.gallae.repository.point;

import kusitms.gallae.domain.Point;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PointRepository extends JpaRepository<Point, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package kusitms.gallae.repository.point;

import kusitms.gallae.domain.Point;
import kusitms.gallae.domain.User;
import kusitms.gallae.dto.program.ProgramMainRes;
import kusitms.gallae.dto.program.ProgramSearchReq;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface PointRepositoryCustom {
Page<Point> getDynamicPoint(User user, String type, String period, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package kusitms.gallae.repository.point;


import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.Wildcard;
import com.querydsl.jpa.impl.JPAQueryFactory;
import kusitms.gallae.domain.Point;
import kusitms.gallae.domain.User;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static kusitms.gallae.domain.QPoint.point;
import static kusitms.gallae.domain.QProgram.program;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Repository
public class PointRepositoryImpl implements PointRepositoryCustom{

private final JPAQueryFactory jpaQueryFactory;


@Override
public Page<Point> getDynamicPoint(User user, String type, String period, Pageable pageable ){
List<Point> points = this.jpaQueryFactory
.select(point)
.from(point)
.where(createPointCondition(user, type, period))
.orderBy(new OrderSpecifier<>(Order.DESC,point.createdAt))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

Long totalSize = this.jpaQueryFactory
.select(Wildcard.count)
.from(point)
.where(createPointCondition(user, type,period))
.fetchOne();

return new PageImpl<>(points, pageable , Objects.requireNonNull(totalSize));
}

private BooleanBuilder createPointCondition(User user, String type, String period) {
BooleanBuilder booleanBuilder = new BooleanBuilder();
booleanBuilder.and(point.user.eq(user));
if(type != null) {
booleanBuilder.and(point.pointCategory.contains(type));
}

if(period != null) {
LocalDateTime now = LocalDateTime.now();
if(period.contains("1주일")) {
booleanBuilder.and(point.createdAt.goe(now.minusDays(7)));
}else if(period.contains("1달")){
booleanBuilder.and(point.createdAt.goe(now.minusMonths(1)));
}else if(period.contains("3개월")) {
booleanBuilder.and(point.createdAt.goe(now.minusMonths(3)));
}else if(period.contains("6개월")) {
booleanBuilder.and(point.createdAt.goe(now.minusMonths(6)));
}else{
booleanBuilder.and(point.createdAt.goe(now.minusYears(1)));
}
}
return booleanBuilder;
}
}
Loading

0 comments on commit 118a55c

Please sign in to comment.