Skip to content

Commit

Permalink
Merge pull request #241 from Link-MIND/feature/#240
Browse files Browse the repository at this point in the history
  • Loading branch information
sss4920 authored Sep 24, 2024
2 parents 3e486f1 + c4e9509 commit 1086d1f
Show file tree
Hide file tree
Showing 19 changed files with 888 additions and 31 deletions.
107 changes: 93 additions & 14 deletions linkmind/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,36 @@ dependencies {
implementation 'mysql:mysql-connector-java:8.0.32'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

runtimeOnly 'com.h2database:h2'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-validation'
testImplementation group: 'com.h2database', name: 'h2', version: '2.2.224'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'

implementation 'io.sentry:sentry-spring-boot-starter:5.7.0'
//JWT
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2'
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2'
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'io.sentry:sentry-spring-boot-starter:5.7.0'
//JWT
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2'
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2'
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2'


// FCM
implementation 'com.google.firebase:firebase-admin:9.1.1'
implementation 'com.squareup.okhttp3:okhttp:4.10.0' // Firebase 서버로 푸시 메시지 전송 시 필요

implementation 'org.springframework.boot:spring-boot-starter-actuator'

//Query DSL
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta"
annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
implementation 'org.springframework.boot:spring-boot-starter-actuator'

//Query DSL
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta"
annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

// S3 AWS
implementation("software.amazon.awssdk:bom:2.21.0")
Expand All @@ -72,8 +80,79 @@ dependencies {
implementation 'io.sentry:sentry-spring-boot-starter:5.7.0'

}
//sourceSets {
// main {
// java {
// srcDirs = ["$projectDir/src/main/java", "$projectDir/build/generated"]
// }
// }
//}
//compileJava { options.compilerArgs << '-parameters'}


tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
// finalizedBy 'jacocoTestReport' // test가 끝나면 jacocoTestReport 동작
}
//// jacoco report 설정
//jacocoTestReport {
// reports {
// // html로 report 생성하기
// // 빌드경로/jacoco/report.html 폴더 내부로 경로 설정
// html.destination file("$jacoco/report.html")
// }
//
// // jacocoTestReport가 끝나면 jacocoTestCoverageVerification 동작
// finalizedBy 'jacocoTestCoverageVerification'
//}
//
//// jacoco 커버리지 검증 설정
//jacocoTestCoverageVerification {
// violationRules {
// rule {
// enabled = true // 커버리지 적용 여부
// element = 'CLASS' // 커버리지 적용 단위
//
// // 라인 커버리지 설정
// // 적용 대상 전체 소스 코드들을 한줄 한줄 따졌을 때 테스트 코드가 작성되어 있는 줄의 빈도
// // 테스트 코드가 작성되어 있는 비율이 90% 이상이어야 함
// limit {
// counter = 'LINE'
// value = 'COVEREDRATIO'
// minimum = 0.10
// }
//
// // 브랜치 커버리지 설정
// // if-else 등을 활용하여 발생되는 분기들 중 테스트 코드가 작성되어 있는 빈도
// // 테스트 코드가 작성되어 있는 비율이 90% 이상이어야 함
// limit {
// counter = 'BRANCH'
// value = 'COVEREDRATIO'
// minimum = 0.00
// }
//
// // 라인 최대 갯수 설정
// // 빈 줄을 제외하고 하나의 자바 파일에서 작성될 수 있는 최대 라인 갯수
// // 한 파일에 최대 500줄까지 작성되어야 함
// limit {
// counter = 'LINE'
// value = 'TOTALCOUNT'
// maximum = 500
// }
// // 커버리지 체크를 제외할 클래스들
// excludes = [
// // '*.test.*',
// '*.common.*',
// '*.config.*',
// '*.controller.*',
// '*.domain.*',
// '*.exception.*',
// '*.external.*',
// '*.infrastructure.*',
// '*.auth.*',
// '*.service.*'
//
// ]
// }
// }
//}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.app.toaster.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;

import jakarta.persistence.EntityManager;

@Configuration
public class JpaQueryFactoryConfig {

@Bean
JPAQueryFactory jpaQueryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}
}
// package com.app.toaster.config;
//
// import org.springframework.context.annotation.Bean;
// import org.springframework.context.annotation.Configuration;
//
// import com.querydsl.jpa.impl.JPAQueryFactory;
//
// import jakarta.persistence.EntityManager;
//
// @Configuration
// public class JpaQueryFactoryConfig {
//
// @Bean
// JPAQueryFactory jpaQueryFactory(EntityManager em) {
// return new JPAQueryFactory(em);
// }
// }
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public enum Error {
NOT_FOUND_IMAGE_EXCEPTION(HttpStatus.NOT_FOUND, "s3 서비스에서 이미지를 찾을 수 없습니다."),
NOT_FOUND_TOAST_FILTER(HttpStatus.NOT_FOUND, "유효하지 않은 필터입니다."),
NOT_FOUND_TIMER(HttpStatus.NOT_FOUND, "찾을 수 없는 타이머입니다."),
NOT_FOUND_POPUP_EXCEPTION(HttpStatus.NOT_FOUND, "유효하지 않은 팝업입니다."),

/**
* 400 BAD REQUEST EXCEPTION
Expand Down
2 changes: 2 additions & 0 deletions linkmind/src/main/java/com/app/toaster/exception/Success.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum Success {
GET_LINKS_SUCCESS(HttpStatus.OK, "이주의 링크 조회 성공"),
GET_SITES_SUCCESS(HttpStatus.OK, "추천 사이트 조회 성공"),
GET_SETTINGS_SUCCESS(HttpStatus.OK, "설정 페이지 조회 성공"),
GET_POPUP_SUCCESS(HttpStatus.OK, "팝업 정보 조회 성공"),

GET_CATEORIES_SUCCESS(HttpStatus.OK, "전체 카테고리 조회 성공"),
GET_CATEORY_SUCCESS(HttpStatus.OK, "세부 카테고리 조회 성공"),
Expand Down Expand Up @@ -52,6 +53,7 @@ public enum Success {
PUSH_ALARM_PERIODIC_SUCCESS(HttpStatus.OK, "푸시알림 활성에 성공했습니다."),
PUSH_ALARM_SUCCESS(HttpStatus.OK, "푸시알림 전송에 성공했습니다."),
CLEAR_SCHEDULED_TASKS_SUCCESS(HttpStatus.OK, "스케줄러에서 예약된 작업을 제거했습니다."),
UPDATE_POPUP_SUCCESS(HttpStatus.OK, "팝업 데이터 수정 성공"),


/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// package com.app.toaster.infrastructure.querydsl;
//
// import static com.app.toaster.domain.QToast.*;
// import static com.app.toaster.domain.QUser.*;
//
// import java.time.LocalDateTime;
// import java.util.ArrayList;
// import java.util.List;
// import org.springframework.data.jpa.repository.Modifying;
// import org.springframework.data.jpa.repository.Query;
// import org.springframework.data.repository.query.Param;
// import org.springframework.stereotype.Repository;
//
// import com.app.toaster.domain.Category;
// import com.app.toaster.domain.QToast;
// import com.app.toaster.domain.QUser;
// import com.app.toaster.domain.Toast;
// import com.app.toaster.domain.User;
// import com.querydsl.core.types.Path;
// import com.querydsl.core.types.dsl.BooleanExpression;
// import com.querydsl.jpa.impl.JPAQueryFactory;
//
// import jakarta.persistence.EntityManager;
// import lombok.RequiredArgsConstructor;
//
// @Repository
// @RequiredArgsConstructor
// public class CustomToastRepository {
// private final JPAQueryFactory queryFactory;
// // private final EntityManager em;
// public List<Toast> getAllByCategory(Category category){
// return queryFactory.select(toast)
// .from(toast)
// .where(eqCategoryId(category.getCategoryId()))
// .fetch();
// }
//
// private BooleanExpression eqCategoryId(Long id){
// if (id == null){
// return null;
// }
// return toast.category.categoryId.eq(id);
// }
//
// ArrayList<Toast> findByIsReadAndCategory(Boolean isRead, Category category){
// return null;
// };
//
// ArrayList<Toast> getAllByUser(User user){
// return null;
// }
//
// List<Toast> getAllByUserOrderByCreatedAtDesc(User user){
// return null;
// }
//
//
// ArrayList<Toast> getAllByUserAndIsReadIsTrue(User user){
// return null;
// }
//
//
// // @Modifying
// // @Query("UPDATE Toast t SET t.category = null WHERE t.category.categoryId IN :categoryIds")
// // void updateCategoryIdsToNull(@Param("categoryIds") List<Long> categoryIds){
// // }
//
// //querydsl의 수정은 bulkupdate라 영속성컨텍스트를 안거치기 때문에 무조건 flush,clear해주자.
// void updateCategoryIdsToNull(List<Long> categoryIds){
// queryFactory.update(toast)
// .set(toast.category, (Category)null)
// .where(toast.category.categoryId.in(categoryIds))
// .execute();
// // em.flush(); //test 코드에서는 따로 em을 주입하는 중이므로 테스트 후 넣자.
// // em.clear();
// }
//
//
// List<Toast> searchToastsByQuery(Long userId, String query){
// return queryFactory.select(toast)
// .from(toast)
// .leftJoin(toast.user, user).fetchJoin()
// .where(eqToastOwner(userId), containToastTitle(query))
// .fetch();
// }
// private BooleanExpression eqToastOwner(Long userId){
// return userId != null?toast.user.userId.eq(userId):null;
// }
//
// private BooleanExpression containToastTitle(String query){
// if (query == null || query.isEmpty() || query.isBlank()){
// return null;
// }
// return toast.title.containsIgnoreCase(query);
// }
//
//
//
// Long countAllByUser(User user){
// return null;
// }
//
//
// Long countALLByUserAndIsReadTrue(User user){
// return null;
// }
//
//
// Long countALLByUserAndIsReadFalse(User user){
// return null;
// }
//
//
// Long countAllByCategory(Category category){
// return null;
// }
//
//
// Long countAllByCategoryAndIsReadTrue(Category category){
// return null;
// }
//
//
// Long countAllByCategoryAndIsReadFalse(Category category){
// return null;
// }
//
//
// Integer getUnReadToastNumber(Long userId){
//
// Integer count = queryFactory.select(toast.count().intValue())
// .from(toast)
// .where(eqToastOwner(userId).and(toast.isRead.isFalse()))
// .fetchOne();
// return (count!=null)?count:0;
// }
//
//
// @Query("SELECT COUNT(t) FROM Toast t WHERE t.user=:user AND t.createdAt >= :startOfWeek AND t.createdAt <= :endOfWeek")
// Long countAllByCreatedAtThisWeek(@Param("startOfWeek") LocalDateTime startOfWeek,
// @Param("endOfWeek") LocalDateTime endOfWeek, @Param("user") User user){
// return null;
// }
//
//
// @Query("SELECT COUNT(t) FROM Toast t WHERE t.user=:user AND t.isRead = true AND t.updateAt >= :startOfWeek AND t.updateAt <= :endOfWeek")
// Long countAllByUpdateAtThisWeek(@Param("startOfWeek") LocalDateTime startOfWeek,
// @Param("endOfWeek") LocalDateTime endOfWeek,
// @Param("user") User user){
// return null;
// }
//
//
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.app.toaster.popup.controller;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.app.toaster.popup.controller.request.PopUpRequestDto;
import com.app.toaster.popup.controller.response.InvisibleResponseDto;
import com.app.toaster.popup.controller.response.PopupResponseDto;
import com.app.toaster.popup.service.PopupService;
import com.app.toaster.common.dto.ApiResponse;
import com.app.toaster.config.UserId;
import com.app.toaster.exception.Success;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v2/popup")
@Validated
public class PopupController {
private final PopupService popupService;


@PatchMapping
public ApiResponse<InvisibleResponseDto> updateInvisible(@UserId Long userId, @RequestBody @Valid PopUpRequestDto popUpRequestDto){
return ApiResponse.success(Success.UPDATE_POPUP_SUCCESS, popupService.updatePopupInvisible(userId,popUpRequestDto));
}

@GetMapping
public ApiResponse<PopupResponseDto> getPopUpInformation(@UserId Long userId){
return ApiResponse.success(Success.GET_POPUP_SUCCESS, popupService.findPopupInformation(userId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.app.toaster.popup.controller.request;

import jakarta.validation.constraints.NotNull;

public record PopUpRequestDto(
Long popupId,
@NotNull
Long hideDate
) {
}
Loading

0 comments on commit 1086d1f

Please sign in to comment.