diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..2b2595ef1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# top-most EditorConfig file +root = true + +[*] +# [encoding-utf8] +charset = utf-8 + +# [newline-lf] +end_of_line = lf + +# [newline-eof] +insert_final_newline = true + +[*.bat] +end_of_line = crlf + +[*.java] +# [indentation-tab] +indent_style = tab + +# [4-spaces-tab] +indent_size = 4 +tab_width = 4 + +# [no-trailing-spaces] +trim_trailing_whitespace = true + +[line-length-120] +max_line_length = 120 diff --git a/.gitattributes b/.gitattributes index 5811c65a2..2e0efdd4b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,18 +1,18 @@ # Set the default behavior, in case people don't have core.autocrlf set. -* text=auto +* text=auto eol=lf # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. -*.java text=auto -*.sql text=auto -*.md text=auto -*.txt text=auto -*.gradle text=auto -Dockerfile text=auto -*.yml text=auto -*.yaml text=auto -*.sh text=auto - +*.java text=auto eol=lf +*.sql text=auto eol=lf +*.md text=auto eol=lf +*.txt text=auto eol=lf +*.gradle text=auto eol=lf +Dockerfile text=auto eol=lf +*.yml text=auto eol=lf +*.yaml text=auto eol=lf +*.sh text=auto eol=lf +*.bat text=auto eol=crlf # Denote all files that are truly binary and should not be modified. *.png binary -*.jpg binary \ No newline at end of file +*.jpg binary diff --git a/.github/workflows/checkstyle-validation.yml b/.github/workflows/checkstyle-validation.yml new file mode 100644 index 000000000..86277c01f --- /dev/null +++ b/.github/workflows/checkstyle-validation.yml @@ -0,0 +1,21 @@ +name: ๐Ÿ‘ฎCheckstyle validation + +on: + pull_request: + branches: [ main, dev ] + +jobs: + checkstyle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Main checkstyle + run: ./gradlew --console verbose clean checkstyleMain + - name: ๏ธTest checkstyle + run: ./gradlew --console verbose clean checkstyleTest diff --git a/.github/workflows/main-deploy.yml b/.github/workflows/main-deploy.yml index b8ba31051..ba3edda91 100644 --- a/.github/workflows/main-deploy.yml +++ b/.github/workflows/main-deploy.yml @@ -14,7 +14,7 @@ env: DOCKER_USER: ${{ secrets.DOCKER_USER }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} IMAGE_NAME: wken5577/42gg-server - VERSION_TAG : ${{ secrets.VERSION_TAG }} + VERSION_TAG: ${{ secrets.VERSION_TAG }} permissions: contents: read @@ -36,7 +36,7 @@ jobs: - name: Make application ymls run: | - cd ./src/main/resources + cd ./gg-pingpong-api/src/main/resources echo "${{ secrets.APPLICATION_YML }}" | base64 -d > application.yml shell: bash diff --git a/.github/workflows/test-code-validation.yml b/.github/workflows/test-code-validation.yml index a7b94c572..2d4b0468d 100644 --- a/.github/workflows/test-code-validation.yml +++ b/.github/workflows/test-code-validation.yml @@ -15,29 +15,35 @@ jobs: java-version: 11 - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: ๏ธ๐Ÿ‘ถ Unit Test with Gradle - run: ./gradlew --console verbose clean unitTestCoverage - - name: mv for separate report folder - run: mv ./build/reports/jacoco/test ./build/reports/jacoco/unitTest - - name: mv for separate report name - run: mv ./build/reports/jacoco/unitTest/jacocoTestReport.xml ./build/reports/jacoco/unitTest/unitTestReport.xml + run: ./gradlew --console verbose clean unitTestCoverage unitTestCoverageReport -x test + + # - name: mv for separate report folder + # run: mv ./gg-pingpong-utils/build/reports/jacoco/unitTestCoverageReport ./build/reports/jacoco/unitTest + + # - name: mv for separate report name + # run: mv ./build/reports/jacoco/unitTest/jacocoTestReport.xml ./build/reports/jacoco/unitTest/unitTestReport.xml + - name: ๐Ÿ“ฒ Upload unitTest coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true - files: ./build/reports/jacoco/unitTest/unitTestReport.xml + files: ./gg-utils/build/reports/jacoco/unitTestCoverageReport/unitTestCoverageReport.xml flags: unitTest name: codecov-unit verbose: true + - name: ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Integration Test with Gradle - run: ./gradlew --console verbose clean integrationTestCoverage + run: ./gradlew --console verbose clean integrationTestCoverage integrationTestCoverageReport -x test + - name: ๐Ÿ“ฒ Upload integrationTest coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true - files: ./build/reports/jacoco/test/jacocoTestReport.xml + files: ./gg-utils/build/reports/jacoco/integrationTestCoverageReport/integrationTestCoverageReport.xml flags: integrationTest name: codecov-integration verbose: true diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index ccf2fa2fe..9867ee258 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -16,7 +16,7 @@ env: DOCKER_USER: ${{ secrets.DOCKER_USER }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} IMAGE_NAME: wken5577/test-migrate-server - + permissions: contents: read @@ -26,63 +26,66 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up JDK 11 - uses: actions/setup-java@v3 - with: - java-version: '11' - distribution: 'temurin' - - - name: Make application ymls - run: | - cd ./src/main/resources - echo "${{ secrets.MIGRATE_APPLICATION_YML }}" | base64 -d > application.yml - shell: bash - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'temurin' + + - name: Make application ymls + run: | + cd ./gg-pingpong-api/src/main/resources + echo "${{ secrets.MIGRATE_APPLICATION_YML }}" | base64 -d > application.yml + shell: bash + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: username: ${{ env.DOCKER_USER }} password: ${{ env.DOCKER_PASSWORD }} - - - name: Build with Gradle - run: ./gradlew clean test build - - - name: build new docker image as latest tag - run: | - docker build -t ${{ env.IMAGE_NAME }}:latest . - docker push ${{ env.IMAGE_NAME }}:latest - - - name: Get Github Actions IP - id: ip - uses: haythem/public-ip@v1.3 - - - name: AWS Credentials - uses: aws-actions/configure-aws-credentials@v2 - with: - aws-access-key-id: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_SECRET_KEY }} - aws-region: ap-northeast-2 - - - name: Add Github Actions IP to Security group - run: | + + - name: Test with Gradle + run: ./gradlew clean test + + - name: Build with Gradle + run: ./gradlew clean build -x test + + - name: build new docker image as latest tag + run: | + docker build -t ${{ env.IMAGE_NAME }}:latest . + docker push ${{ env.IMAGE_NAME }}:latest + + - name: Get Github Actions IP + id: ip + uses: haythem/public-ip@v1.3 + + - name: AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + aws-access-key-id: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_TEST_MIGRATE_SECURITY_SECRET_KEY }} + aws-region: ap-northeast-2 + + - name: Add Github Actions IP to Security group + run: | aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_TEST_MIGRATE_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32 - - name: executing docker-compose up on test server - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.TEST_MIGRATE_SERVER_HOST }} - username: ${{ secrets.TEST_MIGRATE_SERVER_USERNAME }} - key: ${{ secrets.TEST_MIGRATE_SERVER_PEM }} - script: | - cd /home/ec2-user/docker - docker-compose down tomcat - docker rmi ${{ env.IMAGE_NAME }}:latest - docker-compose up tomcat -d - docker-compose up prometheus -d - - - name: Remove Github Actions IP From Security Group - run: | + - name: executing docker-compose up on test server + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.TEST_MIGRATE_SERVER_HOST }} + username: ${{ secrets.TEST_MIGRATE_SERVER_USERNAME }} + key: ${{ secrets.TEST_MIGRATE_SERVER_PEM }} + script: | + cd /home/ec2-user/docker + docker-compose down tomcat + docker rmi ${{ env.IMAGE_NAME }}:latest + docker-compose up tomcat -d + docker-compose up prometheus -d + + - name: Remove Github Actions IP From Security Group + run: | aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_TEST_MIGRATE_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32 diff --git a/.gitignore b/.gitignore index 509fcea84..443c346ca 100644 --- a/.gitignore +++ b/.gitignore @@ -4,13 +4,8 @@ build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ -src/main/resources/application.yml -src/main/resources/application-local.yml -src/main/resources/application-main.yml -src/main/resources/application-test.yml +gg-pingpong-api/src/main/resources/application.yml .DS_Store -src/test/resources/application.yml -src/test/resources/application-local.yml python /logs @@ -54,4 +49,4 @@ pingping.pem ./logs/* ### git commit message convention file ### -.gitmessage.txt \ No newline at end of file +.gitmessage.txt diff --git a/Dockerfile b/Dockerfile index c5fcce172..aeaf705f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,12 +2,12 @@ FROM openjdk:11-jdk WORKDIR /app -ARG JAR_FILE=build/libs/server-42gg.jar +ARG JAR_FILE=gg-pingpong-api/build/libs/gg-pingpong-api-42gg.jar COPY ${JAR_FILE} . EXPOSE 8080 -ENTRYPOINT ["java","-jar","server-42gg.jar", \ +ENTRYPOINT ["java","-jar","gg-pingpong-api-42gg.jar", \ "--spring.profiles.active=${PROFILE}", \ "--spring.security.oauth2.client.registration.42.client-id=${SPRING_42_CLIENT_ID}", \ "--spring.security.oauth2.client.registration.42.client-secret=${SPRING_42_CLIENT_SECRET}"] diff --git a/build.gradle b/build.gradle index 49a217681..fdb0fa7f7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,19 @@ plugins { - id 'org.springframework.boot' version '2.6.8' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'org.asciidoctor.jvm.convert' version '3.3.2' - id 'java' - id 'jacoco' + id 'org.springframework.boot' version '2.6.8' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'org.asciidoctor.jvm.convert' version '3.3.2' + id 'java' + id 'jacoco' + id 'org.ec4j.editorconfig' version '0.0.3' + id 'checkstyle' +} + +editorconfig { + excludes = ['build'] } springBoot { - mainClass = "com.gg.server.Application" + mainClass = "gg.pingpong.api.PingPongApiApplication" } group = 'io.42pp' @@ -15,236 +21,261 @@ version = '42gg' sourceCompatibility = '11' configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } ext { - set('snippetsDir', file("build/generated-snippets")) + set('snippetsDir', file("build/generated-snippets")) } -dependencies { - /* spring */ - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-mail' - annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' - - /* database */ - runtimeOnly 'mysql:mysql-connector-java' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - - /* redis */ - implementation 'org.springframework.boot:spring-boot-starter-data-redis' - implementation 'org.springframework.session:spring-session-data-redis' - implementation 'org.redisson:redisson:3.17.3' - - /* oauth */ - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' +subprojects { + apply plugin: 'java' + apply plugin: 'org.springframework.boot' + apply plugin: 'io.spring.dependency-management' + apply plugin: 'jacoco' + apply plugin: 'checkstyle' + + checkstyle { + maxWarnings = 0 + configFile = file("${rootDir}/naver-checkstyle-rules.xml") + configProperties = ["suppressionFile": "${rootDir}/naver-checkstyle-suppressions.xml"] + toolVersion = "8.24" + } + + dependencies { + /* database */ + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + /* redis */ + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + implementation 'org.redisson:redisson:3.17.3' + + /* spring doc */ + implementation 'org.springdoc:springdoc-openapi-ui:1.6.6' + + /* lombok */ + implementation 'org.projectlombok:lombok:1.18.26' + annotationProcessor 'org.projectlombok:lombok' + compileOnly 'org.projectlombok:lombok' + + /* test */ + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + + //test์—์„œ lombok ์‚ฌ์šฉ + testImplementation 'org.projectlombok:lombok' + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + + /* elk-logstash */ + implementation 'net.logstash.logback:logstash-logback-encoder:6.3' + + //actuator ์ถ”๊ฐ€ + implementation 'org.springframework.boot:spring-boot-starter-actuator' + + //prometheus ์ถ”๊ฐ€ + implementation 'io.micrometer:micrometer-registry-prometheus' + + //testcontainers ์ถ”๊ฐ€ + testImplementation "org.testcontainers:mysql:1.19.3" + testImplementation "com.redis:testcontainers-redis:2.0.1" + testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" + testImplementation "org.testcontainers:testcontainers:1.19.3" + testImplementation "org.testcontainers:junit-jupiter:1.19.3" + } - /* JSON Web Token */ - implementation 'io.jsonwebtoken:jjwt-api:0.11.2' - implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' - implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2' +//ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ธก์ •๋„๊ตฌ + jacoco { + toolVersion = "0.8.8" + } - /* test */ - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' +// dto, ์™ธ๋ถ€ ์—ฐ๋™ ์„œ๋น„์Šค๋Š” ํ…Œ์ŠคํŠธ์—์„œ ์ œ์™ธ + def jacocoExcludes = [ + '*Application*', + "**/config/*", + "**/security/*", + "**/dto/*", + "**/aws/*", + "*NotiMailSender*", + '*SlackbotService*', + ] - /* lombok */ - implementation 'org.projectlombok:lombok:1.18.26' - annotationProcessor 'org.projectlombok:lombok' - compileOnly 'org.projectlombok:lombok' +//์ปค๋ฒ„๋ฆฌ์ง€ ๋ฆฌํฌํŠธ ์ƒ์„ฑ + jacocoTestReport { + + reports { + xml.enabled true + html.enabled true + csv.enabled false + } + + afterEvaluate { + //dto ๋ฐ ์™ธ๋ถ€ ์—ฐ๋™ ์„œ๋น„์Šค๋Š” ํ…Œ์ŠคํŠธ์—์„œ ์ œ์™ธ + classDirectories.setFrom(files(classDirectories.files.collect { + fileTree(dir: it, exclude: jacocoExcludes) + }) + ) + } + } - /* SHA256 */ - implementation 'com.google.guava:guava:31.0.1-jre' +// ์ปค๋ฒ„๋ฆฌ์ง€ ๊ฒ€์ฆ ์„ค์ • + jacocoTestCoverageVerification { + + violationRules { + rule { + enabled = true + element = 'CLASS' + + //๋ธŒ๋žœ์น˜ ์ปค๋ฒ„๋ฆฌ์ง€ + limit { + counter = 'BRANCH' + value = 'COVEREDRATIO' + minimum = 0.00 + } + + //๋ฉ”์†Œ๋“œ ์ปค๋ฒ„๋ฆฌ์ง€ + limit { + counter = 'METHOD' + value = 'COVEREDRATIO' + minimum = 0.00 + } + + //๋ผ์ธ ์ปค๋ฒ„๋ฆฌ์ง€ + limit { + counter = 'LINE' + value = 'COVEREDRATIO' + minimum = 0.00 + } + + //๊ฒ€์ฆ์—์„œ ์ œ์™ธํ•  ํŒจํ‚ค์ง€, ํด๋ž˜์Šค + excludes = jacocoExcludes + } + } + } - /* When..? Error */ - implementation 'org.apache.commons:commons-lang3:3.12.0' +//์ „์ฒด ํ…Œ์ŠคํŠธ + test { + description = 'Runs the total tests.' + useJUnitPlatform() + } - /* REST template */ - implementation 'org.apache.httpcomponents:httpcore:4.4.15' - implementation 'org.apache.httpcomponents:httpclient:4.5.13' +//์œ ๋‹› ํ…Œ์ŠคํŠธ + task unitTest(type: Test) { + group = 'verification' + description = 'Runs the unit tests.' + useJUnitPlatform { + includeTags 'UnitTest' + excludeTags 'IntegrationTest' + } - /* S3 Image Bucket */ - implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' - implementation 'org.springframework:spring-test:5.3.20' - implementation "com.amazonaws:aws-java-sdk-s3:1.12.281" + jacoco { + destinationFile = file("$buildDir/jacoco/test.exec") + } - testImplementation 'org.springframework.security:spring-security-test' + } - //test์—์„œ lombok ์‚ฌ์šฉ - testImplementation 'org.projectlombok:lombok' - testCompileOnly 'org.projectlombok:lombok' - testAnnotationProcessor 'org.projectlombok:lombok' +//ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ + task integrationTest(type: Test) { + group = 'verification' + description = 'Runs the integration tests.' + useJUnitPlatform { + includeTags 'IntegrationTest' + excludeTags 'UnitTest' + } + + jacoco { + destinationFile = file("$buildDir/jacoco/test.exec") + } + } - /* spring doc */ - implementation 'org.springdoc:springdoc-openapi-ui:1.6.6' +//์ „์ฒด ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ + task totalTestCoverage(type: Test) { + group 'verification' + description 'Runs the total tests with coverage' - /* flyway */ - implementation 'org.flywaydb:flyway-core' + dependsOn(project.tasks.findByName('test'), + project.tasks.findByName('jacocoTestReport'), + project.tasks.findByName('jacocoTestCoverageVerification')) - /* elk-logstash */ - implementation 'net.logstash.logback:logstash-logback-encoder:6.3' + tasks['jacocoTestReport'].mustRunAfter(tasks['test']) + tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) + } - //actuator ์ถ”๊ฐ€ - implementation 'org.springframework.boot:spring-boot-starter-actuator' +//์œ ๋‹› ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ + task unitTestCoverage(type: Test) { + group 'verification' + description 'Runs the unit tests with coverage' - //prometheus ์ถ”๊ฐ€ - implementation 'io.micrometer:micrometer-registry-prometheus' + dependsOn(project.tasks.findByName('unitTest'), + project.tasks.findByName('jacocoTestReport'), + project.tasks.findByName('jacocoTestCoverageVerification')) - //testcontainers ์ถ”๊ฐ€ - testImplementation "org.testcontainers:mysql:1.19.3" - testImplementation "com.redis:testcontainers-redis:2.0.1" - testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" - testImplementation "org.testcontainers:testcontainers:1.19.3" - testImplementation "org.testcontainers:junit-jupiter:1.19.3" -} + tasks['jacocoTestReport'].mustRunAfter(tasks['unitTest']) + tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) + } -//ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ธก์ •๋„๊ตฌ -jacoco { - toolVersion = "0.8.8" -} +//ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ + task integrationTestCoverage(type: Test) { + group 'verification' + description 'Runs the integration tests with coverage' -// dto, ์™ธ๋ถ€ ์—ฐ๋™ ์„œ๋น„์Šค๋Š” ํ…Œ์ŠคํŠธ์—์„œ ์ œ์™ธ -def jacocoExcludes = [ - '*Application*', - "**/config/*", - "**/security/*", - "**/dto/*", - "**/aws/*", - "*NotiMailSender*", - '*SlackbotService*', -] + dependsOn(project.tasks.findByName('integrationTest'), + project.tasks.findByName('jacocoTestReport'), + project.tasks.findByName('jacocoTestCoverageVerification')) -//์ปค๋ฒ„๋ฆฌ์ง€ ๋ฆฌํฌํŠธ ์ƒ์„ฑ -jacocoTestReport { - - reports { - xml.enabled true - html.enabled true - csv.enabled false - } - - afterEvaluate { - //dto ๋ฐ ์™ธ๋ถ€ ์—ฐ๋™ ์„œ๋น„์Šค๋Š” ํ…Œ์ŠคํŠธ์—์„œ ์ œ์™ธ - classDirectories.setFrom(files(classDirectories.files.collect { - fileTree(dir: it, exclude: jacocoExcludes)}) - ) - } -} + tasks['jacocoTestReport'].mustRunAfter(tasks['integrationTest']) + tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) + } -// ์ปค๋ฒ„๋ฆฌ์ง€ ๊ฒ€์ฆ ์„ค์ • -jacocoTestCoverageVerification { - - violationRules { - rule { - enabled = true - element = 'CLASS' - - //๋ธŒ๋žœ์น˜ ์ปค๋ฒ„๋ฆฌ์ง€ - limit { - counter = 'BRANCH' - value = 'COVEREDRATIO' - minimum = 0.00 - } - - //๋ฉ”์†Œ๋“œ ์ปค๋ฒ„๋ฆฌ์ง€ - limit { - counter = 'METHOD' - value = 'COVEREDRATIO' - minimum = 0.00 - } - - //๋ผ์ธ ์ปค๋ฒ„๋ฆฌ์ง€ - limit { - counter = 'LINE' - value = 'COVEREDRATIO' - minimum = 0.00 - } - - //๊ฒ€์ฆ์—์„œ ์ œ์™ธํ•  ํŒจํ‚ค์ง€, ํด๋ž˜์Šค - excludes = jacocoExcludes - } - } } -//์ „์ฒด ํ…Œ์ŠคํŠธ -test { - description = 'Runs the total tests.' - useJUnitPlatform() +project(':gg-pingpong-api') { + bootJar { enabled = true } + jar { enabled = true } + dependencies { + implementation project(':gg-data') + implementation project(':gg-repo') + implementation project(':gg-admin-repo') + implementation project(':gg-utils') + } } -//์œ ๋‹› ํ…Œ์ŠคํŠธ -task unitTest(type: Test) { - group = 'verification' - description = 'Runs the unit tests.' - useJUnitPlatform{ - includeTags 'UnitTest' - excludeTags 'IntegrationTest' - } - - jacoco { - destinationFile = file("$buildDir/jacoco/test.exec") - } - +project(':gg-repo') { + bootJar { enabled = false } + jar { enabled = true } + dependencies { + implementation project(':gg-data') + implementation project(':gg-utils') + } } -//ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ -task integrationTest(type: Test) { - group = 'verification' - description = 'Runs the integration tests.' - useJUnitPlatform{ - includeTags 'IntegrationTest' - excludeTags 'UnitTest' - } - - jacoco { - destinationFile = file("$buildDir/jacoco/test.exec") - } +project(':gg-admin-repo') { + bootJar { enabled = false } + jar { enabled = true } + dependencies { + implementation project(':gg-data') + implementation project(':gg-utils') + } } -//์ „์ฒด ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ -task totalTestCoverage(type: Test) { - group 'verification' - description 'Runs the total tests with coverage' - - dependsOn(':test', - ':jacocoTestReport', - ':jacocoTestCoverageVerification') - - tasks['jacocoTestReport'].mustRunAfter(tasks['test']) - tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) +project(':gg-data') { + bootJar { enabled = false } + jar { enabled = true } + dependencies { + implementation project(':gg-utils') + } } -//์œ ๋‹› ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ -task unitTestCoverage(type: Test) { - group 'verification' - description 'Runs the unit tests with coverage' - - dependsOn(':unitTest', - ':jacocoTestReport', - ':jacocoTestCoverageVerification') - - tasks['jacocoTestReport'].mustRunAfter(tasks['unitTest']) - tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) +project(':gg-utils') { + bootJar { enabled = false } + jar { enabled = true } + dependencies { + } } -//ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ, ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ๊ฒ€์ฆ -task integrationTestCoverage(type: Test) { - group 'verification' - description 'Runs the integration tests with coverage' - - dependsOn(':integrationTest', - ':jacocoTestReport', - ':jacocoTestCoverageVerification') - - tasks['jacocoTestReport'].mustRunAfter(tasks['integrationTest']) - tasks['jacocoTestCoverageVerification'].mustRunAfter(tasks['jacocoTestReport']) -} diff --git a/codecov.yml b/codecov.yml index 253397514..1c5086536 100644 --- a/codecov.yml +++ b/codecov.yml @@ -12,7 +12,13 @@ coverage: flags: unitTest: paths: - - src/main/java/com/gg/server/ + - gg-pingpong-api/src/main/java/gg/pingpong/api + - gg-pingpong-repo/src/main/java/gg/pingpong/repo + - gg-pingpong-admin-repo/src/main/java/gg/pingpong/admin/repo + - gg-pingpong-data/src/main/java/gg/pingpong/data integrationTest: paths: - - src/main/java/com/gg/server/ \ No newline at end of file + - gg-pingpong-api/src/main/java/gg/pingpong/api + - gg-pingpong-repo/src/main/java/gg/pingpong/repo + - gg-pingpong-admin-repo/src/main/java/gg/pingpong/admin/repo + - gg-pingpong-data/src/main/java/gg/pingpong/data diff --git a/gg-admin-repo/build.gradle b/gg-admin-repo/build.gradle new file mode 100644 index 000000000..e8bceb7da --- /dev/null +++ b/gg-admin-repo/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' +} + +group 'gg.pingpong.admin.repo' +version '42gg' + +repositories { + mavenCentral() +} + +dependencies { + /* database */ + runtimeOnly 'mysql:mysql-connector-java' + /* flyway */ + implementation 'org.flywaydb:flyway-core' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation testFixtures(project(':gg-utils')) +} + +test { + useJUnitPlatform() +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/GameAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/GameAdminRepository.java new file mode 100644 index 000000000..18efb7a17 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/GameAdminRepository.java @@ -0,0 +1,42 @@ +package gg.admin.repo.game; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.admin.repo.game.out.GameTeamUser; +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.season.Season; + +public interface GameAdminRepository extends JpaRepository { + + Page findBySeason(Pageable pageable, Season season); + + Page findBySeasonAndModeIn(Pageable pageable, Season season, List modes); + + Page findAllByModeIn(Pageable pageable, List modes); + + @Query(value = "select t1.gameId, t1.startTime, t1.endTime, t1.status, t1.mode, " + + "t1.teamId t1TeamId, t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, " + + "t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + + "t2.teamId t2TeamId, t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, " + + "t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + + "from v_rank_game_detail t1, v_rank_game_detail t2 " + + "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsIn(@Param("games") List games); + + @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.status = :status AND g.id = t.game.id" + + " AND t.id = tu.team.id AND tu.user.id = :userId") + Optional findByStatusTypeAndUserId(@Param("status") StatusType status, @Param("userId") Long userId); + + @Query(value = "SELECT g FROM Game g JOIN FETCH g.season WHERE g.id = :gameId") + Optional findGameWithSeasonByGameId(@Param("gameId") Long gameId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepository.java new file mode 100644 index 000000000..fb7e4b362 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepository.java @@ -0,0 +1,8 @@ +package gg.admin.repo.game; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.game.PChange; + +public interface PChangeAdminRepository extends JpaRepository, PChangeAdminRepositoryCustom { +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustom.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustom.java new file mode 100644 index 000000000..afaed7f3b --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustom.java @@ -0,0 +1,9 @@ +package gg.admin.repo.game; + +import java.util.List; + +import gg.data.game.PChange; + +public interface PChangeAdminRepositoryCustom { + List findByTeamUser(Long userId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustomImpl.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustomImpl.java new file mode 100644 index 000000000..a9702a353 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/PChangeAdminRepositoryCustomImpl.java @@ -0,0 +1,24 @@ +package gg.admin.repo.game; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.LockModeType; + +import gg.data.game.PChange; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class PChangeAdminRepositoryCustomImpl implements PChangeAdminRepositoryCustom { + private final EntityManager em; + + @Override + public List findByTeamUser(Long userId) { + String query = "SELECT p FROM PChange p WHERE p.user.id = :userId ORDER BY p.createdAt desc"; + return em.createQuery(query, PChange.class) + .setParameter("userId", userId) + .setMaxResults(2) + .setLockMode(LockModeType.PESSIMISTIC_WRITE) + .getResultList(); + } +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamAdminRepository.java new file mode 100644 index 000000000..da465572f --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamAdminRepository.java @@ -0,0 +1,13 @@ +package gg.admin.repo.game; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.game.Game; +import gg.data.game.Team; + +public interface TeamAdminRepository extends JpaRepository { + List findAllByGame(Game game); + +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamUserAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamUserAdminRepository.java new file mode 100644 index 000000000..7b4750dda --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/TeamUserAdminRepository.java @@ -0,0 +1,18 @@ +package gg.admin.repo.game; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.game.TeamUser; +import gg.data.user.User; + +public interface TeamUserAdminRepository extends JpaRepository { + @Query("SELECT tu.user FROM TeamUser tu WHERE tu.team.id = :teamId") + List findUsersByTeamId(@Param("teamId") Long teamId); + + @Query("SELECT tu FROM TeamUser tu JOIN FETCH tu.team t JOIN FETCH tu.user WHERE tu.team.id IN (:teamId)") + List findUsersByTeamIdIn(@Param("teamId") List teamId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/game/out/GameTeamUser.java b/gg-admin-repo/src/main/java/gg/admin/repo/game/out/GameTeamUser.java new file mode 100644 index 000000000..60cb599f2 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/game/out/GameTeamUser.java @@ -0,0 +1,50 @@ +package gg.admin.repo.game.out; + +import java.time.LocalDateTime; + +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; + +public interface GameTeamUser { + Long getGameId(); + + LocalDateTime getStartTime(); + + LocalDateTime getEndTime(); + + StatusType getStatus(); + + Mode getMode(); + + Long getT1TeamId(); + + Integer getT1Wins(); + + Integer getT1Losses(); + + String getT1IntraId(); + + String getT1Image(); + + Integer getT1Exp(); + + Integer getT1Score(); + + Boolean getT1IsWin(); + + Long getT2TeamId(); + + Integer getT2Wins(); + + Integer getT2Losses(); + + String getT2IntraId(); + + String getT2Image(); + + Integer getT2Exp(); + + Integer getT2Score(); + + Boolean getT2IsWin(); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/AdminSlotManagementsRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/AdminSlotManagementsRepository.java new file mode 100644 index 000000000..ebcf52842 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/AdminSlotManagementsRepository.java @@ -0,0 +1,23 @@ +package gg.admin.repo.manage; + +import java.time.LocalDateTime; +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; + +import gg.data.manage.SlotManagement; + +public interface AdminSlotManagementsRepository extends JpaRepository { + @Query("select slot from SlotManagement slot " + + "where slot.endTime > :nowTime or slot.startTime > :nowTime or slot.endTime = null " + + "order by slot.startTime desc") + List findAfterNowSlotManagement(@Param("nowTime") LocalDateTime nowTime); + + List findAllByOrderByCreatedAtDesc(); + + Optional findFirstByOrderByIdDesc(); + +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/AnnouncementAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/AnnouncementAdminRepository.java new file mode 100644 index 000000000..4a0419c5d --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/AnnouncementAdminRepository.java @@ -0,0 +1,12 @@ +package gg.admin.repo.manage; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.manage.Announcement; + +public interface AnnouncementAdminRepository extends JpaRepository { + + Optional findFirstByOrderByIdDesc(); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/FeedbackAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/FeedbackAdminRepository.java new file mode 100644 index 000000000..971298b64 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/FeedbackAdminRepository.java @@ -0,0 +1,15 @@ +package gg.admin.repo.manage; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.manage.Feedback; + +public interface FeedbackAdminRepository extends JpaRepository { + @Query(value = "select f from Feedback f join fetch f.user " + + "where f.user.intraId = :intraId order by f.user.intraId asc, f.createdAt asc") + List findFeedbacksByUserIntraId(@Param("intraId") String intraId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepository.java new file mode 100644 index 000000000..442f6c753 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepository.java @@ -0,0 +1,22 @@ +package gg.admin.repo.manage; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.manage.Penalty; + +public interface PenaltyAdminRepository extends JpaRepository, PenaltyAdminRepositoryCustom { + @EntityGraph(attributePaths = {"user"}) + Page findAll(Pageable pageable); + + @Query("select p from Penalty p where p.user.id = :userId and p.startTime > :startTime") + List findAfterPenaltiesByUser(@Param("userId") Long userId, + @Param("startTime") LocalDateTime startTime); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustom.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustom.java new file mode 100644 index 000000000..41a680df3 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustom.java @@ -0,0 +1,17 @@ +package gg.admin.repo.manage; + +import java.time.LocalDateTime; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import gg.data.manage.Penalty; + +public interface PenaltyAdminRepositoryCustom { + Page findAllCurrent(Pageable pageable, LocalDateTime targetTime); + + Page findAllByIntraId(Pageable pageable, String intraId); + + Page findAllCurrentByIntraId(Pageable pageable, LocalDateTime targetTime, + String intraId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustomImpl.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustomImpl.java new file mode 100644 index 000000000..c8b934e5e --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyAdminRepositoryCustomImpl.java @@ -0,0 +1,93 @@ +package gg.admin.repo.manage; + +import java.time.LocalDateTime; +import java.util.List; + +import javax.persistence.EntityManager; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.data.manage.Penalty; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class PenaltyAdminRepositoryCustomImpl implements PenaltyAdminRepositoryCustom { + private final EntityManager em; + + @Override + public Page findAllCurrent(Pageable pageable, LocalDateTime targetTime) { + String sql = + "select p from Penalty p where TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " + + "order by p.startTime desc"; + long count = countCurrent(targetTime); + List penalties = em.createQuery(sql, Penalty.class) + .setParameter("targetTime", targetTime) + .setFirstResult((int)pageable.getOffset()) + .setMaxResults(pageable.getPageSize()) + .getResultList(); + Page result = new PageImpl<>(penalties, pageable, count); + return result; + } + + @Override + public Page findAllByIntraId(Pageable pageable, String intraId) { + String sql = "SELECT p FROM Penalty p JOIN FETCH p.user " + + "WHERE p.user.intraId LIKE :intraId ORDER BY p.startTime DESC"; + long count = countByIntraId(intraId); + List penalties = em.createQuery(sql, Penalty.class) + .setParameter("intraId", "%" + intraId + "%") + .setFirstResult((int)pageable.getOffset()) + .setMaxResults(pageable.getPageSize()) + .getResultList(); + Page result = new PageImpl<>(penalties, pageable, count); + return result; + } + + @Override + public Page findAllCurrentByIntraId(Pageable pageable, LocalDateTime targetTime, String intraId) { + String sql = "select p from Penalty p join fetch p.user where " + + "p.user.intraId like :intraId and TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " + + "order by p.startTime desc"; + long count = countCurrentByIntraId(intraId, targetTime); + List penalties = em.createQuery(sql, Penalty.class) + .setParameter("intraId", "%" + intraId + "%") + .setParameter("targetTime", targetTime) + .setFirstResult((int)pageable.getOffset()) + .setMaxResults(pageable.getPageSize()) + .getResultList(); + Page result = new PageImpl<>(penalties, pageable, count); + return result; + } + + private long countCurrent(LocalDateTime targetTime) { + String sql = + "select p from Penalty p where TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " + + "order by p.startTime desc"; + return em.createQuery(sql, Penalty.class) + .setParameter("targetTime", targetTime) + .getResultList().size(); + } + + private long countByIntraId(String intraId) { + String sql = "select p FROM Penalty p join fetch p.user u WHERE u.intraId LIKE :intraId " + + "order by p.startTime desc"; + return em.createQuery(sql, Penalty.class) + .setParameter("intraId", "%" + intraId + "%") + .getResultList() + .size(); + } + + private long countCurrentByIntraId(String intraId, LocalDateTime targetTime) { + String sql = "select p from Penalty p join fetch p.user where " + + "p.user.intraId like :intraId and TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " + + "order by p.startTime desc"; + return em.createQuery(sql, Penalty.class) + .setParameter("intraId", "%" + intraId + "%") + .setParameter("targetTime", targetTime) + .getResultList() + .size(); + + } +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyUserAdminRedisRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyUserAdminRedisRepository.java new file mode 100644 index 000000000..ac0a351f7 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/manage/PenaltyUserAdminRedisRepository.java @@ -0,0 +1,60 @@ +package gg.admin.repo.manage; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.manage.type.PenaltyKey; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class PenaltyUserAdminRedisRepository { + private final RedisTemplate redisTemplate; + + public void addPenaltyUser(RedisPenaltyUser penaltyUser, LocalDateTime releaseTime) { + LocalDateTime now = LocalDateTime.now(); + Duration duration = Duration.between(now, releaseTime); + redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, + duration.getSeconds(), TimeUnit.SECONDS); + } + + public Optional findByIntraId(String intraId) { + RedisPenaltyUser penaltyUser = redisTemplate.opsForValue().get(PenaltyKey.USER_ADMIN + intraId); + return Optional.ofNullable(penaltyUser); + } + + public List findAll() { + Set penaltyUserKeys = redisTemplate.keys(PenaltyKey.ALL + "*"); + List users = penaltyUserKeys.stream().map(key -> redisTemplate.opsForValue().get(key)) + .collect(Collectors.toList()); + return users; + } + + public List findAllByKeyword(String keyword) { + Set penaltyUserKeys = redisTemplate.keys(PenaltyKey.ALL + "*" + keyword + "*"); + List users = penaltyUserKeys.stream().map(key -> redisTemplate.opsForValue().get(key)) + .collect(Collectors.toList()); + return users; + } + + public void deletePenaltyInUser(RedisPenaltyUser penaltyUser, Integer penaltyTime) { + LocalDateTime newReleaseTime = penaltyUser.getReleaseTime().minusMinutes(penaltyTime); + penaltyUser.updateReleaseTime(newReleaseTime, penaltyUser.getPenaltyTime() - penaltyTime); + Duration duration = Duration.between(LocalDateTime.now(), newReleaseTime); + if (duration.isNegative()) { + redisTemplate.delete(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId()); + return; + } + redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, + duration.getSeconds(), TimeUnit.SECONDS); + } +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepository.java new file mode 100644 index 000000000..6e4aec4ba --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepository.java @@ -0,0 +1,17 @@ +package gg.admin.repo.noti; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.noti.Noti; + +public interface NotiAdminRepository + extends JpaRepository, NotiAdminRepositoryCustom { + + @Override + @EntityGraph(attributePaths = {"user"}) + Page findAll(Pageable pageable); + +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustom.java b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustom.java new file mode 100644 index 000000000..fbc90aee0 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustom.java @@ -0,0 +1,12 @@ +package gg.admin.repo.noti; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.query.Param; + +import gg.data.noti.Noti; + +public interface NotiAdminRepositoryCustom { + + Page findNotisByUserIntraId(Pageable pageable, @Param("intraId") String intraId); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustomImpl.java b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustomImpl.java new file mode 100644 index 000000000..a41922069 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/noti/NotiAdminRepositoryCustomImpl.java @@ -0,0 +1,38 @@ +package gg.admin.repo.noti; + +import java.util.List; + +import javax.persistence.EntityManager; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.data.noti.Noti; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class NotiAdminRepositoryCustomImpl implements NotiAdminRepositoryCustom { + private final EntityManager em; + + @Override + public Page findNotisByUserIntraId(Pageable pageable, String intraId) { + long totalElem = countTotalElem(intraId); + String sql = "select n from Noti n join fetch n.user where " + + "n.user.intraId like \'%" + intraId + "%\' order by n.createdAt desc, n.user.intraId asc"; + List notis = em.createQuery(sql, Noti.class) + .setFirstResult((int)pageable.getOffset()) + .setMaxResults(pageable.getPageSize()) + .getResultList(); + Page result = new PageImpl<>(notis, pageable, totalElem); + return result; + } + + private long countTotalElem(String intraId) { + String sql = "select n from Noti n join fetch n.user where " + + "n.user.intraId like \'%" + intraId + "%\'"; + List notiList = em.createQuery(sql, Noti.class) + .getResultList(); + return notiList.size(); + } +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/season/SeasonAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/season/SeasonAdminRepository.java new file mode 100644 index 000000000..7c7a61365 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/season/SeasonAdminRepository.java @@ -0,0 +1,37 @@ +package gg.admin.repo.season; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.season.Season; + +public interface SeasonAdminRepository extends JpaRepository { + /* ์ž…๋ ฅ์‹œ๊ฐ„๊ณผ ๋ชจ๋“œ๋กœ ์ž…๋ ฅ์‹œ๊ฐ„ ์ดํ›„ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์‹œ์ฆŒ ๊ฐ€์ ธ์˜ค๊ธฐ */ + @Query("SELECT e FROM Season e WHERE e.startTime > :targetTime ORDER BY e.startTime ASC") + List findAfterSeasons(@Param("targetTime") LocalDateTime targetTime); + + @Query("SELECT e FROM Season e WHERE e.startTime < :targetTime ORDER BY e.startTime DESC") + List findBeforeSeasons(@Param("targetTime") LocalDateTime targetTime); + + @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now") + Optional findCurrentSeason(@Param("now") LocalDateTime now); + + List findAllByOrderByStartTimeDesc(); + + List findAllByOrderByStartTimeAsc(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "UPDATE Season s " + + "SET s.seasonName = :seasonName, s.startTime = :startTime, " + + "s.startPpp = :startPpp, s.pppGap = :pppGap " + + "WHERE s.id = :id") + void updateReserveSeasonById(@Param("id") Long seasonId, @Param("seasonName") String seasonName, + @Param("startTime") LocalDateTime startTime, + @Param("startPpp") Integer startPpp, @Param("pppGap") Integer pppGap); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/store/CoinPolicyAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/store/CoinPolicyAdminRepository.java new file mode 100644 index 000000000..72fd33f20 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/store/CoinPolicyAdminRepository.java @@ -0,0 +1,11 @@ +package gg.admin.repo.store; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.CoinPolicy; + +public interface CoinPolicyAdminRepository extends JpaRepository { + Optional findFirstByOrderByIdDesc(); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/store/ItemAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/store/ItemAdminRepository.java new file mode 100644 index 000000000..007cf8f02 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/store/ItemAdminRepository.java @@ -0,0 +1,11 @@ +package gg.admin.repo.store; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.Item; + +public interface ItemAdminRepository extends JpaRepository { + Page findAll(Pageable pageable); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/store/MegaphoneAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/store/MegaphoneAdminRepository.java new file mode 100644 index 000000000..133b024b0 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/store/MegaphoneAdminRepository.java @@ -0,0 +1,11 @@ +package gg.admin.repo.store; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.Megaphone; + +public interface MegaphoneAdminRepository extends JpaRepository { + Page findMegaphonesByUserIntraId(String intraId, Pageable pageable); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepository.java new file mode 100644 index 000000000..d121c17ae --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepository.java @@ -0,0 +1,11 @@ +package gg.admin.repo.store; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.Receipt; + +public interface ReceiptAdminRepository extends JpaRepository, ReceiptAdminRepositorySearch { + Page findAll(Pageable pageable); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepositorySearch.java b/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepositorySearch.java new file mode 100644 index 000000000..7d24f901e --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/store/ReceiptAdminRepositorySearch.java @@ -0,0 +1,13 @@ +package gg.admin.repo.store; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.store.Receipt; + +public interface ReceiptAdminRepositorySearch { + @Query(value = "select re from Receipt re where re.purchaserIntraId = :intraId or re.ownerIntraId = :intraId") + Page findReceiptByIntraId(@Param("intraId") String intraId, Pageable pageable); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/user/UserAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/user/UserAdminRepository.java new file mode 100644 index 000000000..b16de379c --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/user/UserAdminRepository.java @@ -0,0 +1,19 @@ +package gg.admin.repo.user; + +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.user.User; + +public interface UserAdminRepository extends JpaRepository { + Optional findByIntraId(String intraId); + + Page findByIntraIdContains(Pageable pageable, String intraId); + + Page findByIntraId(Pageable pageable, String intraId); + + Page findAll(Pageable pageable); +} diff --git a/gg-admin-repo/src/main/java/gg/admin/repo/user/UserImageAdminRepository.java b/gg-admin-repo/src/main/java/gg/admin/repo/user/UserImageAdminRepository.java new file mode 100644 index 000000000..9f9162810 --- /dev/null +++ b/gg-admin-repo/src/main/java/gg/admin/repo/user/UserImageAdminRepository.java @@ -0,0 +1,43 @@ +package gg.admin.repo.user; + +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.user.User; +import gg.data.user.UserImage; + +public interface UserImageAdminRepository extends JpaRepository { + Optional findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(User user); + + Optional findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(User user); + + Page findAllByDeletedAtNotNullOrderByDeletedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.user.id = :user_id " + + "AND ui.deletedAt != NULL ORDER BY ui.deletedAt DESC") + Page findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc(@Param("user_id") Long userId, + Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + + "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + + ") ORDER BY ui.createdAt DESC") + Page findAllChangedOrderByCreatedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + + "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + + ") AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") + Page findAllByUserOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS TRUE" + + " ORDER BY ui.createdAt DESC") + Page findAllByIsCurrentTrueOrderByCreatedAtDesc(Pageable pageable); + + @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS True" + + " AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") + Page findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); +} diff --git a/gg-data/build.gradle b/gg-data/build.gradle new file mode 100644 index 000000000..bf38c2767 --- /dev/null +++ b/gg-data/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java' +} + +group 'gg.pingpong.data' +version '42gg' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation testFixtures(project(':gg-utils')) +} + +test { + useJUnitPlatform() +} diff --git a/gg-data/src/main/java/gg/data/BaseTimeEntity.java b/gg-data/src/main/java/gg/data/BaseTimeEntity.java new file mode 100644 index 000000000..ab03615d0 --- /dev/null +++ b/gg-data/src/main/java/gg/data/BaseTimeEntity.java @@ -0,0 +1,26 @@ +package gg.data; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import lombok.Getter; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseTimeEntity { + @CreatedDate + @Column(updatable = false, nullable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime modifiedAt; + +} diff --git a/gg-data/src/main/java/gg/data/game/Game.java b/gg-data/src/main/java/gg/data/game/Game.java new file mode 100644 index 000000000..2799d9d40 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/Game.java @@ -0,0 +1,112 @@ +package gg.data.game; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.DynamicUpdate; + +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.season.Season; +import gg.utils.exception.BusinessChecker; +import gg.utils.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +@DynamicUpdate +public class Game { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "season_id") + private Season season; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "status", length = 10) + private StatusType status; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "mode", length = 10) + private Mode mode; + + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @Column(name = "end_time") + private LocalDateTime endTime; + + @OneToMany(mappedBy = "game", cascade = CascadeType.ALL) + private List teams = new ArrayList<>(); + + public Game(Season season, StatusType status, Mode mode, LocalDateTime startTime, LocalDateTime endTime) { + this.season = season; + this.status = status; + this.mode = mode; + this.startTime = startTime; + this.endTime = endTime; + } + + public Game(Season season, Mode mode, LocalDateTime startTime, Integer interval) { + this.season = season; + this.status = StatusType.BEFORE; + this.mode = mode; + this.startTime = startTime; + this.endTime = startTime.plusMinutes(interval); + } + + @Override + public String toString() { + return "Game{" + + "id=" + id + + ", season=" + season + + ", status=" + status + + ", mode=" + mode + + ", startTime=" + startTime + + ", endTime=" + endTime + + '}'; + } + + public void updateStatus() { + if (status == StatusType.BEFORE) { + this.status = StatusType.LIVE; + } else if (status == StatusType.LIVE) { + this.status = StatusType.WAIT; + } else { + this.status = StatusType.END; + } + } + + public void addTeam(Team team) { + BusinessChecker.mustNotNull(team, ErrorCode.NULL_POINT); + BusinessChecker.mustNotExceed(1, teams, ErrorCode.TEAM_SIZE_EXCEED); + BusinessChecker.mustNotContains(team, teams, ErrorCode.TEAM_DUPLICATION); + this.teams.add(team); + } + +} diff --git a/gg-data/src/main/java/gg/data/game/PChange.java b/gg-data/src/main/java/gg/data/game/PChange.java new file mode 100644 index 000000000..e1de0dda3 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/PChange.java @@ -0,0 +1,77 @@ +package gg.data.game; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +public class PChange extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "game_id") + private Game game; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "ppp_result") + private Integer pppResult; + + @NotNull + @Column(name = "exp") + private Integer exp; + + @NotNull + @Column(name = "is_checked") + private Boolean isChecked; + + public PChange(Game game, User user, Integer pppResult, Boolean isChecked) { + this.game = game; + this.user = user; + this.pppResult = pppResult; + this.exp = user.getTotalExp(); + this.isChecked = isChecked; + } + + public void checkPChange() { + this.isChecked = true; + } + + public void updatePPP(Integer ppp) { + this.pppResult = ppp; + } + + @Override + public String toString() { + return "PChange{" + + "id=" + id + + ", game=" + game + + ", user=" + user + + ", pppResult=" + pppResult + + ", exp=" + exp + + ", isChecked=" + isChecked + + '}'; + } +} diff --git a/gg-data/src/main/java/gg/data/game/Team.java b/gg-data/src/main/java/gg/data/game/Team.java new file mode 100644 index 000000000..454f0ade7 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/Team.java @@ -0,0 +1,68 @@ +package gg.data.game; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.DynamicUpdate; + +import gg.utils.exception.BusinessChecker; +import gg.utils.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +@DynamicUpdate +public class Team { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "game_id") + private Game game; + + @Column(name = "score") + private Integer score; + + @Column(name = "win") + private Boolean win; + + @OneToMany(mappedBy = "team", cascade = CascadeType.ALL) + private List teamUsers = new ArrayList<>(); + + public Team(Game game, Integer score, Boolean win) { + this.game = game; + this.score = score; + this.win = win; + game.addTeam(this); + } + + public void updateScore(int score, Boolean win) { + this.score = score; + this.win = win; + } + + public void addTeamUser(TeamUser teamUser) { + BusinessChecker.mustNotNull(teamUser, ErrorCode.NULL_POINT); + BusinessChecker.mustNotExceed(1, teamUsers, ErrorCode.TEAM_USER_EXCEED); + BusinessChecker.mustNotContains(teamUser, teamUsers, ErrorCode.TEAM_USER_ALREADY_EXIST); + this.teamUsers.add(teamUser); + } +} diff --git a/gg-data/src/main/java/gg/data/game/TeamUser.java b/gg-data/src/main/java/gg/data/game/TeamUser.java new file mode 100644 index 000000000..525e39351 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/TeamUser.java @@ -0,0 +1,51 @@ +package gg.data.game; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.user.User; +import gg.utils.exception.BusinessChecker; +import gg.utils.exception.ErrorCode; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Entity +@Getter +@ToString +public class TeamUser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id") + private Team team; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + public TeamUser(Team team, User user) { + this.team = team; + this.user = user; + team.addTeamUser(this); + } + + public void updateUser(User user) { + BusinessChecker.mustNotNull(user, ErrorCode.NULL_POINT); + this.user = user; + } +} diff --git a/gg-data/src/main/java/gg/data/game/type/Mode.java b/gg-data/src/main/java/gg/data/game/type/Mode.java new file mode 100644 index 000000000..bd0b05954 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/type/Mode.java @@ -0,0 +1,27 @@ +package gg.data.game.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Mode { + NORMAL("normal"), RANK("rank"), TOURNAMENT("tournament"); + private final String code; + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static Mode getEnumValue(String code) { + for (Mode e : values()) { + if (e.code.equals(code)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(code.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/game/type/StatusType.java b/gg-data/src/main/java/gg/data/game/type/StatusType.java new file mode 100644 index 000000000..78bef3fd9 --- /dev/null +++ b/gg-data/src/main/java/gg/data/game/type/StatusType.java @@ -0,0 +1,33 @@ +package gg.data.game.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum StatusType { + + BEFORE("before", "๊ฒŒ์ž„ ์‹œ์ž‘ ์ „"), + LIVE("live", "๊ฒŒ์ž„ ์ง„ํ–‰ ์ค‘"), + WAIT("wait", "๊ฒŒ์ž„ ๋๋‚˜๊ณ  ์ ์ˆ˜์ž…๋ ฅ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ"), + END("end", "๊ฒŒ์ž„์ด ๋๋‚˜๊ณ  ์ ์ˆ˜์ž…๋ ฅ๋„ ์™„๋ฃŒ"); + + private final String code; + private final String desc; + + @JsonCreator + public static StatusType getEnumFromValue(String value) { + for (StatusType e : values()) { + if (e.name().equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/Announcement.java b/gg-data/src/main/java/gg/data/manage/Announcement.java new file mode 100644 index 000000000..976819c15 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/Announcement.java @@ -0,0 +1,54 @@ +package gg.data.manage; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class Announcement extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @NotNull + @Column(name = "content", length = 1000) + private String content; + @NotNull + @Column(name = "creator_intra_id", length = 30) + private String creatorIntraId; + @Column(name = "deleter_intra_id", length = 30) + private String deleterIntraId; + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @Builder + public Announcement(String content, String creatorIntraId) { + this.content = content; + this.creatorIntraId = creatorIntraId; + } + + public void update(String deleterIntraId, LocalDateTime deletedAt) { + this.deleterIntraId = deleterIntraId; + this.deletedAt = deletedAt; + } + + public static Announcement from(String content, String creatorIntraId) { + return Announcement.builder() + .content(content) + .creatorIntraId(creatorIntraId) + .build(); + } +} diff --git a/gg-data/src/main/java/gg/data/manage/Feedback.java b/gg-data/src/main/java/gg/data/manage/Feedback.java new file mode 100644 index 000000000..5dd721dc1 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/Feedback.java @@ -0,0 +1,56 @@ +package gg.data.manage; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.manage.type.FeedbackType; +import gg.data.user.User; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@Entity +@Getter +public class Feedback extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "category", length = 15) + private FeedbackType category; + + @NotNull + @Column(name = "content", length = 600) + private String content; + + @Setter + @NotNull + @Column(name = "is_solved") + private Boolean isSolved; + + @Builder + public Feedback(User user, FeedbackType category, String content) { + this.user = user; + this.category = category; + this.content = content; + this.isSolved = false; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/Penalty.java b/gg-data/src/main/java/gg/data/manage/Penalty.java new file mode 100644 index 000000000..17f4baf58 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/Penalty.java @@ -0,0 +1,64 @@ +package gg.data.manage; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.manage.type.PenaltyType; +import gg.data.user.User; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Penalty extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "penalty_type", length = 20) + @Enumerated(EnumType.STRING) + private PenaltyType type; + + @Column(name = "message", length = 100) + private String message; + + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @NotNull + @Column(name = "penalty_time") + private Integer penaltyTime; + + public Penalty(User user, PenaltyType type, String message, LocalDateTime startTime, Integer penaltyTime) { + this.user = user; + this.type = type; + this.message = message; + this.startTime = startTime; + this.penaltyTime = penaltyTime; + } + + public void updateStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/SlotManagement.java b/gg-data/src/main/java/gg/data/manage/SlotManagement.java new file mode 100644 index 000000000..2ac1382ff --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/SlotManagement.java @@ -0,0 +1,86 @@ +package gg.data.manage; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.utils.exception.slotmanagement.SlotManagementForbiddenException; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor +@AllArgsConstructor +public class SlotManagement extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "past_slot_time") + private Integer pastSlotTime; + + @NotNull + @Column(name = "future_slot_time") + private Integer futureSlotTime; + + @NotNull + @Column(name = "open_minute") + private Integer openMinute; + + @NotNull + @Column(name = "game_interval") + private Integer gameInterval; + + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @Column(name = "end_time") + private LocalDateTime endTime; + + @Builder + public SlotManagement(Integer pastSlotTime, Integer futureSlotTime, Integer openMinute, Integer gameInterval, + LocalDateTime startTime, LocalDateTime endTime) { + this.pastSlotTime = pastSlotTime; + this.futureSlotTime = futureSlotTime; + this.openMinute = openMinute; + this.gameInterval = gameInterval; + this.startTime = startTime; + this.endTime = endTime; + } + + @Builder + public SlotManagement(Integer pastSlotTime, Integer futureSlotTime, Integer openMinute, Integer gameInterval, + LocalDateTime startTime) { + this.pastSlotTime = pastSlotTime; + this.futureSlotTime = futureSlotTime; + this.openMinute = openMinute; + this.gameInterval = gameInterval; + this.startTime = startTime; + this.endTime = null; + } + + public void updateEndTime(LocalDateTime endTime) { + if (this.endTime != null) { + throw new SlotManagementForbiddenException(); + } + this.endTime = endTime; + } + + public void setNullEndTime() { + if (this.endTime == null) { + throw new SlotManagementForbiddenException(); + } + this.endTime = null; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/redis/RedisPenaltyUser.java b/gg-data/src/main/java/gg/data/manage/redis/RedisPenaltyUser.java new file mode 100644 index 000000000..fbbe906cd --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/redis/RedisPenaltyUser.java @@ -0,0 +1,44 @@ +package gg.data.manage.redis; + +import java.time.LocalDateTime; + +import javax.persistence.Id; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class RedisPenaltyUser { + @Id + private String id; + private String intraId; + private Integer penaltyTime; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime releaseTime; + + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime startTime; + private String reason; + + public RedisPenaltyUser(String intraId, Integer penaltyTime, LocalDateTime releaseTime, LocalDateTime startTime, + String reason) { + this.intraId = intraId; + this.penaltyTime = penaltyTime; + this.releaseTime = releaseTime; + this.startTime = startTime; + this.reason = reason; + } + + public void updateReleaseTime(LocalDateTime releaseTime, Integer penaltyTime) { + this.releaseTime = releaseTime; + this.penaltyTime = penaltyTime; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/type/FeedbackType.java b/gg-data/src/main/java/gg/data/manage/type/FeedbackType.java new file mode 100644 index 000000000..5a3292bc9 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/type/FeedbackType.java @@ -0,0 +1,33 @@ +package gg.data.manage.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum FeedbackType { + BUG("bug"), + GAMERESULT("gameresult"), + COMPLAINT("complaint"), + CHEERS("cheers"), + OPINION("opinion"), + ETC("etc"); + + private final String code; + + @JsonCreator + public static FeedbackType getEnumFromValue(String value) { + for (FeedbackType e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/manage/type/PenaltyKey.java b/gg-data/src/main/java/gg/data/manage/type/PenaltyKey.java new file mode 100644 index 000000000..5a9368832 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/type/PenaltyKey.java @@ -0,0 +1,7 @@ +package gg.data.manage.type; + +public class PenaltyKey { + public static final String ALL = "PENALTY:"; + public static final String USER = "PENALTY:USER:"; + public static final String USER_ADMIN = "PENALTY:USER:ADMIN:"; +} diff --git a/gg-data/src/main/java/gg/data/manage/type/PenaltyType.java b/gg-data/src/main/java/gg/data/manage/type/PenaltyType.java new file mode 100644 index 000000000..037632693 --- /dev/null +++ b/gg-data/src/main/java/gg/data/manage/type/PenaltyType.java @@ -0,0 +1,38 @@ +package gg.data.manage.type; + +import java.util.Arrays; +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum PenaltyType { + NONE("none"), + NOSHOW("noshow"), + CANCEL("cancel"); + + private final String code; + + public static PenaltyType of(String code) { + return Arrays.stream(PenaltyType.values()) + .filter(penaltyType -> penaltyType.getCode().equals(code)) + .findAny() + .orElse(NONE); + } + + @JsonCreator + public static PenaltyType getEnumFromValue(String value) { + for (PenaltyType e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/match/RedisMatchTime.java b/gg-data/src/main/java/gg/data/match/RedisMatchTime.java new file mode 100644 index 000000000..10e8a5a03 --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/RedisMatchTime.java @@ -0,0 +1,34 @@ +package gg.data.match; + +import java.io.Serializable; +import java.time.LocalDateTime; + +import javax.persistence.Id; + +import org.springframework.data.redis.core.RedisHash; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import gg.data.match.type.Option; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@RedisHash("matchTime") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class RedisMatchTime implements Serializable { + @Id + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime startTime; + private Option option; + + public RedisMatchTime(LocalDateTime startTime, Option option) { + this.startTime = startTime; + this.option = option; + } +} diff --git a/gg-data/src/main/java/gg/data/match/RedisMatchUser.java b/gg-data/src/main/java/gg/data/match/RedisMatchUser.java new file mode 100644 index 000000000..b76350975 --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/RedisMatchUser.java @@ -0,0 +1,28 @@ +package gg.data.match; + +import java.io.Serializable; + +import javax.persistence.Id; + +import org.springframework.data.redis.core.RedisHash; + +import gg.data.match.type.Option; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@RedisHash("matchUser") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class RedisMatchUser implements Serializable { + @Id + private Long userId; + private Integer ppp; + private Option option; + + public RedisMatchUser(Long userId, Integer ppp, Option option) { + this.userId = userId; + this.ppp = ppp; + this.option = option; + } +} diff --git a/gg-data/src/main/java/gg/data/match/type/MatchKey.java b/gg-data/src/main/java/gg/data/match/type/MatchKey.java new file mode 100644 index 000000000..78f3fbd0f --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/type/MatchKey.java @@ -0,0 +1,28 @@ +package gg.data.match.type; + +import java.time.LocalDateTime; + +import lombok.Getter; + +@Getter +public class MatchKey { + public static final String USER = "MATCH:USER:"; + public static final String TIME = "MATCH:TIME:"; + private static final String conjunctive = ":"; + + public static String getUserTime(Long userId, LocalDateTime startTime) { + return USER + userId + conjunctive + startTime; + } + + public static String getUser(Long userId) { + return USER + userId; + } + + public static String getTime(LocalDateTime startTime) { + return TIME + startTime; + } + + public static String getAllTime() { + return TIME; + } +} diff --git a/gg-data/src/main/java/gg/data/match/type/Option.java b/gg-data/src/main/java/gg/data/match/type/Option.java new file mode 100644 index 000000000..a5f6225f0 --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/type/Option.java @@ -0,0 +1,37 @@ +package gg.data.match.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import gg.utils.exception.match.OptionInvalidException; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Option { + //match์—์„œ๋Š” Both๋ฅผ ์จ์„œ ์ž๋ฃŒํ˜• ๋”ฐ๋กœ ๋งŒ๋“ฌ + BOTH(0, "both"), + NORMAL(1, "normal"), + RANK(2, "rank"), + TOURNAMENT(3, "tournament"); + + // ๋ชจ๋“œ๋Š” 4๊ฐ€์ง€๊ฐ€ ์žˆ์Œ. + + private final Integer value; + private final String code; + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static Option getEnumValue(String code) { + for (Option e : values()) { + if (e.code.equals(code)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(code.toUpperCase(Locale.ROOT))) { + return e; + } + } + throw new OptionInvalidException(); + } + +} diff --git a/gg-data/src/main/java/gg/data/match/type/SlotStatus.java b/gg-data/src/main/java/gg/data/match/type/SlotStatus.java new file mode 100644 index 000000000..e2aca1604 --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/type/SlotStatus.java @@ -0,0 +1,30 @@ +package gg.data.match.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum SlotStatus { + OPEN("open"), + CLOSE("close"), + MYTABLE("mytable"), + MATCH("match"); + private final String code; + + @JsonCreator + public static SlotStatus getEnumFromValue(String value) { + for (SlotStatus e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/match/type/TournamentMatchStatus.java b/gg-data/src/main/java/gg/data/match/type/TournamentMatchStatus.java new file mode 100644 index 000000000..24602a660 --- /dev/null +++ b/gg-data/src/main/java/gg/data/match/type/TournamentMatchStatus.java @@ -0,0 +1,17 @@ +package gg.data.match.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TournamentMatchStatus { + // ํ† ๋„ˆ๋จผํŠธ ๋งค์น˜ ์ƒํƒœ + UNNECESSARY(0, "๋งค์นญ ๋ถˆํ•„์š”ํ•จ"), + REQUIRED(1, "๋งค์นญ ํ•„์š”ํ•จ"), + ALREADY_MATCHED(2, "์ด๋ฏธ ๋งค์นญ๋จ"), + NO_MORE_MATCHES(3, "๋งˆ์ง€๋ง‰ ๊ฒฝ๊ธฐ๋กœ ๋”์ด์ƒ ๋งค์นญํ•  ๊ฒŒ์ž„์ด ์—†์Œ"); + + private final Integer value; + private final String code; +} diff --git a/gg-data/src/main/java/gg/data/noti/Noti.java b/gg-data/src/main/java/gg/data/noti/Noti.java new file mode 100644 index 000000000..043f353ae --- /dev/null +++ b/gg-data/src/main/java/gg/data/noti/Noti.java @@ -0,0 +1,64 @@ +package gg.data.noti; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class Noti extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "noti_type", length = 30) + @Enumerated(EnumType.STRING) + private NotiType type; + + @Column(name = "message", length = 255) + private String message; + + @NotNull + @Column(name = "is_checked") + private Boolean isChecked; + + public Noti(User user, NotiType type, String message, Boolean isChecked) { + this.user = user; + this.type = type; + this.message = message; + this.isChecked = isChecked; + } + + public void update(User user, NotiType type, String message, Boolean isChecked) { + this.user = user; + this.type = type; + this.message = message; + this.isChecked = isChecked; + } + + public void modifyIsChecked(Boolean isChecked) { + this.isChecked = isChecked; + } +} diff --git a/gg-data/src/main/java/gg/data/noti/type/NotiType.java b/gg-data/src/main/java/gg/data/noti/type/NotiType.java new file mode 100644 index 000000000..5c83e8390 --- /dev/null +++ b/gg-data/src/main/java/gg/data/noti/type/NotiType.java @@ -0,0 +1,46 @@ +package gg.data.noti.type; + +import java.util.Arrays; +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NotiType { + MATCHED("matched", "๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆํ."), + CANCELEDBYMAN("canceledbyman", "๋งค์นญ์ด ์ทจ์†Œ๋˜์—ˆํ."), + CANCELEDBYTIME("canceledbytime", "๋งค์นญ์ด ์ƒ๋Œ€ ์—†์Œ์œผ๋กœ ์ทจ์†Œ๋˜์—ˆํ."), + IMMINENT("imminent", "๋งค์น˜๊ฐ€ ๊ณง ์‹œ์ž‘๋ ํ."), + ANNOUNCE("announce", "๊ณต์ง€์‚ฌํ•ญ์ด ๋„์ฐฉํ–ˆํ."), + GIFT("gift", "์ƒˆ๋กœ์šด ์„ ๋ฌผ์ด ๋„์ฐฉํ–ˆํ."), + TOURNAMENT_CANCELED("tournament canceled", "์ฐธ๊ฐ€ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์‹ ์ฒญ ์ธ์› ๋ฏธ๋‹ฌ๋กœ ์ทจ์†Œ๋˜์—ˆํ."), + TOURNAMENT_GAME_MATCHED("tournament game matched", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์„ฑ์‚ฌ๋˜์—ˆํ."), + TOURNAMENT_GAME_CANCELED("tournament game canceled", "ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ์ด ์ทจ์†Œ๋˜์—ˆํ."); + + private final String code; + private final String message; + + public static NotiType of(String code) { + return Arrays.stream(NotiType.values()) + .filter(notiType -> notiType.getCode().equals(code)) + .findAny() + .orElse(ANNOUNCE); + } + + @JsonCreator + public static NotiType getEnumFromValue(String value) { + for (NotiType e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } + +} diff --git a/gg-data/src/main/java/gg/data/rank/Rank.java b/gg-data/src/main/java/gg/data/rank/Rank.java new file mode 100644 index 000000000..6dc0ed4a4 --- /dev/null +++ b/gg-data/src/main/java/gg/data/rank/Rank.java @@ -0,0 +1,107 @@ +package gg.data.rank; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.DynamicUpdate; + +import gg.data.BaseTimeEntity; +import gg.data.season.Season; +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "ranks") +@DynamicUpdate +public class Rank extends BaseTimeEntity implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "season_id") + private Season season; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tier_id") + private Tier tier; + + @NotNull + @Column(name = "ppp") + private Integer ppp; + + @NotNull + @Column(name = "wins") + private Integer wins; + + @NotNull + @Column(name = "losses") + private Integer losses; + + @Column(name = "status_message", length = 30) + private String statusMessage; + + public static Rank from(User user, Season season, Integer ppp, Tier tier) { + return Rank.builder() + .user(user) + .ppp(ppp) + .season(season) + .wins(0) + .losses(0) + .statusMessage("") + .tier(tier) + .build(); + } + + @Builder + public Rank(User user, Season season, Integer ppp, Integer wins, + Integer losses, String statusMessage, Tier tier) { + this.user = user; + this.season = season; + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + this.statusMessage = statusMessage; + this.tier = tier; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + public void modifyUserRank(Integer ppp, int wins, int losses) { + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + } + + public void updateTier(Tier tier) { + this.tier = tier; + } + + public boolean isParticipated() { + return wins + losses > 0; + } +} diff --git a/gg-data/src/main/java/gg/data/rank/Tier.java b/gg-data/src/main/java/gg/data/rank/Tier.java new file mode 100644 index 000000000..ea26be3b9 --- /dev/null +++ b/gg-data/src/main/java/gg/data/rank/Tier.java @@ -0,0 +1,33 @@ +package gg.data.rank; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class Tier implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "image_uri") + private String imageUri; + + @Column(name = "name") + private String name; + + public Tier(String imageUri) { + this.imageUri = imageUri; + } +} diff --git a/gg-data/src/main/java/gg/data/rank/redis/RankRedis.java b/gg-data/src/main/java/gg/data/rank/redis/RankRedis.java new file mode 100644 index 000000000..29fbfb5fa --- /dev/null +++ b/gg-data/src/main/java/gg/data/rank/redis/RankRedis.java @@ -0,0 +1,90 @@ +package gg.data.rank.redis; + +import java.io.Serializable; + +import org.springframework.data.redis.core.RedisHash; + +import gg.data.rank.Rank; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@RedisHash("rank") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class RankRedis implements Serializable { + private Long userId; + private String intraId; + private int ppp; + private int wins; + private int losses; + private String statusMessage; + private String tierImageUri; + private String textColor; + + public void updateRank(int changePpp, int wins, int losses) { + this.ppp += changePpp; + this.wins = wins; + this.losses = losses; + } + + public void updateTierImage(String tierImageUri) { + this.tierImageUri = tierImageUri; + } + + public void changedRank(int ppp, int wins, int losses) { + this.ppp = ppp; + this.wins = wins; + this.losses = losses; + } + + public void setStatusMessage(String msg) { + this.statusMessage = msg; + } + + public static RankRedis from(Long id, String intraId, String textColor, Integer ppp, String tierImageUri) { + RankRedis rankRedis = RankRedis.builder() + .userId(id) + .intraId(intraId) + .ppp(ppp) + .wins(0) + .losses(0) + .statusMessage("") + .tierImageUri(tierImageUri) + .textColor(textColor) + .build(); + return rankRedis; + } + + public static RankRedis from(Rank rank) { + RankRedis rankRedis = RankRedis.builder() + .userId(rank.getUser().getId()) + .intraId(rank.getUser().getIntraId()) + .ppp(rank.getPpp()) + .wins(rank.getWins()) + .losses(rank.getLosses()) + .statusMessage(rank.getStatusMessage()) + .tierImageUri(rank.getTier().getImageUri()) + .textColor(rank.getUser().getTextColor()) + .build(); + return rankRedis; + } + + @Override + public String toString() { + return "RankRedis{" + + "userId=" + userId + + ", intraId='" + intraId + '\'' + + ", ppp=" + ppp + + ", wins=" + wins + + ", losses=" + losses + + ", statusMessage='" + statusMessage + '\'' + + ", tierImageUri='" + tierImageUri + '\'' + + ", textColor='" + textColor + '\'' + + '}'; + } +} diff --git a/gg-data/src/main/java/gg/data/season/Season.java b/gg-data/src/main/java/gg/data/season/Season.java new file mode 100644 index 000000000..ceffb0d78 --- /dev/null +++ b/gg-data/src/main/java/gg/data/season/Season.java @@ -0,0 +1,61 @@ +package gg.data.season; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +public class Season { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Setter + @NotNull + @Column(name = "season_name", length = 20) + private String seasonName; + + @Setter + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @Setter + @NotNull + @Column(name = "end_time") + private LocalDateTime endTime; + + @Setter + @NotNull + @Column(name = "start_ppp") + private Integer startPpp; + + @Setter + @NotNull + @Column(name = "ppp_gap") + private Integer pppGap; + + @Builder + public Season(String seasonName, LocalDateTime startTime, LocalDateTime endTime, Integer startPpp, Integer pppGap) { + this.seasonName = seasonName; + this.startTime = startTime; + this.endTime = endTime; + this.startPpp = startPpp; + this.pppGap = pppGap; + } + +} diff --git a/gg-data/src/main/java/gg/data/store/CoinHistory.java b/gg-data/src/main/java/gg/data/store/CoinHistory.java new file mode 100644 index 000000000..b1e3b731c --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/CoinHistory.java @@ -0,0 +1,50 @@ +package gg.data.store; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import org.springframework.data.annotation.CreatedDate; + +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class CoinHistory { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "history", length = 30) + private String history; + + @Column(name = "amount") + private int amount; + + @CreatedDate + @Column(name = "createdAt", updatable = false, nullable = false) + private LocalDateTime createdAt; + + public CoinHistory(User user, String history, int amount) { + this.user = user; + this.history = history; + this.amount = amount; + this.createdAt = LocalDateTime.now(); + } +} diff --git a/gg-data/src/main/java/gg/data/store/CoinPolicy.java b/gg-data/src/main/java/gg/data/store/CoinPolicy.java new file mode 100644 index 000000000..57bb6a20d --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/CoinPolicy.java @@ -0,0 +1,70 @@ +package gg.data.store; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import org.springframework.data.annotation.CreatedDate; + +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class CoinPolicy { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "attendance") + private int attendance; + + @Column(name = "normal") + private int normal; + + @Column(name = "rankWin") + private int rankWin; + + @Column(name = "rankLose") + private int rankLose; + + @CreatedDate + @Column(name = "createdAt", updatable = false, nullable = false) + private LocalDateTime createdAt; + + @Builder + public CoinPolicy(User user, int attendance, int normal, int rankWin, int rankLose) { + this.user = user; + this.attendance = attendance; + this.normal = normal; + this.rankWin = rankWin; + this.rankLose = rankLose; + this.createdAt = LocalDateTime.now(); + } + + public static CoinPolicy from(User user, int attendance, int normal, int rankWin, int rankLose) { + return CoinPolicy.builder() + .user(user) + .attendance(attendance) + .normal(normal) + .rankWin(rankWin) + .rankLose(rankLose) + .build(); + } +} diff --git a/gg-data/src/main/java/gg/data/store/Item.java b/gg-data/src/main/java/gg/data/store/Item.java new file mode 100644 index 000000000..4220eefa7 --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/Item.java @@ -0,0 +1,106 @@ +package gg.data.store; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +import gg.data.store.type.ItemType; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name", length = 30) + private String name; + + @Column(name = "main_content", length = 255) + private String mainContent; + + @Column(name = "sub_content", length = 255) + private String subContent; + + @Column(name = "image_uri", length = 255) + private String imageUri; + + @NotNull + @Column(name = "price") + private Integer price; + + @NotNull + @Column(name = "is_visible") + private Boolean isVisible; + + @Column(name = "discount") + private Integer discount; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "type") + private ItemType type; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + @NotNull + @Column(name = "creator_intra_id", length = 10) + private String creatorIntraId; + + @Column(name = "deleter_intra_id", length = 10) + private String deleterIntraId; + + @Builder + public Item(String name, String mainContent, String subContent, String imageUri, Integer price, + Boolean isVisible, Integer discount, ItemType type, LocalDateTime createdAt, String creatorIntraId) { + this.name = name; + this.mainContent = mainContent; + this.subContent = subContent; + this.imageUri = imageUri; + this.price = price; + this.isVisible = isVisible; + this.discount = discount; + this.type = type; + this.createdAt = createdAt; + this.creatorIntraId = creatorIntraId; + } + + public void imageUpdate(String imageUri) { + this.imageUri = imageUri; + } + + public void setVisibility(String intraId) { + this.isVisible = false; + this.deleterIntraId = intraId; + } + + @Override + public String toString() { + return "Item{" + + "id=" + id + + ", name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", imageUri='" + imageUri + '\'' + + ", price=" + price + + ", isVisible=" + isVisible + + ", discount=" + discount + + ", createdAt=" + createdAt + + ", creatorIntraId='" + creatorIntraId + '\'' + + ", deleterIntraId='" + deleterIntraId + '\'' + + '}'; + } +} diff --git a/gg-data/src/main/java/gg/data/store/Megaphone.java b/gg-data/src/main/java/gg/data/store/Megaphone.java new file mode 100644 index 000000000..6d2a82de3 --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/Megaphone.java @@ -0,0 +1,51 @@ +package gg.data.store; + +import java.time.LocalDate; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.user.User; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Megaphone { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "receipt_id") + private Receipt receipt; + + @Column(name = "content", length = 30) + private String content; + + @NotNull + @Column(name = "used_at") + private LocalDate usedAt; + + public Megaphone(User user, Receipt receipt, String content, LocalDate usedAt) { + this.user = user; + this.receipt = receipt; + this.content = content; + this.usedAt = usedAt; + } +} diff --git a/gg-data/src/main/java/gg/data/store/Receipt.java b/gg-data/src/main/java/gg/data/store/Receipt.java new file mode 100644 index 000000000..d5d40cdad --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/Receipt.java @@ -0,0 +1,76 @@ +package gg.data.store; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.store.type.ItemStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class Receipt { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + + @NotNull + @Column(name = "purchaser_intra_id") + private String purchaserIntraId; + + @NotNull + @Column(name = "owner_intra_id") + private String ownerIntraId; + + @NotNull + @Enumerated(EnumType.STRING) + private ItemStatus status; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + public Receipt(Item item, String purchaserIntraId, String ownerIntraId, + ItemStatus status, LocalDateTime purchasedAt) { + this.item = item; + this.purchaserIntraId = purchaserIntraId; + this.ownerIntraId = ownerIntraId; + this.status = status; + this.createdAt = purchasedAt; + } + + @Override + public String toString() { + return "Receipt{" + + "id=" + id + + ", item=" + item + + ", purchaserIntraId='" + purchaserIntraId + '\'' + + ", ownerIntraId='" + ownerIntraId + '\'' + + ", status=" + status + + ", purchasedAt=" + createdAt + + '}'; + } + + public void updateStatus(ItemStatus status) { + this.status = status; + } +} diff --git a/gg-data/src/main/java/gg/data/store/redis/MegaphoneRedis.java b/gg-data/src/main/java/gg/data/store/redis/MegaphoneRedis.java new file mode 100644 index 000000000..36c922012 --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/redis/MegaphoneRedis.java @@ -0,0 +1,33 @@ +package gg.data.store.redis; + +import java.time.LocalDateTime; + +import javax.persistence.Id; + +import org.springframework.data.redis.core.RedisHash; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@RedisHash("megaphone") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MegaphoneRedis { + @Id + private Long id; + private String intraId; + private String content; + + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime usedAt; +} diff --git a/gg-data/src/main/java/gg/data/store/type/HistoryType.java b/gg-data/src/main/java/gg/data/store/type/HistoryType.java new file mode 100644 index 000000000..9a1ba6c83 --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/type/HistoryType.java @@ -0,0 +1,16 @@ +package gg.data.store.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum HistoryType { + + ATTENDANCECOIN("์ถœ์„"), + NORMAL("์ผ๋ฐ˜์ „ ์ฐธ๊ฐ€"), + RANKWIN("๋žญํฌ์ „ ์Šน๋ฆฌ"), + RANKLOSE("๋žญํฌ์ „ ํŒจ๋ฐฐ"); + + private final String history; +} diff --git a/gg-data/src/main/java/gg/data/store/type/ItemStatus.java b/gg-data/src/main/java/gg/data/store/type/ItemStatus.java new file mode 100644 index 000000000..31c47a1b7 --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/type/ItemStatus.java @@ -0,0 +1,16 @@ +package gg.data.store.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ItemStatus { + BEFORE("์‚ฌ์šฉ ์ „"), + WAITING("์‚ฌ์šฉ ๋Œ€๊ธฐ"), + USING("์‚ฌ์šฉ ์ค‘"), + USED("์‚ฌ์šฉ ์™„๋ฃŒ"), + DELETED("์‚ญ์ œ"); + + private final String description; +} diff --git a/gg-data/src/main/java/gg/data/store/type/ItemType.java b/gg-data/src/main/java/gg/data/store/type/ItemType.java new file mode 100644 index 000000000..920ab5d3a --- /dev/null +++ b/gg-data/src/main/java/gg/data/store/type/ItemType.java @@ -0,0 +1,9 @@ +package gg.data.store.type; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ItemType { + MEGAPHONE, BACKGROUND, EDGE, TEXT_COLOR, PROFILE_IMAGE + +} diff --git a/gg-data/src/main/java/gg/data/tournament/Tournament.java b/gg-data/src/main/java/gg/data/tournament/Tournament.java new file mode 100644 index 000000000..38b976fdb --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/Tournament.java @@ -0,0 +1,158 @@ +package gg.data.tournament; + +import static gg.utils.exception.BusinessChecker.*; +import static gg.utils.exception.ErrorCode.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class Tournament extends BaseTimeEntity { + // ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž ์ˆ˜ => ํ˜„์žฌ๋Š” 8๊ฐ• ๊ณ ์ • + public static final int ALLOWED_JOINED_NUMBER = 8; + // ํ† ๋„ˆ๋จผํŠธ ์ตœ์†Œ ์‹œ์ž‘ ๋‚ ์งœ (n์ผ ํ›„) + public static final int ALLOWED_MINIMAL_START_DAYS = 2; + // ํ† ๋„ˆ๋จผํŠธ ์ตœ์†Œ ์ง„ํ–‰ ์‹œ๊ฐ„ (n์‹œ๊ฐ„) + public static final int MINIMUM_TOURNAMENT_DURATION = 2; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "title", length = 30) + private String title; + + @NotNull + @Column(name = "contents", length = 3000) + private String contents; + + @NotNull + @Column(name = "start_time") + private LocalDateTime startTime; + + @NotNull + @Column(name = "end_time") + private LocalDateTime endTime; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "type") + private TournamentType type; + + @NotNull + @Column(name = "status") + @Enumerated(EnumType.STRING) + private TournamentStatus status; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "winner_id") + private User winner; + + @OneToMany(mappedBy = "tournament", cascade = CascadeType.ALL) + private List tournamentGames = new ArrayList<>(); + + @OneToMany(mappedBy = "tournament", cascade = CascadeType.ALL) + private List tournamentUsers = new ArrayList<>(); + + /** + * winner๋Š” ์ƒ์„ฑ์‹œ์ ์— ์กด์žฌํ•˜์ง€ ์•Š์Œ. + */ + @Builder + public Tournament(String title, String contents, LocalDateTime startTime, LocalDateTime endTime, + TournamentType type, TournamentStatus status) { + this.title = title; + this.contents = contents; + this.startTime = startTime; + this.endTime = endTime; + this.type = type; + this.status = status; + this.winner = null; + } + + public void update(String title, String contents, LocalDateTime startTime, + LocalDateTime endTime, TournamentType type, TournamentStatus status) { + this.title = title; + this.contents = contents; + this.startTime = startTime; + this.endTime = endTime; + this.type = type; + this.status = status; + } + + /** + * TournamentGame ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. + */ + protected void addTournamentGame(TournamentGame tournamentGame) { + mustNotNull(tournamentGame, NULL_POINT); + mustNotExceed(ALLOWED_JOINED_NUMBER - 2, tournamentGames, TOURNAMENT_GAME_EXCEED); + mustNotContains(tournamentGame, tournamentGames, TOURNAMENT_GAME_DUPLICATION); + this.tournamentGames.add(tournamentGame); + } + + /** + * TournamentUser ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. + */ + protected void addTournamentUser(@NotNull TournamentUser tournamentUser) { + mustNotNull(tournamentUser, NULL_POINT); + mustNotContains(tournamentUser, tournamentUsers, TOURNAMENT_USER_DUPLICATION); + this.tournamentUsers.add(tournamentUser); + } + + /** + * TournamentGame ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. + */ + protected void deleteTournamentUser(TournamentUser tournamentUser) { + mustNotNull(tournamentUser, NULL_POINT); + mustContains(tournamentUser, tournamentUsers, TOURNAMENT_USER_NOT_FOUND); + this.tournamentUsers.remove(tournamentUser); + } + + public void updateWinner(User winner) { + mustNotNull(winner, NULL_POINT); + this.winner = winner; + } + + public void updateStatus(TournamentStatus status) { + mustNotNull(status, NULL_POINT); + this.status = status; + } + + public void updateEndTime(LocalDateTime endTime) { + mustNotNull(endTime, NULL_POINT); + this.endTime = endTime; + } + + public Optional findTournamentUserByUserId(Long userId) { + return tournamentUsers.stream() + .filter(tournamentUser -> tournamentUser.getUser().getId().equals(userId)) + .findFirst(); + } +} diff --git a/gg-data/src/main/java/gg/data/tournament/TournamentGame.java b/gg-data/src/main/java/gg/data/tournament/TournamentGame.java new file mode 100644 index 000000000..c2d2166e5 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/TournamentGame.java @@ -0,0 +1,72 @@ +package gg.data.tournament; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.game.Game; +import gg.data.tournament.type.TournamentRound; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class TournamentGame extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "game_id") + private Game game; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tournament_id") + private Tournament tournament; + + @NotNull + @Column(name = "round", length = 30) + @Enumerated(EnumType.STRING) + private TournamentRound tournamentRound; + + /** + * id ๊ฐ’ ์ œ์™ธํ•œ ์ƒ์„ฑ์ž. + *

+ * ์ƒ์„ฑ์— ๋”ฐ๋ฅธ Tournament ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •์„ ๋‹ด๋‹น + *

+ * @param game + * @param tournament + * @param tournamentRound + */ + @Builder + public TournamentGame(Game game, Tournament tournament, TournamentRound tournamentRound) { + tournament.addTournamentGame(this); + this.game = game; + this.tournament = tournament; + this.tournamentRound = tournamentRound; + } + + /** + * TournamentGame์˜ ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. + * @param game + */ + public void updateGame(Game game) { + this.game = game; + } + +} diff --git a/gg-data/src/main/java/gg/data/tournament/TournamentUser.java b/gg-data/src/main/java/gg/data/tournament/TournamentUser.java new file mode 100644 index 000000000..2e7a7ef27 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/TournamentUser.java @@ -0,0 +1,71 @@ +package gg.data.tournament; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.validation.constraints.NotNull; + +import gg.data.BaseTimeEntity; +import gg.data.user.User; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +public class TournamentUser extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tournament_id") + private Tournament tournament; + + @NotNull + @Column(name = "is_joined") + private Boolean isJoined; + + @NotNull + @Column(name = "register_time") + private LocalDateTime registerTime; + + /** + * ์ƒ์„ฑ์ž์ด๋ฉฐ, ๋นŒ๋”์ด์ž, ์ƒ์„ฑ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋‹ด๋‹นํ•œ๋‹ค. + */ + @Builder + public TournamentUser(User user, Tournament tournament, boolean isJoined, LocalDateTime registerTime) { + tournament.addTournamentUser(this); + this.user = user; + this.tournament = tournament; + this.isJoined = isJoined; + this.registerTime = registerTime; + } + + /** + * ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ์‚ญ์ œ ์ฑ…์ž„์„ ๊ฐ€์ง„๋‹ค. + */ + public void deleteTournament() { + tournament.deleteTournamentUser(this); + this.tournament = null; + } + + public void updateIsJoined(boolean isJoined) { + this.isJoined = isJoined; + } +} diff --git a/gg-data/src/main/java/gg/data/tournament/type/RoundNumber.java b/gg-data/src/main/java/gg/data/tournament/type/RoundNumber.java new file mode 100644 index 000000000..ecbd44897 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/type/RoundNumber.java @@ -0,0 +1,15 @@ +package gg.data.tournament.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum RoundNumber { + THE_FINAL(2, "๊ฒฐ์Šน"), + SEMI_FINAL(4, "4๊ฐ•"), + QUARTER_FINAL(8, "8๊ฐ•"); + + private final int round; + private final String code; +} diff --git a/gg-data/src/main/java/gg/data/tournament/type/TournamentRound.java b/gg-data/src/main/java/gg/data/tournament/type/TournamentRound.java new file mode 100644 index 000000000..8b868cb00 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/type/TournamentRound.java @@ -0,0 +1,53 @@ +package gg.data.tournament.type; + +import static gg.data.tournament.type.RoundNumber.*; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum TournamentRound { + // the final -> ๊ฒฐ์Šน + // semi final -> 4๊ฐ• + // quarter final -> 8๊ฐ• + // ordinal()๋กœ sorting ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ˆœ์„œ ์ค‘์š” -> ์ดํ›„์— ๋ฆฌํŒฉํ† ๋ง์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + THE_FINAL(null, RoundNumber.THE_FINAL, 1), + SEMI_FINAL_1(THE_FINAL, SEMI_FINAL, 1), + SEMI_FINAL_2(THE_FINAL, SEMI_FINAL, 2), + QUARTER_FINAL_1(SEMI_FINAL_1, QUARTER_FINAL, 1), + QUARTER_FINAL_2(SEMI_FINAL_1, QUARTER_FINAL, 2), + QUARTER_FINAL_3(SEMI_FINAL_2, QUARTER_FINAL, 3), + QUARTER_FINAL_4(SEMI_FINAL_2, QUARTER_FINAL, 4); + + private final TournamentRound nextRound; + private final RoundNumber roundNumber; + private final int roundOrder; + + public static List getSameRounds(RoundNumber roundNumber) { + List sameRounds = new ArrayList<>(); + for (TournamentRound e : values()) { + if (roundNumber.equals(e.getRoundNumber())) { + sameRounds.add(e); + } + } + return sameRounds; + } + + /** + * ์ด์ „ TournamentRound์˜ roundNum๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + * @param roundNumber - ํ˜„์žฌ ๋ผ์šด๋“œ + * @return ์ด์ „ ๋ผ์šด๋“œ์˜ roundNum, ์—†์„ ๊ฒฝ์šฐ null ๋ฐ˜ํ™˜ + */ + public static RoundNumber getPreviousRoundNumber(RoundNumber roundNumber) { + for (TournamentRound e : values()) { + if (e.nextRound != null && roundNumber == e.nextRound.getRoundNumber()) { + return e.roundNumber; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/tournament/type/TournamentStatus.java b/gg-data/src/main/java/gg/data/tournament/type/TournamentStatus.java new file mode 100644 index 000000000..02ba48893 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/type/TournamentStatus.java @@ -0,0 +1,34 @@ +package gg.data.tournament.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TournamentStatus { + BEFORE("before", "ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์ „"), + LIVE("live", "ํ† ๋„ˆ๋จผํŠธ ์ง„ํ–‰ ์ค‘"), + END("end", "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ"); + + private final String code; + private final String desc; + + @JsonCreator + public static TournamentStatus getEnumFromValue(String value) { + if (value == null) { + return null; + } + for (TournamentStatus e : values()) { + if (e.name().equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/tournament/type/TournamentType.java b/gg-data/src/main/java/gg/data/tournament/type/TournamentType.java new file mode 100644 index 000000000..276830c5d --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/type/TournamentType.java @@ -0,0 +1,34 @@ +package gg.data.tournament.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TournamentType { + ROOKIE("rookie", "์ดˆ๋ณด"), + MASTER("master", "๊ณ ์ˆ˜"), + CUSTOM("custom", "์ปค์Šคํ…€"); + + private final String code; + private final String desc; + + @JsonCreator + public static TournamentType getEnumFromValue(String value) { + if (value == null) { + return null; + } + for (TournamentType e : values()) { + if (e.name().equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } +} diff --git a/gg-data/src/main/java/gg/data/tournament/type/TournamentUserStatus.java b/gg-data/src/main/java/gg/data/tournament/type/TournamentUserStatus.java new file mode 100644 index 000000000..2ef930740 --- /dev/null +++ b/gg-data/src/main/java/gg/data/tournament/type/TournamentUserStatus.java @@ -0,0 +1,15 @@ +package gg.data.tournament.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TournamentUserStatus { + PLAYER("player", "ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž"), + WAIT("wait", "ํ† ๋„ˆ๋จผํŠธ ๋Œ€๊ธฐ์ž"), + BEFORE("before", "ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ ์ „"); + + private final String code; + private final String desc; +} diff --git a/gg-data/src/main/java/gg/data/user/User.java b/gg-data/src/main/java/gg/data/user/User.java new file mode 100644 index 000000000..b1a71662c --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/User.java @@ -0,0 +1,148 @@ +package gg.data.user; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +import org.hibernate.annotations.DynamicUpdate; + +import gg.data.BaseTimeEntity; +import gg.data.user.type.BackgroundType; +import gg.data.user.type.EdgeType; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.utils.exception.item.InsufficientGgcoinException; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DynamicUpdate +public class User extends BaseTimeEntity implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "intra_id", length = 30) + private String intraId; + + @Column(name = "e_mail", length = 60) + private String eMail; + + @Column(name = "image_uri") + private String imageUri; + + @Enumerated(EnumType.STRING) + @Column(name = "racket_type", length = 10) + private RacketType racketType; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = "role_type", length = 10) + private RoleType roleType; + + @Column(name = "total_exp") + private Integer totalExp; + + @Column(name = "sns_noti_opt", length = 10) + @Enumerated(EnumType.STRING) + private SnsType snsNotiOpt; + + @Column(name = "kakao_id") + private Long kakaoId; + + @Column(name = "gg_coin") + private Integer ggCoin; + + @Column(name = "background") + @Enumerated(EnumType.STRING) + private BackgroundType background; + + @Column(name = "text_color", length = 10) + private String textColor; + + @Column(name = "edge") + @Enumerated(EnumType.STRING) + private EdgeType edge; + + @Builder + public User(String intraId, String eMail, String imageUri, RacketType racketType, + RoleType roleType, Integer totalExp, SnsType snsNotiOpt, Long kakaoId) { + this.intraId = intraId; + this.eMail = eMail; + this.imageUri = imageUri; + this.racketType = racketType; + this.roleType = roleType; + this.totalExp = totalExp; + this.snsNotiOpt = snsNotiOpt; + this.kakaoId = kakaoId; + this.background = BackgroundType.BASIC; + this.textColor = "#000000"; + this.edge = EdgeType.BASIC; + this.ggCoin = 0; + } + + public void modifyUserDetail(String email, RacketType racketType, RoleType roleType, Integer coin) { + this.eMail = email; + this.racketType = racketType; + this.roleType = roleType; + this.ggCoin = coin; + } + + public void updateImageUri(String imageUri) { + this.imageUri = imageUri; + } + + public void updateTypes(RacketType racketType, SnsType snsType) { + this.racketType = racketType; + this.snsNotiOpt = snsType; + } + + public void addExp(int plus) { + this.totalExp += plus; + } + + public void updateExp(int beforeExp) { + this.totalExp = beforeExp; + } + + public void updateKakaoId(Long kakaoId) { + this.kakaoId = kakaoId; + } + + public void updateTextColor(String textColor) { + this.textColor = textColor; + } + + public void updateEdge(EdgeType edge) { + this.edge = edge; + } + + public int addGgCoin(int plus) { + this.ggCoin += plus; + return this.ggCoin; + } + + public void payGgCoin(int amount) { + if (this.ggCoin < amount) { + throw new InsufficientGgcoinException(); // ์‚ฌ์šฉ์ž์˜ ggCoin์ด ํ•„์š”ํ•œ ๊ธˆ์•ก๋ณด๋‹ค ์ ์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ + } + this.ggCoin = this.ggCoin - amount; + } + + public void updateBackground(BackgroundType background) { + this.background = background; + } +} diff --git a/gg-data/src/main/java/gg/data/user/UserImage.java b/gg-data/src/main/java/gg/data/user/UserImage.java new file mode 100644 index 000000000..ad4b2675a --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/UserImage.java @@ -0,0 +1,65 @@ +package gg.data.user; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import com.sun.istack.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Getter +public class UserImage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @NotNull + @Column(name = "image_uri") + private String imageUri; + + @NotNull + @Column(name = "created_at") + private LocalDateTime createdAt; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @NotNull + @Column(name = "is_current") + private Boolean isCurrent; + + public UserImage(User user, String imageUri, LocalDateTime createdAt, LocalDateTime deletedAt, Boolean isCurrent) { + this.user = user; + this.imageUri = imageUri; + this.createdAt = createdAt; + this.deletedAt = deletedAt; + this.isCurrent = isCurrent; + } + + public void updateIsCurrent() { + this.isCurrent = !this.isCurrent; + } + + public void updateDeletedAt(LocalDateTime deletedAt) { + this.deletedAt = deletedAt; + updateIsCurrent(); + } +} diff --git a/gg-data/src/main/java/gg/data/user/type/BackgroundType.java b/gg-data/src/main/java/gg/data/user/type/BackgroundType.java new file mode 100644 index 000000000..135c53626 --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/BackgroundType.java @@ -0,0 +1,52 @@ +package gg.data.user.type; + +import java.util.Random; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum BackgroundType { + BASIC(0), + COLOR1(1), + COLOR2(2), + COLOR3(3), + COLOR4(4), + COLOR5(5), + COLOR6(6), + COLOR7(7), + COLOR8(8), + COLOR9(9), + COLOR10(10), + COLOR11(11), + COLOR12(12), + COLOR13(13), + COLOR14(14), + COLOR15(15), + COLOR16(16); + + private final Integer code; + + public static BackgroundType getRandomBackgroundType() { + Random random = new Random(); + int tierInt = random.nextInt(100); + int colorInt; + + if (tierInt <= 50) { + colorInt = random.nextInt(100) % 4 + 1; + } else if (tierInt <= 70) { + colorInt = (random.nextInt(99) % 3) + 5; + } else if (tierInt <= 85) { + colorInt = (random.nextInt(99) % 3) + 8; + } else if (tierInt <= 95) { + colorInt = (random.nextInt(99) % 3) + 11; + } else { + colorInt = (random.nextInt(99) % 3) + 14; + } + + return BackgroundType.values()[colorInt]; + } + + public static BackgroundType of(String code) { + return BackgroundType.valueOf(code); + } +} diff --git a/gg-data/src/main/java/gg/data/user/type/EdgeType.java b/gg-data/src/main/java/gg/data/user/type/EdgeType.java new file mode 100644 index 000000000..6a6283875 --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/EdgeType.java @@ -0,0 +1,52 @@ +package gg.data.user.type; + +import java.util.Random; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum EdgeType { + BASIC(0), + COLOR1(1), + COLOR2(2), + COLOR3(3), + COLOR4(4), + COLOR5(5), + COLOR6(6), + COLOR7(7), + COLOR8(8), + COLOR9(9), + COLOR10(10), + COLOR11(11), + COLOR12(12), + COLOR13(13), + COLOR14(14), + COLOR15(15), + COLOR16(16); + + private final Integer code; + + public static EdgeType getRandomEdgeType() { + Random random = new Random(); + int tierInt = random.nextInt(100); + int colorInt; + + if (tierInt <= 50) { + colorInt = random.nextInt(100) % 4 + 1; + } else if (tierInt <= 70) { + colorInt = (random.nextInt(99) % 3) + 5; + } else if (tierInt <= 85) { + colorInt = (random.nextInt(99) % 3) + 8; + } else if (tierInt <= 95) { + colorInt = (random.nextInt(99) % 3) + 11; + } else { + colorInt = (random.nextInt(99) % 3) + 14; + } + + return EdgeType.values()[colorInt]; + } + + public static EdgeType of(String code) { + return EdgeType.valueOf(code); + } +} diff --git a/gg-data/src/main/java/gg/data/user/type/OauthType.java b/gg-data/src/main/java/gg/data/user/type/OauthType.java new file mode 100644 index 000000000..a41d16c5a --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/OauthType.java @@ -0,0 +1,40 @@ +package gg.data.user.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum OauthType { + KAKAO("kakao"), + FORTYTWO("fortyTwo"), + BOTH("both"); + + private final String code; + + @JsonCreator + public static OauthType getEnumFromValue(String value) { + for (OauthType e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } + + public static OauthType of(RoleType roleType, Long kakaoId) { + if (kakaoId == null) { + return OauthType.FORTYTWO; + } + if (roleType.equals(RoleType.GUEST)) { + return OauthType.KAKAO; + } + return OauthType.BOTH; + } +} diff --git a/gg-data/src/main/java/gg/data/user/type/RacketType.java b/gg-data/src/main/java/gg/data/user/type/RacketType.java new file mode 100644 index 000000000..baae5e934 --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/RacketType.java @@ -0,0 +1,32 @@ +package gg.data.user.type; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum RacketType { + PENHOLDER("PENHOLDER"), + SHAKEHAND("SHAKEHAND"), + DUAL("DUAL"), + NONE("NONE"); + + private final String code; + + @JsonCreator + public static RacketType getEnumFromValue(String value) { + for (RacketType e : values()) { + if (e.code.equals(value)) { + return e; + } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { + return e; + } + } + return null; + } + +} diff --git a/gg-data/src/main/java/gg/data/user/type/RoleType.java b/gg-data/src/main/java/gg/data/user/type/RoleType.java new file mode 100644 index 000000000..f4a5e11c5 --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/RoleType.java @@ -0,0 +1,26 @@ +package gg.data.user.type; + +import java.util.Arrays; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum RoleType { + + ADMIN("ROLE_ADMIN", "๊ด€๋ฆฌ์ž"), + USER("ROLE_USER", "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž"), + GUEST("ROLE_GUEST", "๊ฒŒ์ŠคํŠธ"); + + private final String key; + private final String displayName; + + public static RoleType of(String key) { + return Arrays.stream(RoleType.values()) + .filter(r -> r.getKey().equals(key)) + .findAny() + .orElse(USER); + } +} + diff --git a/gg-data/src/main/java/gg/data/user/type/SnsType.java b/gg-data/src/main/java/gg/data/user/type/SnsType.java new file mode 100644 index 000000000..e5c7fb036 --- /dev/null +++ b/gg-data/src/main/java/gg/data/user/type/SnsType.java @@ -0,0 +1,27 @@ +package gg.data.user.type; + +import java.util.Arrays; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum SnsType { + + NONE(0, "NONE"), + SLACK(1, "SLACK"), + EMAIL(2, "EMAIL"), + BOTH(3, "BOTH"); + + private final Integer value; + private final String code; + + public static SnsType of(String code) { + return Arrays.stream(SnsType.values()) + .filter(snsType -> snsType.getCode().equals(code)) + .findAny() + .orElse(SLACK); + } + +} diff --git a/gg-data/src/test/java/gg/data/tournament/TournamentUnitTest.java b/gg-data/src/test/java/gg/data/tournament/TournamentUnitTest.java new file mode 100644 index 000000000..555bc1bde --- /dev/null +++ b/gg-data/src/test/java/gg/data/tournament/TournamentUnitTest.java @@ -0,0 +1,426 @@ +package gg.data.tournament; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +@UnitTest +@DisplayName("TournamentUnitTest") +class TournamentUnitTest { + + List mockTournamentGames; + List mockTournamentUsers; + List tournaments; + + @BeforeEach + void setUp() { + mockTournamentGames = IntStream.range(0, 10) + .mapToObj(i -> mock(TournamentGame.class)) + .collect(Collectors.toCollection(ArrayList::new)); + + mockTournamentUsers = IntStream.range(0, 10) + .mapToObj(i -> mock(TournamentUser.class)) + .collect(Collectors.toCollection(ArrayList::new)); + + tournaments = IntStream.range(0, 10) + .mapToObj(i -> new Tournament("", "", LocalDateTime.now(), LocalDateTime.now(), + TournamentType.MASTER, TournamentStatus.END)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Nested + @DisplayName("AddTournamentGame") + class AddTournamentGame { + + @Test + @DisplayName("๋‹จ์ผ TournamentGame ์ถ”๊ฐ€ ์„ฑ๊ณต") + public void addSingleTournamentGameSuccess() { + //given + Tournament tournament = tournaments.get(0); + TournamentGame mockTournamentGame = mockTournamentGames.get(0); + + //when + tournament.addTournamentGame(mockTournamentGame); + + //then + assertEquals(1, tournament.getTournamentGames().size()); + assertEquals(mockTournamentGame, tournament.getTournamentGames().get(0)); + } + + @Test + @DisplayName("์ตœ๋Œ€ TournamentGame ์ถ”๊ฐ€ ์„ฑ๊ณต") + void addMultiTournamentGameSuccess() { + //given + Tournament tournament = tournaments.get(0); + + //when + IntStream.range(0, 7).forEach(i -> tournament.addTournamentGame(mockTournamentGames.get(i))); + + //then + assertEquals(7, tournament.getTournamentGames().size()); + IntStream.range(0, 7).forEach(i -> + assertEquals(mockTournamentGames.get(i), tournament.getTournamentGames().get(i))); + } + + @Test + @DisplayName("์ตœ๋Œ€ ์ด์ƒ์˜ TournamentGame ์ถ”๊ฐ€ ์‹คํŒจ") + void addExceedTournamentGameFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + IntStream.range(0, 7).forEach(i -> tournament.addTournamentGame(mockTournamentGames.get(i))); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.addTournamentGame(mockTournamentGames.get(7))); + assertEquals(ErrorCode.TOURNAMENT_GAME_EXCEED, businessException.getErrorCode()); + assertEquals(ErrorCode.TOURNAMENT_GAME_EXCEED.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("๋™์ผํ•œ TournamentGame ์ถ”๊ฐ€ ์‹คํŒจ") + void duplicatedTournamentGameAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + tournament.addTournamentGame(mockTournamentGames.get(0)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.addTournamentGame(mockTournamentGames.get(0))); + assertEquals(ErrorCode.TOURNAMENT_GAME_DUPLICATION, businessException.getErrorCode()); + assertEquals(ErrorCode.TOURNAMENT_GAME_DUPLICATION.getMessage(), + businessException.getMessage()); + } + + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + TournamentGame tournamentGame = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.addTournamentGame(tournamentGame)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + } + + @Nested + @DisplayName("AddTournamentUser") + class AddTournamentUser { + + @Test + @DisplayName("๋‹จ์ผ TournamentUser ์ถ”๊ฐ€ ์„ฑ๊ณต") + public void addSingleTournamentGameSuccess() { + //given + Tournament tournament = tournaments.get(0); + TournamentUser mockTournamentUser = mockTournamentUsers.get(0); + + //when + tournament.addTournamentUser(mockTournamentUser); + + //then + assertEquals(1, tournament.getTournamentUsers().size()); + assertEquals(mockTournamentUser, tournament.getTournamentUsers().get(0)); + } + + @Test + @DisplayName("์—ฌ๋Ÿฌ TournamentUser ์ถ”๊ฐ€ ์„ฑ๊ณต") + void addMultiTournamentGameSuccess() { + //given + Tournament tournament = tournaments.get(0); + + //when + IntStream.range(0, mockTournamentUsers.size()).forEach(i -> + tournament.addTournamentUser(mockTournamentUsers.get(i))); + + //then + assertEquals(mockTournamentUsers.size(), tournament.getTournamentUsers().size()); + IntStream.range(0, mockTournamentUsers.size()).forEach(i -> + assertEquals(mockTournamentUsers.get(i), tournament.getTournamentUsers().get(i))); + } + + @Test + @DisplayName("๋™์ผํ•œ TournamentUser ์ถ”๊ฐ€ ์‹คํŒจ") + void duplicatedTournamentGameAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + tournament.addTournamentUser(mockTournamentUsers.get(0)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.addTournamentUser(mockTournamentUsers.get(0))); + assertEquals(ErrorCode.TOURNAMENT_USER_DUPLICATION, businessException.getErrorCode()); + assertEquals(ErrorCode.TOURNAMENT_USER_DUPLICATION.getMessage(), + businessException.getMessage()); + } + + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + TournamentUser tournamentUser = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.addTournamentUser(tournamentUser)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + } + + @Nested + @DisplayName("DeleteTournamentUser") + class DeleteTournamentUser { + + @Test + @DisplayName("TournamentUser ์‚ญ์ œ ์„ฑ๊ณต") + public void addSingleTournamentGameSuccess() { + //given + Tournament tournament = tournaments.get(0); + TournamentUser mockTournamentUser = mockTournamentUsers.get(0); + tournament.addTournamentUser(mockTournamentUser); + + //when + tournament.deleteTournamentUser(mockTournamentUser); + + //then + assertEquals(0, tournament.getTournamentUsers().size()); + } + + @Test + @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” TournamentUser ์‚ญ์ œ ์‹คํŒจ") + void duplicatedTournamentGameAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + tournament.addTournamentUser(mockTournamentUsers.get(0)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.deleteTournamentUser(mockTournamentUsers.get(1))); + assertEquals(ErrorCode.TOURNAMENT_USER_NOT_FOUND, businessException.getErrorCode()); + assertEquals(ErrorCode.TOURNAMENT_USER_NOT_FOUND.getMessage(), + businessException.getMessage()); + } + + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + TournamentUser tournamentUser = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.deleteTournamentUser(tournamentUser)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + } + + @Nested + @DisplayName("UpdateWinner") + class UpdateWinner { + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + User user = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.updateWinner(user)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("์Šน์ž ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") + void updateSuccess() { + //given + Tournament tournament = tournaments.get(0); + User user = mock(User.class); + + //when + tournament.updateWinner(user); + + //then + assertEquals(user, tournament.getWinner()); + } + } + + @Nested + @DisplayName("UpdateStatus") + class UpdateStatus { + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + TournamentStatus status = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.updateStatus(status)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("์ƒํƒœ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") + void updateSuccess() { + //given + Tournament tournament = tournaments.get(0); + TournamentStatus status = TournamentStatus.LIVE; + + //when + tournament.updateStatus(status); + + //then + assertEquals(status, tournament.getStatus()); + } + } + + @Nested + @DisplayName("UpdateStatus") + class UpdateEndTime { + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Tournament tournament = tournaments.get(0); + + //when + LocalDateTime endTime = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> tournament.updateEndTime(endTime)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("endTime ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") + void updateEndTimeSuccess() { + //given + Tournament tournament = tournaments.get(0); + LocalDateTime endTime = LocalDateTime.now().withMinute(0).withNano(0); + + //when + tournament.updateEndTime(endTime); + + //then + assertEquals(endTime, tournament.getEndTime()); + } + } + + @Nested + @DisplayName("findTournamentUserByUserId") + class FindTournamentUserByUserId { + @Test + @DisplayName("Long null ์ „๋‹ฌ ์‹œ ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์—†์œผ๋ฉด exception") + void ifNullException() { + //given + Tournament tournament = tournaments.get(0); + TournamentUser tournamentUser = mockTournamentUsers.get(0); + tournament.getTournamentUsers().add(tournamentUser); + Long userId = null; + + //when, then + assertThrows(NullPointerException.class, () -> tournament.findTournamentUserByUserId(userId)); + } + + @Test + @DisplayName("Long null ์ „๋‹ฌ ์‹œ ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์žˆ์œผ๋ฉด Optional.null") + void ifNullOptionalNull() { + //given + Tournament tournament = tournaments.get(0); + Long userId = null; + + //when + Optional result = tournament.findTournamentUserByUserId(userId); + + //then + Assertions.assertThat(result).isEqualTo(Optional.empty()); + } + + @Test + @DisplayName("์กด์žฌํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์œ ์ €๋ฉด ๋ฐ˜ํ™˜") + void userFind() { + //given + Tournament tournament = tournaments.get(0); + TournamentUser tournamentUser = mockTournamentUsers.get(0); + tournament.getTournamentUsers().add(tournamentUser); + User user = mock(User.class); + when(user.getId()).thenReturn(1L); + when(tournamentUser.getUser()).thenReturn(user); + Long userId = 1L; + + //when + Optional result = tournament.findTournamentUserByUserId(userId); + + //then + Assertions.assertThat(result.get()).isEqualTo(tournamentUser); + } + + @Test + @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ† ๋„ˆ๋จผํŠธ ์œ ์ €๋ฉด optional.empty ๋ฐ˜ํ™˜") + void userNotFind() { + //given + Tournament tournament = tournaments.get(0); + TournamentUser tournamentUser = mockTournamentUsers.get(0); + User user = mock(User.class); + when(user.getId()).thenReturn(1L); + when(tournamentUser.getUser()).thenReturn(user); + tournament.getTournamentUsers().add(tournamentUser); + Long userId = 2L; + + //when + Optional result = tournament.findTournamentUserByUserId(userId); + + //then + Assertions.assertThat(result).isEqualTo(Optional.empty()); + } + } +} diff --git a/gg-pingpong-api/build.gradle b/gg-pingpong-api/build.gradle new file mode 100644 index 000000000..9edc92c20 --- /dev/null +++ b/gg-pingpong-api/build.gradle @@ -0,0 +1,53 @@ +plugins { + id 'java' +} + +group 'gg.api' +version '42gg' + +repositories { + mavenCentral() +} + +dependencies { + /* spring */ + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-mail' + annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' + + implementation 'org.springframework.session:spring-session-data-redis' + + /* oauth */ + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + + /* JSON Web Token */ + implementation 'io.jsonwebtoken:jjwt-api:0.11.2' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2' + + /* StringUtils */ + implementation 'org.apache.commons:commons-lang3:3.12.0' + + /* REST template */ + implementation 'org.apache.httpcomponents:httpcore:4.4.15' + implementation 'org.apache.httpcomponents:httpclient:4.5.13' + /* HttpHeaders */ + implementation 'com.google.guava:guava:31.0.1-jre' + + /* S3 Image Bucket */ + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + implementation 'org.springframework:spring-test:5.3.20' + implementation "com.amazonaws:aws-java-sdk-s3:1.12.281" + + testImplementation 'org.springframework.security:spring-security-test' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation testFixtures(project(':gg-utils')) +} + +test { + useJUnitPlatform() +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/PingpongApiApplication.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/PingpongApiApplication.java new file mode 100644 index 000000000..468f1ac8b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/PingpongApiApplication.java @@ -0,0 +1,14 @@ +package gg.pingpong.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = {"gg.admin.repo", "gg.data", "gg.repo", + "gg.pingpong.api", "gg.utils"}) +public class PingpongApiApplication { + + public static void main(String[] args) { + SpringApplication.run(PingpongApiApplication.class, args); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/GameAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/GameAdminController.java new file mode 100644 index 000000000..3391d8cb1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/GameAdminController.java @@ -0,0 +1,74 @@ +package gg.pingpong.api.admin.game.controller; + +import javax.validation.Valid; +import javax.validation.constraints.Positive; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.game.controller.response.GameLogListAdminResponseDto; +import gg.pingpong.api.admin.game.dto.GameUserLogAdminReqDto; +import gg.pingpong.api.admin.game.dto.RankGamePPPModifyReqDto; +import gg.pingpong.api.admin.game.service.GameAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.user.rank.redis.RankRedisService; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/games") +public class GameAdminController { + private final GameAdminService gameAdminService; + private final RankRedisService rankRedisService; + + @GetMapping + public GameLogListAdminResponseDto gameFindBySeasonId(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + int page = pageRequestDto.getPage(); + int size = pageRequestDto.getSize(); + + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("startTime").descending()); + return gameAdminService.findAllGamesByAdmin(pageable); + } + + /** + * ํŠน์ • ์œ ์ €์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ API + * @param reqDto intraId page size + * @return GameLogListAdminResponseDto gameLogList totalPage + */ + @GetMapping("/users") + public GameLogListAdminResponseDto gameFindByIntraId(@ModelAttribute GameUserLogAdminReqDto reqDto) { + + Pageable pageable = PageRequest.of(reqDto.getPage() - 1, reqDto.getSize()); + return gameAdminService.findGamesByIntraId(reqDto.getIntraId(), pageable); + } + + /** + * ๋žญํ‚น ์ ์ˆ˜ ์ˆ˜์ • API + * @param reqDto team1Id team1Score team2Id team2Score + * @param gameId ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ id + * @return ResponseEntity + * @throws InvalidParameterException ์ ์ˆ˜๊ฐ€ 3์ ์„ ์ดˆ๊ณผํ•˜๊ฑฐ๋‚˜, ๋‘ ํŒ€์˜ ์ ์ˆ˜๊ฐ€ ๊ฐ™์„ ๊ฒฝ์šฐ + */ + @PutMapping("/{gameId}") + public ResponseEntity gameResultEdit(@Valid @RequestBody RankGamePPPModifyReqDto reqDto, + @PathVariable @Positive Long gameId) { + if (reqDto.getTeam1Score() + reqDto.getTeam2Score() > 3 || reqDto.getTeam1Score() == reqDto.getTeam2Score()) { + throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); + } + gameAdminService.rankResultEdit(reqDto, gameId); + rankRedisService.updateAllTier(gameId); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/response/GameLogListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/response/GameLogListAdminResponseDto.java new file mode 100644 index 000000000..72e342644 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/controller/response/GameLogListAdminResponseDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.admin.game.controller.response; + +import java.util.List; + +import gg.pingpong.api.admin.game.dto.GameLogAdminDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class GameLogListAdminResponseDto { + private List gameLogList; + private int totalPage; + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameLogAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameLogAdminDto.java new file mode 100644 index 000000000..52f622d4c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameLogAdminDto.java @@ -0,0 +1,37 @@ +package gg.pingpong.api.admin.game.dto; + +import java.time.Duration; +import java.time.LocalDateTime; + +import gg.admin.repo.game.out.GameTeamUser; +import gg.data.game.type.StatusType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class GameLogAdminDto { + private Long gameId; + private LocalDateTime startAt; + private String slotTime; + private String mode; + private StatusType status; + private GameTeamAdminDto team1; + private GameTeamAdminDto team2; + + public GameLogAdminDto(GameTeamUser game) { + this.gameId = game.getGameId(); + this.startAt = game.getStartTime(); + this.slotTime = game.getEndTime() == null ? null : + String.valueOf( + Duration.between(game.getStartTime().toLocalTime(), game.getEndTime().toLocalTime()).toMinutes()); + this.mode = game.getMode().getCode(); + this.team1 = new GameTeamAdminDto(game.getT1IntraId(), game.getT1TeamId(), game.getT1Score(), + game.getT1IsWin()); + this.team2 = new GameTeamAdminDto(game.getT2IntraId(), game.getT2TeamId(), game.getT2Score(), + game.getT2IsWin()); + this.status = game.getStatus(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameTeamAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameTeamAdminDto.java new file mode 100644 index 000000000..757da8285 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameTeamAdminDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.admin.game.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class GameTeamAdminDto { + private String intraId1; + @JsonInclude(JsonInclude.Include.NON_NULL) + private String intraId2; //๋ณต์‹์ผ ๊ฒฝ์šฐ์—๋งŒ ์žˆ์Œ + private Long teamId; + private Integer score; + @JsonInclude(JsonInclude.Include.NON_NULL) + private Boolean win; + + public GameTeamAdminDto(String intraId, Long teamId, Integer score, Boolean win) { + this.intraId1 = intraId; + this.teamId = teamId; + this.score = score; + this.win = win; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameUserLogAdminReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameUserLogAdminReqDto.java new file mode 100644 index 000000000..ea4b42050 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/GameUserLogAdminReqDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.admin.game.dto; + +import javax.validation.constraints.NotNull; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; + +@Getter +public class GameUserLogAdminReqDto extends PageRequestDto { + @NotNull(message = "plz, intraId") + private String intraId; + + public GameUserLogAdminReqDto(String intraId, Integer page, Integer size) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/RankGamePPPModifyReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/RankGamePPPModifyReqDto.java new file mode 100644 index 000000000..20815eb7c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/dto/RankGamePPPModifyReqDto.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.admin.game.dto; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class RankGamePPPModifyReqDto { + @NotNull(message = "Team1Id ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long team1Id; + @NotNull(message = "Team1Score ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int team1Score; + @NotNull(message = "Team2Id ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long team2Id; + @NotNull(message = "Team2Score ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int team2Score; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/service/GameAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/service/GameAdminService.java new file mode 100644 index 000000000..26e581a1d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/game/service/GameAdminService.java @@ -0,0 +1,223 @@ +package gg.pingpong.api.admin.game.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import javax.persistence.EntityManager; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.game.GameAdminRepository; +import gg.admin.repo.game.PChangeAdminRepository; +import gg.admin.repo.game.TeamUserAdminRepository; +import gg.admin.repo.game.out.GameTeamUser; +import gg.admin.repo.season.SeasonAdminRepository; +import gg.admin.repo.user.UserAdminRepository; +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.admin.game.controller.response.GameLogListAdminResponseDto; +import gg.pingpong.api.admin.game.dto.GameLogAdminDto; +import gg.pingpong.api.admin.game.dto.RankGamePPPModifyReqDto; +import gg.pingpong.api.user.rank.redis.RankRedisService; +import gg.pingpong.api.user.rank.service.TierService; +import gg.pingpong.api.user.season.dto.CurSeason; +import gg.pingpong.api.user.season.service.SeasonService; +import gg.repo.game.PChangeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.utils.exception.game.GameNotExistException; +import gg.utils.exception.game.NotRecentlyGameException; +import gg.utils.exception.pchange.PChangeNotExistException; +import gg.utils.exception.season.SeasonNotFoundException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class GameAdminService { + + private final GameAdminRepository gameAdminRepository; + private final SeasonAdminRepository seasonAdminRepository; + private final UserAdminRepository userAdminRepository; + private final PChangeRepository pChangeRepository; + private final PChangeAdminRepository pChangeAdminRepository; + private final RankRedisService rankRedisService; + private final TeamUserAdminRepository teamUserAdminRepository; + private final RedisMatchUserRepository redisMatchUserRepository; + private final TierService tierService; + private final SeasonService seasonService; + private final EntityManager entityManager; + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ œ์™ธํ•œ ์ผ๋ฐ˜, ๋žญํฌ ๊ฒŒ์ž„๋“ค์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

+ * @param pageable + * @return + */ + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findAllGamesByAdmin(Pageable pageable) { + Page gamePage = gameAdminRepository.findAllByModeIn(pageable, List.of(Mode.NORMAL, Mode.RANK)); + return new GameLogListAdminResponseDto( + getGameLogList(gamePage.getContent().stream().map(Game::getId).collect(Collectors.toList())), + gamePage.getTotalPages()); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ œ์™ธํ•œ ํ•ด๋‹น ์‹œ์ฆŒ์˜ ์ผ๋ฐ˜, ๋žญํฌ ๊ฒŒ์ž„๋“ค์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

+ * @param pageable + * @return + */ + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findGamesBySeasonId(Long seasonId, Pageable pageable) { + Season season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + Page games = gameAdminRepository.findBySeasonAndModeIn(pageable, season, List.of(Mode.NORMAL, Mode.RANK)); + return new GameLogListAdminResponseDto( + getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.getTotalPages()); + } + + @Transactional(readOnly = true) + public List getGameLogList(List gameIdList) { + List teamViews = gameAdminRepository.findTeamsByGameIsIn(gameIdList); + return teamViews.stream().map(GameLogAdminDto::new).collect(Collectors.toList()); + } + + /** + * ํŠน์ • ์œ ์ €์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ (ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ œ์™ธ) + * @param intraId ์กฐํšŒํ•  ์œ ์ €์˜ intraId + * @param pageable page size + * @return GameLogListAdminResponseDto + * @throws UserNotFoundException intraId์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ €๊ฐ€ ์—†์„ ๊ฒฝ์šฐ + */ + @Transactional(readOnly = true) + public GameLogListAdminResponseDto findGamesByIntraId(String intraId, Pageable pageable) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + List pChangeList = pChangeRepository.findAllByUserIdGameModeIn(user.getId(), + List.of(Mode.NORMAL, Mode.RANK)); + List gameList = new ArrayList<>(); + + for (PChange pChange : pChangeList) { + gameList.add(pChange.getGame()); + } + + int start = (int)pageable.getOffset(); + int end = Math.min((start + pageable.getPageSize()), gameList.size()); + Page games = new PageImpl<>(gameList.subList(start, end), pageable, gameList.size()); + return new GameLogListAdminResponseDto( + getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.getTotalPages()); + } + + /** + * ๋žญํ‚น ์ ์ˆ˜ ์ˆ˜์ • + * @param reqDto team1Id team1Score team2Id team2Score + * @param gameId ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ id + * @throws GameNotExistException gameId์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์ž„์ด ์—†์„ ๊ฒฝ์šฐ + * @throws SeasonNotFoundException ๊ฒŒ์ž„์— ํ•ด๋‹นํ•˜๋Š” ์‹œ์ฆŒ์ด ์—†์„ ๊ฒฝ์šฐ + * @throws NotRecentlyGameException ๊ฒŒ์ž„์ด ๋‘๋ช… ๋‹ค ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„์ด ์•„๋‹ ๊ฒฝ์šฐ + */ + @Transactional + @Caching(evict = { + @CacheEvict(value = "rankGameListByIntra", allEntries = true), + @CacheEvict(value = "rankGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true), + @CacheEvict(value = "ranking", allEntries = true) + }) + public void rankResultEdit(RankGamePPPModifyReqDto reqDto, Long gameId) { + // ๊ฒŒ์ž„์ด ๋‘๋ช… ๋‹ค ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„์ธ์ง€ ํ™•์ธ (๊ทธ game์— ํ•ด๋‹นํ•˜๋Š” ํŒ€์ด ๋งž๋Š”์ง€ ํ™•์ธ) + List teamUsers = teamUserAdminRepository.findUsersByTeamIdIn( + List.of(reqDto.getTeam1Id(), reqDto.getTeam2Id())); + Game game = gameAdminRepository.findGameWithSeasonByGameId(gameId) + .orElseThrow(GameNotExistException::new); + CurSeason curSeason = seasonService.getCurSeason(); + if (!isRecentlyGame(teamUsers, gameId) || enrollSlots(teamUsers) || !game.getSeason() + .getId() + .equals(curSeason.getId())) { + throw new NotRecentlyGameException(); + } + // pchange ๊ฐ€์ ธ์™€์„œ rank ppp ์ด์ „ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์ƒˆ ์ ์ˆ˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐ + // user 1 + List pChanges = pChangeAdminRepository.findByTeamUser(teamUsers.get(0).getUser().getId()); + if (!pChanges.get(0).getGame().getId().equals(gameId)) { + throw new PChangeNotExistException(); + } + RankRedis rankRedis1 = rollbackGameResult(game.getSeason(), teamUsers.get(0), pChanges); + pChangeAdminRepository.deleteById(pChanges.get(0).getId()); + // user 2 + pChanges = pChangeAdminRepository.findByTeamUser(teamUsers.get(1).getUser().getId()); + if (!pChanges.get(0).getGame().getId().equals(gameId)) { + throw new PChangeNotExistException(); + } + RankRedis rankRedis2 = rollbackGameResult(game.getSeason(), teamUsers.get(1), pChanges); + pChangeAdminRepository.deleteById(pChanges.get(0).getId()); + entityManager.flush(); + for (int i = 0; i < teamUsers.size(); i++) { + updateScore(reqDto, teamUsers.get(i)); + } + teamUserAdminRepository.flush(); + rankRedisService.updateAdminRankData(teamUsers.get(0), teamUsers.get(1), game, rankRedis1, rankRedis2); + tierService.updateAllTier(game.getSeason()); + } + + private RankRedis rollbackGameResult(Season season, TeamUser teamUser, List pChanges) { + // pchange ppp๋„ update + // rankredis ์— ppp ๋‹ค์‹œ ๋ฐ˜์˜ + // rank zset ๋„ update + // ์ด์ „ ppp, exp ๋˜๋Œ๋ฆฌ๊ธฐ + // rank data ์— ์žˆ๋Š” ppp ๋˜๋Œ๋ฆฌ๊ธฐ + RankRedis rankRedis; + if (pChanges.size() == 1) { + rankRedis = rankRedisService.rollbackRank(teamUser, season.getStartPpp(), season.getId()); + teamUser.getUser().updateExp(0); + } else { + rankRedis = rankRedisService.rollbackRank(teamUser, pChanges.get(1).getPppResult(), season.getId()); + teamUser.getUser().updateExp(pChanges.get(1).getExp()); + } + return rankRedis; + } + + private void updateScore(RankGamePPPModifyReqDto reqDto, TeamUser teamUser) { + if (teamUser.getTeam().getId().equals(reqDto.getTeam1Id())) { + teamUser.getTeam().updateScore(reqDto.getTeam1Score(), reqDto.getTeam1Score() > reqDto.getTeam2Score()); + } else if (teamUser.getTeam().getId().equals(reqDto.getTeam2Id())) { + teamUser.getTeam().updateScore(reqDto.getTeam2Score(), reqDto.getTeam2Score() > reqDto.getTeam1Score()); + } + } + + private Boolean isRecentlyGame(List teamUsers, Long gameId) { + for (TeamUser teamUser : teamUsers) { + List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); + if (!pChanges.get(0).getGame().getId().equals(gameId)) { + return false; + } + } + return true; + } + + private Boolean enrollSlots(List teamUsers) { + for (TeamUser teamUser : teamUsers) { + Long userId = teamUser.getUser().getId(); + if (redisMatchUserRepository.countMatchTime(userId) > 0) { + return true; + } + if (gameAdminRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userId).isPresent()) { + return true; + } + } + return false; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/AnnouncementAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/AnnouncementAdminController.java new file mode 100644 index 000000000..7f9ef0498 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/AnnouncementAdminController.java @@ -0,0 +1,56 @@ +package gg.pingpong.api.admin.manage.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.manage.controller.response.AnnouncementAdminListResponseDto; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.pingpong.api.admin.manage.service.AnnouncementAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +@RequestMapping("pingpong/admin") +@Validated +public class AnnouncementAdminController { + private final AnnouncementAdminService announcementAdminService; + + @GetMapping("/announcement") + public ResponseEntity getAnnouncementList( + @ModelAttribute @Valid PageRequestDto anReq) { + + Pageable pageable = PageRequest.of(anReq.getPage() - 1, anReq.getSize(), Sort.by("createdAt").descending()); + + return ResponseEntity.ok() + .body(announcementAdminService.findAllAnnouncement(pageable)); + } + + @PostMapping("/announcement") + public ResponseEntity addAnnouncement(@Valid @RequestBody AnnouncementAdminAddDto addDto) { + announcementAdminService.addAnnouncement(addDto); + + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping("/announcement/{deleterIntraId}") + public ResponseEntity announcementModify(@PathVariable String deleterIntraId) { + announcementAdminService.modifyAnnouncementIsDel(deleterIntraId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/FeedbackAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/FeedbackAdminController.java new file mode 100644 index 000000000..48dd58025 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/FeedbackAdminController.java @@ -0,0 +1,60 @@ +package gg.pingpong.api.admin.manage.controller; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.manage.controller.request.FeedbackAdminPageRequestDto; +import gg.pingpong.api.admin.manage.controller.response.FeedbackListAdminResponseDto; +import gg.pingpong.api.admin.manage.service.FeedbackAdminService; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("pingpong/admin/feedback") +@RequiredArgsConstructor +@Validated +public class FeedbackAdminController { + private final FeedbackAdminService feedbackAdminService; + + /** + *

intraId ๊ฐ€ ์—†๋‹ค๋ฉด ์ „์ฒด, ์žˆ๋‹ค๋ฉด ํƒ€๊ฒŸ ์œ ์ €์˜ ํ”ผ๋“œ๋ฐฑ๋“ค์„ ๋ฐ˜ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.

+ * @param req dto + * @return FeedbackListAdminResponseDto + */ + @GetMapping + public ResponseEntity feedbackAll( + @ModelAttribute @Valid FeedbackAdminPageRequestDto req) { + if (req.getIntraId() == null) { + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("isSolved").and(Sort.by("createdAt"))); + return ResponseEntity.status(HttpStatus.OK).body(feedbackAdminService.findAllFeedback(pageable)); + } + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("isSolved").and(Sort.by("createdAt"))); + return ResponseEntity.status(HttpStatus.OK) + .body(feedbackAdminService.findByPartsOfIntraId(req.getIntraId(), pageable)); + } + + /** + *

ํƒ€๊ฒŸ ํ”ผ๋“œ๋ฐฑ์˜ ์ฒ˜๋ฆฌ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด์ค๋‹ˆ๋‹ค.

+ * @param feedbackId ํƒ€๊ฒŸ ํ”ผ๋“œ๋ฐฑ id + */ + @PatchMapping("/{feedbackId}") + public ResponseEntity feedbackIsSolvedToggle(@PathVariable @NotNull Long feedbackId) { + feedbackAdminService.toggleFeedbackIsSolvedByAdmin(feedbackId); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/PenaltyAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/PenaltyAdminController.java new file mode 100644 index 000000000..69375f5de --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/PenaltyAdminController.java @@ -0,0 +1,57 @@ +package gg.pingpong.api.admin.manage.controller; + +import javax.validation.Valid; +import javax.validation.constraints.Min; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +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 gg.pingpong.api.admin.manage.controller.request.PenaltyRequestDto; +import gg.pingpong.api.admin.manage.controller.response.PenaltyListResponseDto; +import gg.pingpong.api.admin.manage.service.PenaltyAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@Validated +@RequestMapping("/pingpong/admin/") +public class PenaltyAdminController { + private final PenaltyAdminService penaltyAdminService; + + @PostMapping("penalty") + public ResponseEntity givePenaltyToUser(@RequestBody @Valid PenaltyRequestDto requestDto) { + penaltyAdminService.givePenalty(requestDto.getIntraId(), requestDto.getPenaltyTime(), requestDto.getReason()); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @GetMapping("penalty") + public PenaltyListResponseDto getAllPenaltyUser(@ModelAttribute @Valid PageRequestDto pageRequestDto, + @RequestParam(required = false) String intraId, @RequestParam Boolean current) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("startTime").descending()); + if (intraId == null) { + return penaltyAdminService.getAllPenalties(pageable, current); + } + return penaltyAdminService.getAllPenaltiesByIntraId(pageable, intraId, current); + } + + @DeleteMapping("penalty/{penaltyId}") + public ResponseEntity releasePenaltyUser(@PathVariable @Min(1) Long penaltyId) { + penaltyAdminService.deletePenalty(penaltyId); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/SlotAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/SlotAdminController.java new file mode 100644 index 000000000..f885221e4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/SlotAdminController.java @@ -0,0 +1,45 @@ +package gg.pingpong.api.admin.manage.controller; + +import javax.validation.Valid; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.manage.controller.request.SlotCreateRequestDto; +import gg.pingpong.api.admin.manage.controller.response.SlotListAdminResponseDto; +import gg.pingpong.api.admin.manage.service.SlotAdminService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/slot-management") +public class SlotAdminController { + private final SlotAdminService slotAdminService; + + @GetMapping + public SlotListAdminResponseDto getSlotSetting() { + + return slotAdminService.getSlotSetting(); + } + + @PostMapping + public synchronized ResponseEntity addSlotSetting(@Valid @RequestBody SlotCreateRequestDto requestDto) { + slotAdminService.addSlotSetting(requestDto); + return new ResponseEntity(HttpStatus.CREATED); + } + + @DeleteMapping + public synchronized ResponseEntity delSlotSetting() { + slotAdminService.delSlotSetting(); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/FeedbackAdminPageRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/FeedbackAdminPageRequestDto.java new file mode 100644 index 000000000..80fbdb426 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/FeedbackAdminPageRequestDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.admin.manage.controller.request; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; + +@Getter +public class FeedbackAdminPageRequestDto extends PageRequestDto { + String intraId; + + public FeedbackAdminPageRequestDto(String intraId, Integer page, Integer size) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/PenaltyRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/PenaltyRequestDto.java new file mode 100644 index 000000000..abf067516 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/PenaltyRequestDto.java @@ -0,0 +1,20 @@ +package gg.pingpong.api.admin.manage.controller.request; + +import javax.validation.constraints.PositiveOrZero; + +import org.hibernate.validator.constraints.Length; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PenaltyRequestDto { + @Length(max = 30) + private String intraId; + @PositiveOrZero + private Integer penaltyTime; + private String reason; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/SlotCreateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/SlotCreateRequestDto.java new file mode 100644 index 000000000..2a6d6c9a1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/request/SlotCreateRequestDto.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.admin.manage.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SlotCreateRequestDto { + @NotNull(message = "Nothing pastSlotTime") + @PositiveOrZero(message = "plz. Positive Or Zero") + private Integer pastSlotTime; + + @NotNull(message = "Nothing futureSlotTime") + @PositiveOrZero(message = "plz. Positive Or Zero") + private Integer futureSlotTime; + + @NotNull(message = "Nothing interval") + @PositiveOrZero(message = "plz. Positive Or Zero") + private Integer interval; + + @NotNull(message = "Nothing openMinute") + @PositiveOrZero(message = "plz. Positive Or Zero") + private Integer openMinute; + + @NotNull(message = "Nothing startTime") + @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) + private LocalDateTime startTime; + + public void updateStartTime() { + LocalDateTime setStartTime = LocalDateTime.of( + this.startTime.getYear(), this.startTime.getMonth(), + this.startTime.getDayOfMonth(), this.startTime.getHour(), 0); + this.startTime = setStartTime; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminListResponseDto.java new file mode 100644 index 000000000..0b91213d6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class AnnouncementAdminListResponseDto { + private List announcementList; + private int totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminResponseDto.java new file mode 100644 index 000000000..4b71bffb3 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/AnnouncementAdminResponseDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.time.LocalDateTime; + +import gg.data.manage.Announcement; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class AnnouncementAdminResponseDto { + private String creatorIntraId; + private String deleterIntraId; + private String content; + private LocalDateTime createdAt; + private LocalDateTime modifiedAt; + private LocalDateTime deletedAt; + + public AnnouncementAdminResponseDto(Announcement announcementAdmin) { + this.content = announcementAdmin.getContent(); + this.creatorIntraId = announcementAdmin.getCreatorIntraId(); + this.deleterIntraId = announcementAdmin.getDeleterIntraId(); + this.createdAt = announcementAdmin.getCreatedAt(); + this.modifiedAt = announcementAdmin.getModifiedAt(); + this.deletedAt = announcementAdmin.getDeletedAt(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackAdminResponseDto.java new file mode 100644 index 000000000..1065e13c6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackAdminResponseDto.java @@ -0,0 +1,28 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.time.LocalDateTime; + +import gg.data.manage.Feedback; +import gg.data.manage.type.FeedbackType; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class FeedbackAdminResponseDto { + private Long id; + private String intraId; + private LocalDateTime createdAt; + private FeedbackType category; + private String content; + private Boolean isSolved; + + public FeedbackAdminResponseDto(Feedback feedback) { + this.id = feedback.getId(); + this.intraId = feedback.getUser().getIntraId(); + this.createdAt = feedback.getCreatedAt(); + this.category = feedback.getCategory(); + this.content = feedback.getContent(); + this.isSolved = feedback.getIsSolved(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackListAdminResponseDto.java new file mode 100644 index 000000000..6d0b2203d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/FeedbackListAdminResponseDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class FeedbackListAdminResponseDto { + private List feedbackList; + private int totalPage; + + public FeedbackListAdminResponseDto(List newDtos, int totalPage) { + this.feedbackList = newDtos; + this.totalPage = totalPage; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyListResponseDto.java new file mode 100644 index 000000000..28ecebbbf --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PenaltyListResponseDto { + List penaltyList; + Integer totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyUserResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyUserResponseDto.java new file mode 100644 index 000000000..155620215 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/PenaltyUserResponseDto.java @@ -0,0 +1,42 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.time.LocalDateTime; + +import gg.data.manage.Penalty; +import gg.data.manage.redis.RedisPenaltyUser; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PenaltyUserResponseDto { + private Long penaltyId; + private String intraId; + private String reason; + private LocalDateTime releaseTime; + + public PenaltyUserResponseDto(RedisPenaltyUser penaltyUser) { + this.intraId = penaltyUser.getIntraId(); + this.reason = penaltyUser.getReason(); + this.releaseTime = penaltyUser.getReleaseTime(); + } + + public PenaltyUserResponseDto(Penalty penalty) { + this.penaltyId = penalty.getId(); + this.intraId = penalty.getUser().getIntraId(); + this.reason = penalty.getMessage(); + this.releaseTime = penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()); + } + + @Override + public String toString() { + return "PenaltyUserResponseDto{" + + "penaltyId=" + penaltyId + ", intraId='" + + intraId + '\'' + ", reason='" + + reason + '\'' + ", releaseTime=" + + releaseTime + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/SlotListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/SlotListAdminResponseDto.java new file mode 100644 index 000000000..1010bc65a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/controller/response/SlotListAdminResponseDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.admin.manage.controller.response; + +import java.util.List; + +import gg.pingpong.api.admin.manage.dto.SlotAdminDto; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class SlotListAdminResponseDto { + List slotList; + + public SlotListAdminResponseDto(List slotList) { + this.slotList = slotList; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/AnnouncementAdminAddDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/AnnouncementAdminAddDto.java new file mode 100644 index 000000000..3e168a342 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/AnnouncementAdminAddDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.admin.manage.dto; + +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class AnnouncementAdminAddDto { + @NotNull(message = "plz. content") + private String content; + @NotNull(message = "plz. creatorIntraId") + private String creatorIntraId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/SlotAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/SlotAdminDto.java new file mode 100644 index 000000000..2fbc5ad5b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/dto/SlotAdminDto.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.admin.manage.dto; + +import java.time.LocalDateTime; + +import gg.data.manage.SlotManagement; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SlotAdminDto { + private Integer pastSlotTime; + + private Integer futureSlotTime; + + private Integer interval; + + private Integer openMinute; + + private LocalDateTime startTime; + + private LocalDateTime endTime; + + public SlotAdminDto(SlotManagement slotManagement) { + this.pastSlotTime = slotManagement.getPastSlotTime(); + this.futureSlotTime = slotManagement.getFutureSlotTime(); + this.interval = slotManagement.getGameInterval(); + this.openMinute = slotManagement.getOpenMinute(); + this.startTime = slotManagement.getStartTime(); + this.endTime = slotManagement.getEndTime(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/AnnouncementAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/AnnouncementAdminService.java new file mode 100644 index 000000000..7df2a2a4c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/AnnouncementAdminService.java @@ -0,0 +1,53 @@ +package gg.pingpong.api.admin.manage.service; + +import java.time.LocalDateTime; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.AnnouncementAdminRepository; +import gg.data.manage.Announcement; +import gg.pingpong.api.admin.manage.controller.response.AnnouncementAdminListResponseDto; +import gg.pingpong.api.admin.manage.controller.response.AnnouncementAdminResponseDto; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.utils.exception.announcement.AnnounceDupException; +import gg.utils.exception.announcement.AnnounceNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class AnnouncementAdminService { + private final AnnouncementAdminRepository announcementAdminRepository; + + @Transactional(readOnly = true) + public AnnouncementAdminListResponseDto findAllAnnouncement(Pageable pageable) { + Page allAnnouncements = announcementAdminRepository.findAll(pageable); + Page responseDtos = allAnnouncements.map(AnnouncementAdminResponseDto::new); + + return new AnnouncementAdminListResponseDto(responseDtos.getContent(), + responseDtos.getTotalPages()); + } + + @Transactional + public void addAnnouncement(AnnouncementAdminAddDto addDto) { + Announcement announcement = announcementAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(AnnounceNotFoundException::new); + if (announcement.getDeletedAt() == null) { + throw new AnnounceDupException(); + } + + announcementAdminRepository.save(Announcement.from(addDto.getContent(), addDto.getCreatorIntraId())); + } + + @Transactional + public void modifyAnnouncementIsDel(String deleterIntraId) { + Announcement announcement = announcementAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(AnnounceNotFoundException::new); + if (announcement.getDeletedAt() != null) { + throw new AnnounceNotFoundException(); + } + announcement.update(deleterIntraId, LocalDateTime.now()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/FeedbackAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/FeedbackAdminService.java new file mode 100644 index 000000000..e2004c3da --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/FeedbackAdminService.java @@ -0,0 +1,63 @@ +package gg.pingpong.api.admin.manage.service; + +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.FeedbackAdminRepository; +import gg.data.manage.Feedback; +import gg.pingpong.api.admin.manage.controller.response.FeedbackAdminResponseDto; +import gg.pingpong.api.admin.manage.controller.response.FeedbackListAdminResponseDto; +import gg.utils.exception.feedback.FeedbackNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class FeedbackAdminService { + private final FeedbackAdminRepository feedbackAdminRepository; + + /** + *

๋ชจ๋“  ํ”ผ๋“œ๋ฐฑ์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค

+ * @param pageable + * @return FeedbackListAdminResponseDto + */ + @Transactional(readOnly = true) + public FeedbackListAdminResponseDto findAllFeedback(Pageable pageable) { + Page feedbacks = feedbackAdminRepository.findAll(pageable); + Page feedbackAdminResponseDto = feedbacks.map(FeedbackAdminResponseDto::new); + + return new FeedbackListAdminResponseDto( + feedbackAdminResponseDto.getContent(), + feedbackAdminResponseDto.getTotalPages()); + } + + /** + *

ํ”ผ๋“œ๋ฐฑ ํ•ด๊ฒฐ์ƒํ™ฉ์„ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

+ * @param feedbackId ํƒ€๊ฒŸ ํ”ผ๋“œ๋ฐฑ id + */ + @Transactional + public void toggleFeedbackIsSolvedByAdmin(Long feedbackId) { + Feedback feedback = feedbackAdminRepository.findById(feedbackId).orElseThrow(FeedbackNotFoundException::new); + feedback.setIsSolved(!feedback.getIsSolved()); + } + + /** + *

ํƒ€๊ฒŸ ์œ ์ €์˜ ํ”ผ๋“œ๋ฐฑ์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

+ * @param intraId ํƒ€๊ฒŸ ์œ ์ € intraId + * @param pageable + * @return FeedbackListAdminResponseDto + */ + @Transactional(readOnly = true) + public FeedbackListAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { + List feedbackList = feedbackAdminRepository.findFeedbacksByUserIntraId(intraId); + Page feedbacks = new PageImpl<>(feedbackList, pageable, feedbackList.size()); + Page feedbackAdminResponseDto = feedbacks.map(FeedbackAdminResponseDto::new); + return new FeedbackListAdminResponseDto( + feedbackAdminResponseDto.getContent(), + feedbackAdminResponseDto.getTotalPages()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/PenaltyAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/PenaltyAdminService.java new file mode 100644 index 000000000..b98cb933f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/PenaltyAdminService.java @@ -0,0 +1,111 @@ +package gg.pingpong.api.admin.manage.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.PenaltyAdminRepository; +import gg.admin.repo.manage.PenaltyUserAdminRedisRepository; +import gg.data.manage.Penalty; +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.manage.type.PenaltyType; +import gg.data.user.User; +import gg.pingpong.api.admin.manage.controller.response.PenaltyListResponseDto; +import gg.pingpong.api.admin.manage.controller.response.PenaltyUserResponseDto; +import gg.pingpong.api.user.user.service.UserFindService; +import gg.utils.exception.penalty.PenaltyExpiredException; +import gg.utils.exception.penalty.PenaltyNotFoundException; +import gg.utils.exception.penalty.RedisPenaltyUserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class PenaltyAdminService { + private final PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; + private final UserFindService userFindService; + private final PenaltyAdminRepository penaltyRepository; + + @Transactional + public void givePenalty(String intraId, Integer penaltyTime, String reason) { + User user = userFindService.findByIntraId(intraId); + Optional redisPenaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + LocalDateTime releaseTime; + RedisPenaltyUser penaltyUser; + Penalty penalty; + LocalDateTime now = LocalDateTime.now(); + if (redisPenaltyUser.isPresent()) { + releaseTime = redisPenaltyUser.get().getReleaseTime().plusHours(penaltyTime); + penaltyUser = new RedisPenaltyUser(intraId, redisPenaltyUser.get().getPenaltyTime() + penaltyTime * 60, + releaseTime, redisPenaltyUser.get().getStartTime(), reason); + penalty = new Penalty(user, PenaltyType.NOSHOW, reason, redisPenaltyUser.get().getReleaseTime(), + penaltyTime * 60); + } else { + releaseTime = now.plusHours(penaltyTime); + penaltyUser = new RedisPenaltyUser(intraId, penaltyTime * 60, releaseTime, now, reason); + penalty = new Penalty(user, PenaltyType.NOSHOW, reason, now, penaltyTime * 60); + } + penaltyRepository.save(penalty); + penaltyUserAdminRedisRepository.addPenaltyUser(penaltyUser, releaseTime); + } + + @Transactional(readOnly = true) + public PenaltyListResponseDto getAllPenalties(Pageable pageable, Boolean current) { + Page allPenalties; + if (current) { + allPenalties = penaltyRepository.findAllCurrent(pageable, LocalDateTime.now()); + } else { + allPenalties = penaltyRepository.findAll(pageable); + } + Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); + return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + @Transactional + public void deletePenalty(Long penaltyId) { + Penalty penalty = penaltyRepository.findById(penaltyId).orElseThrow(() + -> new PenaltyNotFoundException()); + if (penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()).isBefore(LocalDateTime.now())) { + throw new PenaltyExpiredException(); + } + RedisPenaltyUser penaltyUser = penaltyUserAdminRedisRepository + .findByIntraId(penalty.getUser().getIntraId()).orElseThrow(() + -> new RedisPenaltyUserNotFoundException()); + penaltyUserAdminRedisRepository.deletePenaltyInUser(penaltyUser, + penalty.getPenaltyTime()); //redis ์‹œ๊ฐ„ ์ค„์—ฌ์ฃผ๊ธฐ + //๋’ค์— ์žˆ๋Š” penalty ์‹œ๊ฐ„ ๋‹น๊ฒจ์ฃผ๊ธฐ + modifyStartTimeOfAfterPenalties(penalty); + penaltyRepository.delete(penalty); + } + + @Transactional(readOnly = true) + public PenaltyListResponseDto getAllPenaltiesByIntraId(Pageable pageable, String intraId, Boolean current) { + Page allPenalties; + if (current) { + allPenalties = penaltyRepository.findAllCurrentByIntraId(pageable, LocalDateTime.now(), intraId); + } else { + allPenalties = penaltyRepository.findAllByIntraId(pageable, intraId); + } + Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); + return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + private void modifyStartTimeOfAfterPenalties(Penalty penalty) { + List afterPenalties = penaltyRepository.findAfterPenaltiesByUser(penalty.getUser().getId(), + penalty.getStartTime()); + LocalDateTime newStartTime; + if (penalty.getStartTime().isAfter(LocalDateTime.now())) { + newStartTime = penalty.getStartTime(); + } else { + newStartTime = LocalDateTime.now(); + } + for (Penalty afterPenalty : afterPenalties) { + afterPenalty.updateStartTime(newStartTime); + newStartTime = newStartTime.plusMinutes(afterPenalty.getPenaltyTime()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/SlotAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/SlotAdminService.java new file mode 100644 index 000000000..fbb735a00 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/manage/service/SlotAdminService.java @@ -0,0 +1,91 @@ +package gg.pingpong.api.admin.manage.service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.AdminSlotManagementsRepository; +import gg.data.manage.SlotManagement; +import gg.pingpong.api.admin.manage.controller.request.SlotCreateRequestDto; +import gg.pingpong.api.admin.manage.controller.response.SlotListAdminResponseDto; +import gg.pingpong.api.admin.manage.dto.SlotAdminDto; +import gg.utils.exception.slotmanagement.SlotManagementForbiddenException; +import gg.utils.exception.slotmanagement.SlotManagementNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SlotAdminService { + private final AdminSlotManagementsRepository adminSlotManagementRepository; + + @Transactional(readOnly = true) + public SlotListAdminResponseDto getSlotSetting() { + List slotManagements = adminSlotManagementRepository.findAfterNowSlotManagement( + LocalDateTime.now()); + List dtoList = new ArrayList<>(); + for (SlotManagement slot : slotManagements) { + SlotAdminDto dto = new SlotAdminDto(slot); + dtoList.add(dto); + } + return new SlotListAdminResponseDto(dtoList); + } + + @Transactional + public void addSlotSetting(SlotCreateRequestDto requestDto) { + checkVaildSlotManagement(requestDto); + requestDto.updateStartTime(); + updateNowSlotManagementEndTime(requestDto.getStartTime()); + SlotManagement slotManagement = new SlotManagement(requestDto.getPastSlotTime(), requestDto.getFutureSlotTime(), + requestDto.getInterval(), requestDto.getOpenMinute(), requestDto.getStartTime()); + + adminSlotManagementRepository.save(slotManagement); + } + + @Transactional + public void delSlotSetting() { + List slotManagements = adminSlotManagementRepository.findAfterNowSlotManagement( + LocalDateTime.now()); + + SlotManagement slotManagement = slotManagements.get(0); + if (LocalDateTime.now().isAfter(slotManagement.getStartTime())) { + throw new SlotManagementForbiddenException(); + } + adminSlotManagementRepository.delete(slotManagement); + + SlotManagement beforeSlotManagement = slotManagements.get(1); + beforeSlotManagement.setNullEndTime(); + } + + private void checkVaildSlotManagement(SlotCreateRequestDto requestDto) { + if (requestDto.getPastSlotTime() > 23) { + throw new SlotManagementForbiddenException(); + } + if (requestDto.getFutureSlotTime() > 12) { + throw new SlotManagementForbiddenException(); + } + if (60 % requestDto.getInterval() != 0 || requestDto.getInterval() % 5 != 0) { + throw new SlotManagementForbiddenException(); + } + if (requestDto.getPastSlotTime() > requestDto.getInterval()) { + throw new SlotManagementForbiddenException(); + } + } + + private void updateNowSlotManagementEndTime(LocalDateTime endTime) { + SlotManagement nowSlotManagement = adminSlotManagementRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new SlotManagementNotFoundException()); + + LocalDateTime nowFutureSlotTime = LocalDateTime.now().isAfter(nowSlotManagement.getStartTime()) + ? LocalDateTime.now().plusHours(nowSlotManagement.getFutureSlotTime()) + : nowSlotManagement.getStartTime().plusHours(nowSlotManagement.getFutureSlotTime()); + + if (nowFutureSlotTime.isAfter(endTime)) { + throw new SlotManagementForbiddenException(); + } + + nowSlotManagement.updateEndTime(endTime); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/NotiAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/NotiAdminController.java new file mode 100644 index 000000000..7c37774c4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/NotiAdminController.java @@ -0,0 +1,48 @@ +package gg.pingpong.api.admin.noti.controller; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.noti.controller.request.NotiListAdminRequestDto; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.controller.response.NotiListAdminResponseDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +@RequestMapping(value = "/pingpong/admin/notifications") +public class NotiAdminController { + + private final NotiAdminService notiAdminService; + + @GetMapping + public NotiListAdminResponseDto getAllNoti(@ModelAttribute NotiListAdminRequestDto requestDto) { + int page = requestDto.getPage(); + int size = requestDto.getSize(); + String intraId = requestDto.getIntraId(); + + Pageable pageable = PageRequest.of(page - 1, size, + Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending())); + if (intraId == null) { + return notiAdminService.getAllNoti(pageable); + } else { + return notiAdminService.getFilteredNotifications(pageable, intraId); + } + } + + @PostMapping + public ResponseEntity sendNotiToUser(@RequestBody SendNotiAdminRequestDto sendNotiAdminRequestDto) { + notiAdminService.sendAnnounceNotiToUser(sendNotiAdminRequestDto); + return new ResponseEntity(HttpStatus.CREATED); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/NotiListAdminRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/NotiListAdminRequestDto.java new file mode 100644 index 000000000..2d545d127 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/NotiListAdminRequestDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.admin.noti.controller.request; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class NotiListAdminRequestDto extends PageRequestDto { + private String intraId; + + public NotiListAdminRequestDto(Integer page, Integer size, String intraId) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/SendNotiAdminRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/SendNotiAdminRequestDto.java new file mode 100644 index 000000000..54ccfd78f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/request/SendNotiAdminRequestDto.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.admin.noti.controller.request; + +import java.util.Objects; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SendNotiAdminRequestDto { + + @NotNull + private String intraId; + + @NotNull + @Size(max = 255) + private String message; + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof SendNotiAdminRequestDto)) { + return false; + } + SendNotiAdminRequestDto other = (SendNotiAdminRequestDto)obj; + return Objects.equals(message, other.message); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/response/NotiListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/response/NotiListAdminResponseDto.java new file mode 100644 index 000000000..88c084f9d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/controller/response/NotiListAdminResponseDto.java @@ -0,0 +1,39 @@ +package gg.pingpong.api.admin.noti.controller.response; + +import java.util.List; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import gg.pingpong.api.admin.noti.dto.NotiAdminDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class NotiListAdminResponseDto { + private List notiList; + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer totalPage; + + @Override + public String toString() { + return "NotiListResponseDto{" + + "notifications=" + notiList + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + NotiListAdminResponseDto other = (NotiListAdminResponseDto)obj; + return Objects.equals(notiList, other.notiList); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/dto/NotiAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/dto/NotiAdminDto.java new file mode 100644 index 000000000..d55960ed4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/dto/NotiAdminDto.java @@ -0,0 +1,63 @@ +package gg.pingpong.api.admin.noti.dto; + +import java.time.LocalDateTime; +import java.util.Objects; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class NotiAdminDto { + private Long id; + private String intraId; + private NotiType type; + private Boolean isChecked; + private String message; + private LocalDateTime createdAt; + + public NotiAdminDto(Noti noti) { + if (noti != null) { + this.id = noti.getId(); + this.intraId = noti.getUser().getIntraId(); + this.type = noti.getType(); + this.isChecked = noti.getIsChecked(); + this.message = noti.getMessage(); + this.createdAt = noti.getCreatedAt(); + } + } + + @Override + public String toString() { + return "NotiAdminDto{" + + "id=" + id + + ", user=" + intraId + + ", type=" + type + + ", isChecked=" + isChecked + + ", message='" + message + '\'' + + ", creatdDate=" + createdAt + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof NotiAdminDto)) { + return false; + } + NotiAdminDto other = (NotiAdminDto)obj; + return Objects.equals(id, other.id) + && Objects.equals(intraId, other.intraId) + && Objects.equals(type, other.type) + && Objects.equals(isChecked, other.isChecked) + && Objects.equals(message, other.message) + && Objects.equals(createdAt, other.createdAt); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/service/NotiAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/service/NotiAdminService.java new file mode 100644 index 000000000..1982e1bc1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/noti/service/NotiAdminService.java @@ -0,0 +1,68 @@ +package gg.pingpong.api.admin.noti.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.noti.NotiAdminRepository; +import gg.admin.repo.user.UserAdminRepository; +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.controller.response.NotiListAdminResponseDto; +import gg.pingpong.api.admin.noti.dto.NotiAdminDto; +import gg.pingpong.api.user.noti.service.SnsNotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.user.UserNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class NotiAdminService { + private final NotiAdminRepository notiAdminRepository; + private final UserAdminRepository userAdminRepository; + private final SnsNotiService snsNotiService; + + /** + * ์œ ์ €์—๊ฒŒ ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + * @param sendNotiAdminRequestDto ์•Œ๋ฆผ ์š”์ฒญ Dto + * @exception UserNotFoundException ์œ ์ €๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public void sendAnnounceNotiToUser(SendNotiAdminRequestDto sendNotiAdminRequestDto) { + String message = sendNotiAdminRequestDto.getMessage(); + String intraId = sendNotiAdminRequestDto.getIntraId(); + + User user = userAdminRepository.findByIntraId(intraId) + .orElseThrow(UserNotFoundException::new); + Noti noti = notiAdminRepository.save(new Noti(user, NotiType.ANNOUNCE, message, false)); + snsNotiService.sendSnsNotification(noti, UserDto.from(user)); + } + + /** + * ์ „์ฒด ์•Œ๋ฆผ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. + * @param pageable ์•Œ๋ฆผ ๋ชฉ๋ก ํŽ˜์ด์ง€ + * @return ์•Œ๋ฆผ ๋ชฉ๋ก ์‘๋‹ต Dto + */ + @Transactional(readOnly = true) + public NotiListAdminResponseDto getAllNoti(Pageable pageable) { + Page allNotiPage = notiAdminRepository.findAll(pageable); + Page notiAdminDtoPage = allNotiPage.map(NotiAdminDto::new); + return new NotiListAdminResponseDto(notiAdminDtoPage.getContent(), notiAdminDtoPage.getTotalPages()); + } + + /** + * ํŠน์ • ์œ ์ €์˜ ์•Œ๋ฆผ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. + * @param pageable ์œ ์ €์˜ ์•Œ๋ฆผ ๋ชฉ๋ก ํŽ˜์ด์ง€ + * @param intraId ์ธํŠธ๋ผ Id + * @return ์•Œ๋ฆผ ๋ชฉ๋ก ์‘๋‹ต Dto + */ + @Transactional(readOnly = true) + public NotiListAdminResponseDto getFilteredNotifications(Pageable pageable, String intraId) { + Page findNotis = notiAdminRepository.findNotisByUserIntraId(pageable, intraId); + Page notiResponseDtoPage = findNotis.map(NotiAdminDto::new); + return new NotiListAdminResponseDto(notiResponseDtoPage.getContent(), notiResponseDtoPage.getTotalPages()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankAdminService.java new file mode 100644 index 000000000..eef02cdc5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankAdminService.java @@ -0,0 +1,61 @@ +package gg.pingpong.api.admin.rank.service; + +import static gg.data.user.type.RoleType.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.user.UserAdminRepository; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.season.SeasonRepository; +import gg.utils.exception.season.SeasonForbiddenException; +import gg.utils.exception.season.SeasonTimeBeforeException; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class RankAdminService { + private final RankRepository rankRepository; + private final UserAdminRepository userAdminRepository; + private final SeasonRepository seasonRepository; + private final TierRepository tierRepository; + + @Transactional + public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { + if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) { + throw new SeasonTimeBeforeException(); + } + List users = userAdminRepository.findAll(); + + List ranks = new ArrayList<>(); + Season season = seasonRepository.findById(seasonAdminDto.getSeasonId()).get(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + users.forEach(user -> { + if (user.getRoleType() != GUEST) { + Rank userRank = Rank.from(user, season, seasonAdminDto.getStartPpp(), tier); + ranks.add(userRank); + } + }); + rankRepository.saveAll(ranks); + } + + @Transactional + public void deleteAllUserRankBySeason(SeasonAdminDto seasonAdminDto) { + if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) { + throw new SeasonForbiddenException(); + } + + rankRepository.deleteAllBySeasonId(seasonAdminDto.getSeasonId()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankRedisAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankRedisAdminService.java new file mode 100644 index 000000000..1c903d6ad --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/rank/service/RankRedisAdminService.java @@ -0,0 +1,63 @@ +package gg.pingpong.api.admin.rank.service; + +import static gg.data.user.type.RoleType.*; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.user.User; +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class RankRedisAdminService { + private final UserRepository userRepository; + private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; + + @Transactional + public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { + List users = userRepository.findAll(); + + String redisHashKey = RedisKeyManager.getHashKey(seasonAdminDto.getSeasonId()); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + + users.forEach(user -> { + if (user.getRoleType() != GUEST) { + RankRedis userRank = RankRedis.from(user.getId(), user.getIntraId(), user.getTextColor(), + seasonAdminDto.getStartPpp(), tier.getImageUri()); + + rankRedisRepository.addRankData(redisHashKey, user.getId(), userRank); + } + }); + } + + @Transactional + public void deleteSeasonRankBySeasonId(Long seasonId) { + String redisHashKey = RedisKeyManager.getHashKey(seasonId); + + rankRedisRepository.deleteHashKey(redisHashKey); + } + + public void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { + rankRedisRepository.updateRankData(hashKey, userId, userRank); + if (userPlayedRank(userRank)) { + rankRedisRepository.deleteFromZSet(zsetKey, userId); + rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); + } + } + + private boolean userPlayedRank(RankRedis userRank) { + return (userRank.getWins() + userRank.getLosses()) != 0; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/SeasonAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/SeasonAdminController.java new file mode 100644 index 000000000..b7d4f4634 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/SeasonAdminController.java @@ -0,0 +1,59 @@ +package gg.pingpong.api.admin.season.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.season.controller.request.SeasonCreateRequestDto; +import gg.pingpong.api.admin.season.controller.request.SeasonUpdateRequestDto; +import gg.pingpong.api.admin.season.controller.response.SeasonListAdminResponseDto; +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import gg.pingpong.api.admin.season.service.SeasonAdminService; +import lombok.AllArgsConstructor; + +@RestController +@RequestMapping(value = "/pingpong/admin") +@AllArgsConstructor +public class SeasonAdminController { + private final SeasonAdminService seasonAdminService; + + @GetMapping(value = "/seasons") + public SeasonListAdminResponseDto rankSeasonList() { + List seasons = seasonAdminService.findAllSeasons(); + + return new SeasonListAdminResponseDto(seasons); + } + + @PostMapping(value = "/seasons") + public synchronized ResponseEntity createSeason(@Valid @RequestBody SeasonCreateRequestDto seasonCreateReqeustDto) { + seasonAdminService.createSeason(seasonCreateReqeustDto); + + return new ResponseEntity(HttpStatus.CREATED); + } + + @DeleteMapping(value = "/seasons/{seasonId}") + public synchronized ResponseEntity deleteSeason(@PathVariable Long seasonId) { + seasonAdminService.deleteSeason(seasonId); + + return new ResponseEntity(HttpStatus.NO_CONTENT); + } + + @PutMapping(value = "/seasons/{seasonId}") + public synchronized ResponseEntity updateSeason(@PathVariable Long seasonId, + @RequestBody SeasonUpdateRequestDto seasonUpdateRequestDto) { + seasonAdminService.updateSeason(seasonId, seasonUpdateRequestDto); + + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonCreateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonCreateRequestDto.java new file mode 100644 index 000000000..484f5a65d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonCreateRequestDto.java @@ -0,0 +1,50 @@ +package gg.pingpong.api.admin.season.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotNull; + +import org.springframework.format.annotation.DateTimeFormat; + +import gg.data.season.Season; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SeasonCreateRequestDto { + @NotNull(message = "plz. seasonName") + private String seasonName; + + @NotNull(message = "plz. startTime") + @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) + private LocalDateTime startTime; + + @NotNull(message = "plz. startPpp") + private Integer startPpp; + + @NotNull(message = "plz. pppGap") + private Integer pppGap; + + public Season toSeason() { + return Season.builder() + .seasonName(seasonName) + .startTime(startTime) + .startPpp(startPpp) + .pppGap(pppGap) + .build(); + } + + public String toString() { + return "SeasonCreateRequestAdminDto{" + '\'' + + "seasonName=" + seasonName + '\'' + + ", startTime=" + startTime + + ", startPpp='" + startPpp + '\'' + + ", pppGap='" + pppGap + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonUpdateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonUpdateRequestDto.java new file mode 100644 index 000000000..dcb48ca09 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/request/SeasonUpdateRequestDto.java @@ -0,0 +1,32 @@ +package gg.pingpong.api.admin.season.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotNull; + +import org.springframework.format.annotation.DateTimeFormat; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SeasonUpdateRequestDto { + @NotNull(message = "plz. seasonName") + private String seasonName; + + @NotNull(message = "plz. startTime") + @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) + private LocalDateTime startTime; + + @NotNull(message = "plz. startPpp") + private Integer startPpp; + + @NotNull(message = "plz. pppGap") + private Integer pppGap; + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/response/SeasonListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/response/SeasonListAdminResponseDto.java new file mode 100644 index 000000000..673630738 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/controller/response/SeasonListAdminResponseDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.admin.season.controller.response; + +import java.util.List; + +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class SeasonListAdminResponseDto { + List seasonList; + + public SeasonListAdminResponseDto(List seasonList) { + this.seasonList = seasonList; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/dto/SeasonAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/dto/SeasonAdminDto.java new file mode 100644 index 000000000..b65c3070d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/dto/SeasonAdminDto.java @@ -0,0 +1,45 @@ +package gg.pingpong.api.admin.season.dto; + +import java.time.LocalDateTime; + +import gg.data.season.Season; +import gg.pingpong.api.admin.season.type.SeasonStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SeasonAdminDto { + + private Long seasonId; + private String seasonName; + private LocalDateTime startTime; + private LocalDateTime endTime; + private Integer startPpp; + private Integer pppGap; + private String status; + + public SeasonAdminDto(Season season) { + this.seasonId = season.getId(); + this.seasonName = season.getSeasonName(); + this.startTime = season.getStartTime(); + this.endTime = season.getEndTime(); + this.startPpp = season.getStartPpp(); + this.pppGap = season.getPppGap(); + this.status = getSeasonStatus(season); + } + + public String getSeasonStatus(Season season) { + LocalDateTime now = LocalDateTime.now(); + + if (now.isAfter(season.getEndTime())) { + return SeasonStatus.SEASON_PAST.getSeasonStatus(); + } else if (now.isAfter(season.getStartTime()) && now.isBefore((season.getEndTime()))) { + return SeasonStatus.SEASON_CURRENT.getSeasonStatus(); + } else { + return SeasonStatus.SEASON_FUTURE.getSeasonStatus(); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/service/SeasonAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/service/SeasonAdminService.java new file mode 100644 index 000000000..639439fe2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/service/SeasonAdminService.java @@ -0,0 +1,213 @@ +package gg.pingpong.api.admin.season.service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.season.SeasonAdminRepository; +import gg.data.season.Season; +import gg.pingpong.api.admin.rank.service.RankAdminService; +import gg.pingpong.api.admin.rank.service.RankRedisAdminService; +import gg.pingpong.api.admin.season.controller.request.SeasonCreateRequestDto; +import gg.pingpong.api.admin.season.controller.request.SeasonUpdateRequestDto; +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import gg.utils.exception.season.SeasonForbiddenException; +import gg.utils.exception.season.SeasonNotFoundException; +import gg.utils.exception.season.SeasonTimeBeforeException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class SeasonAdminService { + private final SeasonAdminRepository seasonAdminRepository; + private final RankRedisAdminService rankRedisAdminService; + private final RankAdminService rankAdminService; + + /** + *

๋ชจ๋“  ์‹œ์ฆŒ์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

+ * @return + */ + public List findAllSeasons() { + List seasons = seasonAdminRepository.findAllByOrderByStartTimeDesc(); + List dtoList = new ArrayList<>(); + for (Season season : seasons) { + SeasonAdminDto dto = new SeasonAdminDto(season); + dtoList.add(dto); + } + return dtoList; + } + + /** + *

ํ˜„์žฌ ์‹œ๊ฐ„๋ณด๋‹ค ์ดํ›„์˜ ์‹œ๊ฐ„์— ์‹œ์ž‘ํ•˜๋Š” ์ƒˆ๋กœ์šด ์‹œ์ฆŒ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

+ *

์ƒˆ๋กœ์šด ์‹œ์ฆŒ์„ ์˜ˆ์•ฝํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ์˜ˆ์•ฝ ์ค‘์ธ ์‹œ์ฆŒ์ด ์—ฌ๋Ÿฌ๊ฐœ์ผ ์ˆ˜ ๋„ ์žˆ๋‹ค.

+ * @param createDto dto + */ + @Transactional + public void createSeason(SeasonCreateRequestDto createDto) { + + Season newSeason = createDto.toSeason(); + + insert(newSeason); + seasonAdminRepository.save(newSeason); + + checkSeasonAtDB(); + + SeasonAdminDto seasonAdminDto = new SeasonAdminDto(newSeason); + rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); + rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); + } + + /** + *

ํƒ€๊ฒŸ ์‹œ์ฆŒ์„ ์ฐพ๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

+ * @param seasonId ํƒ€๊ฒŸ ์‹œ์ฆŒ ์•„์ด๋”” + * @return + */ + @Transactional + public SeasonAdminDto findSeasonById(Long seasonId) { + Season season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + + return new SeasonAdminDto(season); + } + + /** + *

์˜ˆ์•ฝ๋œ ์‹œ์ฆŒ์„ ์‚ญ์ œํ•œ๋‹ค.

+ * @param seasonId ํƒ€๊ฒŸ ์˜ˆ์•ฝ ์‹œ์ฆŒ ์•„์ด๋”” + */ + @Transactional + public void deleteSeason(Long seasonId) { + Season season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + detach(season); + SeasonAdminDto seasonDto = new SeasonAdminDto(season); + rankAdminService.deleteAllUserRankBySeason(seasonDto); + rankRedisAdminService.deleteSeasonRankBySeasonId(seasonId); + seasonAdminRepository.delete(season); + checkSeasonAtDB(); + } + + /** + *

์˜ˆ์•ฝ๋œ ์‹œ์ฆŒ์„ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

+ *

ํ˜„์žฌ ์‹œ์ฆŒ์€ ์ˆ˜์ • ๋ฒ„ํŠผ์ด ์žˆ์ง€๋งŒ ๊ตฌํ˜„์ด ์•ˆ๋˜์–ด ์žˆ์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•จ. -> ์ถ”ํ›„ ์ˆ˜์ •ํ•ด์•ผํ•จ

+ * @param seasonId + * @param updateDto + */ + @Transactional + public void updateSeason(Long seasonId, SeasonUpdateRequestDto updateDto) { + Season season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + + if (LocalDateTime.now().isAfter(season.getStartTime())) { + throw new SeasonForbiddenException(); + } + // ์˜ˆ์•ฝ ์‹œ์ฆŒ ์ˆ˜์ • + detach(season); + seasonAdminRepository.updateReserveSeasonById(seasonId, updateDto.getSeasonName(), updateDto.getStartTime(), + updateDto.getStartPpp(), updateDto.getPppGap()); + season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + insert(season); + seasonAdminRepository.save(season); + checkSeasonAtDB(); + + SeasonAdminDto seasonAdminDto = new SeasonAdminDto(season); + rankAdminService.deleteAllUserRankBySeason(seasonAdminDto); + rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); + rankRedisAdminService.deleteSeasonRankBySeasonId(seasonAdminDto.getSeasonId()); + rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); + + } + + /** + *

์ถ”๊ฐ€ ํ•˜๊ณ ์žํ•˜๋Š” season์ด ํ˜„์žฌ ์‹œ๊ฐ„๋ถ€ํ„ฐ 24์‹œ๊ฐ„ ํ›„๊ฐ€ ์•„๋‹ˆ๋ฉด ์—๋Ÿฌ

+ * @param season + */ + private void insert(Season season) { + if (LocalDateTime.now().plusHours(24).isAfter(season.getStartTime())) { + throw new SeasonTimeBeforeException(); + } + + List beforeSeasons = seasonAdminRepository.findBeforeSeasons(season.getStartTime()); + Season beforeSeason = beforeSeasons.isEmpty() ? null : beforeSeasons.get(0); + List afterSeasons = seasonAdminRepository.findAfterSeasons(season.getStartTime()); + Season afterSeason = afterSeasons.isEmpty() ? null : afterSeasons.get(0); + + if (beforeSeason != null) { + if (beforeSeason.getStartTime().plusDays(1).isAfter(season.getStartTime())) { + throw new SeasonForbiddenException(); + } + beforeSeason.setEndTime(season.getStartTime().minusSeconds(1)); + } + if (afterSeason != null) { + season.setEndTime(afterSeason.getStartTime().minusSeconds(1)); + } else { + season.setEndTime(LocalDateTime.of(9999, 12, 31, 23, 59, 59)); + } + } + + /** + *

ํƒ€๊ฒŸ ์‹œ์ฆŒ์˜ ์•ž๋’ค ์‹œ์ฆŒ๋ผ๋ฆฌ ์ด์–ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค

+ * @param season + */ + private void detach(Season season) { + // ์ด๋ฏธ ํ•ด๋‹น ์‹œ์ฆŒ ์ค‘๊ฐ„ || ์ด์ „ ์‹œ์ฆŒ + if ((LocalDateTime.now().isAfter(season.getStartTime()) && LocalDateTime.now().isBefore(season.getEndTime())) + || season.getEndTime().isBefore(LocalDateTime.now())) { + throw new SeasonForbiddenException(); + } + + List beforeSeasons = seasonAdminRepository.findBeforeSeasons(season.getStartTime()); + Season beforeSeason = beforeSeasons.isEmpty() ? null : beforeSeasons.get(0); + List afterSeasons = seasonAdminRepository.findAfterSeasons(season.getStartTime()); + Season afterSeason = afterSeasons.isEmpty() ? null : afterSeasons.get(0); + + if (beforeSeason != null) { + if (afterSeason != null) { + beforeSeason.setEndTime(afterSeason.getStartTime().minusSeconds(1)); + } else { + beforeSeason.setEndTime( + LocalDateTime.of(9999, 12, 31, 23, 59, 59)); + } + } + } + + /** + *

์‹œ์ฆŒ๋“ค์˜ ์‹œ์ž‘, ์ข…๋ฃŒ ์‹œ๊ฐ„ ์ฒดํฌ ๋ฉ”์„œ๋“œ์ด๋‹ค

+ */ + private void checkSeasonAtDB() { + List seasons = seasonAdminRepository.findAllByOrderByStartTimeAsc(); + for (int i = 1; i < seasons.size(); i++) { + if (isOverlap(seasons.get(i - 1), seasons.get(i))) { + throw new SeasonForbiddenException(); + } + } + } + + /** + *

์‹œ์ฆŒ๋ผ๋ฆฌ์˜ ๊ฒน์น˜๋Š” ๊ธฐ๊ฐ„์ด ์žˆ๋Š”์ง€ ํŒ๋ณ„ํ•˜๋Š ๋ฉ”์„œ๋“œ ์ž…๋‹ˆ๋‹ค.

+ * @param season1 + * @param season2 + * @return + */ + private boolean isOverlap(Season season1, Season season2) { + LocalDateTime start1 = season1.getStartTime(); + LocalDateTime end1 = season1.getEndTime(); + LocalDateTime start2 = season2.getStartTime(); + LocalDateTime end2 = season2.getEndTime(); + + if (start1.isEqual(end1) || start2.isEqual(end2)) { + return false; + } + // ์ฒซ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์ด ๋‘ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์˜ ์ด์ „์— ๋๋‚  ๋•Œ + if (end1.isBefore(start2)) { + return false; + } + + // ์ฒซ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์ด ๋‘ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์˜ ์ดํ›„์— ์‹œ์ž‘ํ•  ๋•Œ + if (start1.isAfter(end2)) { + return false; + } + + // ๋‚˜๋จธ์ง€ ๊ฒฝ์šฐ์—๋Š” ๋‘ ๊ธฐ๊ฐ„์ด ๊ฒน์นฉ๋‹ˆ๋‹ค. + return true; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/type/SeasonStatus.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/type/SeasonStatus.java new file mode 100644 index 000000000..ba6b81288 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/season/type/SeasonStatus.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.admin.season.type; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum SeasonStatus { + + SEASON_PAST("PAST"), + SEASON_CURRENT("CURRENT"), + SEASON_FUTURE("FUTURE"); + + private final String seasonStatus; + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinAdminController.java new file mode 100644 index 000000000..b86d71050 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinAdminController.java @@ -0,0 +1,25 @@ +package gg.pingpong.api.admin.store.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.store.controller.request.CoinUpdateRequestDto; +import gg.pingpong.api.admin.store.service.CoinAdminService; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("pingpong/admin/coin") +public class CoinAdminController { + private final CoinAdminService coinAdminService; + + @PutMapping() + public ResponseEntity updateUserCoin(@RequestBody CoinUpdateRequestDto coinUpdateRequestDto) { + coinAdminService.updateUserCoin(coinUpdateRequestDto); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinPolicyAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinPolicyAdminController.java new file mode 100644 index 000000000..5a6b8f406 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/CoinPolicyAdminController.java @@ -0,0 +1,51 @@ +package gg.pingpong.api.admin.store.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.store.controller.response.CoinPolicyAdminListResponseDto; +import gg.pingpong.api.admin.store.dto.CoinPolicyAdminAddDto; +import gg.pingpong.api.admin.store.service.CoinPolicyAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("pingpong/admin") +@Validated +public class CoinPolicyAdminController { + private final CoinPolicyAdminService coinPolicyAdminService; + + @GetMapping("/coinpolicy") + public ResponseEntity getCoinPolicyList( + @ModelAttribute @Valid PageRequestDto coReq) { + Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); + + return ResponseEntity.ok() + .body(coinPolicyAdminService.findAllCoinPolicy(pageable)); + } + + @PostMapping("/coinpolicy") + public ResponseEntity addCoinPolicy(@Parameter(hidden = true) @Login UserDto userDto, + @Valid @RequestBody CoinPolicyAdminAddDto addDto) { + + coinPolicyAdminService.addCoinPolicy(userDto, addDto); + return new ResponseEntity(HttpStatus.CREATED); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ItemAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ItemAdminController.java new file mode 100644 index 000000000..8fa6a208e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ItemAdminController.java @@ -0,0 +1,71 @@ +package gg.pingpong.api.admin.store.controller; + +import java.io.IOException; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.admin.store.controller.response.ItemListResponseDto; +import gg.pingpong.api.admin.store.service.ItemAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.item.ItemImageLargeException; +import gg.utils.exception.item.ItemImageTypeException; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/items") +public class ItemAdminController { + private final ItemAdminService itemAdminService; + + @GetMapping("/history") + public ItemListResponseDto getItemHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("createdAt").descending()); + return itemAdminService.getAllItemHistory(pageable); + } + + @PostMapping(path = "/{itemId}", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) + public ResponseEntity updateItem(@PathVariable("itemId") Long itemId, + @RequestPart @Valid ItemUpdateRequestDto updateItemInfo, + @RequestPart(required = false) MultipartFile imgData, + @Parameter(hidden = true) @Login UserDto user) throws IOException { + if (imgData != null) { + if (imgData.getSize() > 50000) { + throw new ItemImageLargeException(); + } else if (imgData.getContentType() == null || !imgData.getContentType().equals("image/jpeg")) { + throw new ItemImageTypeException(); + } + itemAdminService.updateItem(itemId, updateItemInfo, imgData, user); + } else { + itemAdminService.updateItem(itemId, updateItemInfo, user); + } + return new ResponseEntity(HttpStatus.NO_CONTENT); + } + + @DeleteMapping("/{itemId}") + public ResponseEntity deleteItem(@PathVariable("itemId") Long itemId, + @Parameter(hidden = true) @Login UserDto user) { + itemAdminService.deleteItem(itemId, user); + return new ResponseEntity(HttpStatus.NO_CONTENT); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/MegaphoneAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/MegaphoneAdminController.java new file mode 100644 index 000000000..79e67c696 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/MegaphoneAdminController.java @@ -0,0 +1,36 @@ +package gg.pingpong.api.admin.store.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.store.controller.response.MegaphoneHistoryResponseDto; +import gg.pingpong.api.admin.store.service.MegaphoneAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/megaphones") +public class MegaphoneAdminController { + private final MegaphoneAdminService megaphoneAdminService; + + @GetMapping("/history") + public MegaphoneHistoryResponseDto getMegaphoneHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto, + @RequestParam(required = false) String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("id").descending()); + if (intraId == null) { + return megaphoneAdminService.getMegaphoneHistory(pageable); + } + return megaphoneAdminService.getMegaphoneHistoryByIntraId(intraId, pageable); + + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ReceiptAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ReceiptAdminController.java new file mode 100644 index 000000000..733aac2ba --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/ReceiptAdminController.java @@ -0,0 +1,36 @@ +package gg.pingpong.api.admin.store.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.admin.store.controller.request.ReceiptAdminPageRequestDto; +import gg.pingpong.api.admin.store.controller.response.ReceiptListResponseDto; +import gg.pingpong.api.admin.store.service.ReceiptAdminService; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/admin/receipt") +public class ReceiptAdminController { + private final ReceiptAdminService receiptAdminService; + + @GetMapping + public ReceiptListResponseDto getReceiptList(@ModelAttribute @Valid ReceiptAdminPageRequestDto req) { + + if (req.getIntraId() == null) { + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return receiptAdminService.getAllReceipt(pageable); + } + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return receiptAdminService.findByIntraId(req.getIntraId(), pageable); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/CoinUpdateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/CoinUpdateRequestDto.java new file mode 100644 index 000000000..04cf48535 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/CoinUpdateRequestDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.admin.store.controller.request; + +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class CoinUpdateRequestDto { + @NotNull(message = "intraId๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private String intraId; + @NotNull(message = "change๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private int change; + @NotNull(message = "content๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private String content; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ItemUpdateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ItemUpdateRequestDto.java new file mode 100644 index 000000000..8b48862db --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ItemUpdateRequestDto.java @@ -0,0 +1,61 @@ +package gg.pingpong.api.admin.store.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import gg.data.store.Item; +import gg.data.store.type.ItemType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemUpdateRequestDto { + @NotNull(message = "[Request] ์•„์ดํ…œ ์ด๋ฆ„์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private String name; + + @NotNull(message = "[Request] ์ฃผ ์„ค๋ช…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private String mainContent; + + @NotNull(message = "[Request] ๋ถ€ ์„ค๋ช…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private String subContent; + + @NotNull(message = "[Request] ๊ฐ€๊ฒฉ์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private Integer price; + + @NotNull(message = "[Request] ํ• ์ธ์œจ์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private Integer discount; + + @NotNull(message = "[Request] ์•„์ดํ…œ ํƒ€์ž…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private ItemType itemType; + + public Item toItem(String imageUrl, String userIntraId) { + return Item.builder() + .name(name) + .mainContent(mainContent) + .subContent(subContent) + .price(price) + .discount(discount) + .imageUri(imageUrl) + .isVisible(true) + .type(itemType) + .createdAt(LocalDateTime.now()) + .creatorIntraId(userIntraId) + .build(); + } + + @Override + public String toString() { + return "ItemUpdateRequestDto{" + + "name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", price=" + price + + ", discount=" + discount + + ", itemType='" + itemType + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ReceiptAdminPageRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ReceiptAdminPageRequestDto.java new file mode 100644 index 000000000..89a895eaa --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/request/ReceiptAdminPageRequestDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.admin.store.controller.request; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; + +@Getter +public class ReceiptAdminPageRequestDto extends PageRequestDto { + private String intraId; + + public ReceiptAdminPageRequestDto(String intraId, Integer page, Integer size) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminListResponseDto.java new file mode 100644 index 000000000..f78d98f94 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class CoinPolicyAdminListResponseDto { + private List coinPolicyList; + private int totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminResponseDto.java new file mode 100644 index 000000000..c6370a3b2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/CoinPolicyAdminResponseDto.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.time.LocalDateTime; + +import gg.data.store.CoinPolicy; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CoinPolicyAdminResponseDto { + private Long coinPolicyId; + private String createUserId; + private int attendance; + private int normal; + private int rankWin; + private int rankLose; + private LocalDateTime createdAt; + + public CoinPolicyAdminResponseDto(CoinPolicy coinPolicyAdmin) { + this.coinPolicyId = coinPolicyAdmin.getId(); + this.createUserId = coinPolicyAdmin.getUser().getIntraId(); + this.attendance = coinPolicyAdmin.getAttendance(); + this.normal = coinPolicyAdmin.getNormal(); + this.rankWin = coinPolicyAdmin.getRankWin(); + this.rankLose = coinPolicyAdmin.getRankLose(); + this.createdAt = coinPolicyAdmin.getCreatedAt(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemHistoryResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemHistoryResponseDto.java new file mode 100644 index 000000000..5855e6766 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemHistoryResponseDto.java @@ -0,0 +1,56 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.time.LocalDateTime; + +import gg.data.store.Item; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemHistoryResponseDto { + private Long itemId; + private String name; + private String mainContent; + private String subContent; + private String imageUri; + private Integer price; + private Integer discount; + private boolean isVisible; + private LocalDateTime createdAt; + private String creatorIntraId; + private String deleterIntraId; + + public ItemHistoryResponseDto(Item item) { + this.itemId = item.getId(); + this.name = item.getName(); + this.mainContent = item.getMainContent(); + this.subContent = item.getSubContent(); + this.imageUri = item.getImageUri(); + this.price = item.getPrice(); + this.discount = item.getDiscount(); + this.isVisible = item.getIsVisible(); + this.createdAt = item.getCreatedAt(); + this.creatorIntraId = item.getCreatorIntraId(); + this.deleterIntraId = item.getDeleterIntraId(); + } + + @Override + public String toString() { + return "ItemHistoryResponseDto{" + + "itemId=" + itemId + + ", name='" + name + '\'' + + ", mainContent='" + mainContent + '\'' + + ", subContent='" + subContent + '\'' + + ", imageUri='" + imageUri + '\'' + + ", price=" + price + + ", discount=" + discount + + ", isVisible=" + isVisible + + ", createdAt=" + createdAt + + ", creatorIntraId='" + creatorIntraId + '\'' + + ", deleterIntraId='" + deleterIntraId + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemListResponseDto.java new file mode 100644 index 000000000..d885cfe76 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ItemListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ItemListResponseDto { + private List historyList; + private Integer totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneAdminResponseDto.java new file mode 100644 index 000000000..e09f2633a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneAdminResponseDto.java @@ -0,0 +1,23 @@ +package gg.pingpong.api.admin.store.controller.response; + +import gg.data.store.Megaphone; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneAdminResponseDto { + private Long megaphoneId; + private String content; + private String usedAt; + private String status; + private String intraId; + + public MegaphoneAdminResponseDto(Megaphone megaphone) { + this.megaphoneId = megaphone.getId(); + this.content = megaphone.getContent(); + this.usedAt = megaphone.getUsedAt().toString(); + this.status = megaphone.getReceipt().getStatus().getDescription(); + this.intraId = megaphone.getUser().getIntraId(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneHistoryResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneHistoryResponseDto.java new file mode 100644 index 000000000..9ff53a483 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/MegaphoneHistoryResponseDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneHistoryResponseDto { + private List megaphoneList; + private int totalPage; + + public MegaphoneHistoryResponseDto(List newDtos, int totalPage) { + this.megaphoneList = newDtos; + this.totalPage = totalPage; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptListResponseDto.java new file mode 100644 index 000000000..04eee49d9 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ReceiptListResponseDto { + private List receiptList; + private Integer totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptResponseDto.java new file mode 100644 index 000000000..026f4f448 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/controller/response/ReceiptResponseDto.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.admin.store.controller.response; + +import java.time.LocalDateTime; + +import gg.data.store.Item; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ReceiptResponseDto { + private Long receiptId; + private LocalDateTime createdAt; + private String itemName; + private Integer itemPrice; + private String purchaserIntraId; + private String ownerIntraId; + private ItemStatus itemStatusType; + + public ReceiptResponseDto(Receipt receipt) { + Item item = receipt.getItem(); + this.itemName = item.getName(); + this.itemPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); + this.receiptId = receipt.getId(); + this.createdAt = receipt.getCreatedAt(); + this.purchaserIntraId = receipt.getPurchaserIntraId(); + this.ownerIntraId = receipt.getOwnerIntraId(); + this.itemStatusType = receipt.getStatus(); + } + + @Override + public String toString() { + return "ReceiptResponseDto{" + + "receiptId=" + receiptId + + ", createdAt=" + createdAt + + ", itemName='" + itemName + '\'' + + ", itemPrice=" + itemPrice + + ", purchaserIntraId='" + purchaserIntraId + '\'' + + ", ownerIntraId='" + ownerIntraId + '\'' + + ", itemStatusType=" + itemStatusType + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/dto/CoinPolicyAdminAddDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/dto/CoinPolicyAdminAddDto.java new file mode 100644 index 000000000..25d8d75eb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/dto/CoinPolicyAdminAddDto.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.admin.store.dto; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CoinPolicyAdminAddDto { + @NotNull(message = "plz. not null attendance") + @PositiveOrZero(message = "plz. attendance PositiveOrZero") + private int attendance; + + @NotNull(message = "plz. not null normal") + @PositiveOrZero(message = "plz. normal PositiveOrZero") + private int normal; + + @NotNull(message = "plz. not null rankWin") + @PositiveOrZero(message = "plz. rankWin PositiveOrZero") + private int rankWin; + + @NotNull(message = "plz. not null rankLose") + @PositiveOrZero(message = "plz. rankLose PositiveOrZero") + private int rankLose; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinAdminService.java new file mode 100644 index 000000000..6a52d9781 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinAdminService.java @@ -0,0 +1,28 @@ +package gg.pingpong.api.admin.store.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.CoinHistory; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.request.CoinUpdateRequestDto; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.repo.user.UserRepository; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class CoinAdminService { + private final UserRepository userRepository; + private final CoinHistoryService coinHistoryService; + + @Transactional + public void updateUserCoin(CoinUpdateRequestDto coinUpdateRequestDto) { + User user = userRepository.findByIntraId(coinUpdateRequestDto.getIntraId()) + .orElseThrow(UserNotFoundException::new); + user.addGgCoin(coinUpdateRequestDto.getChange()); + coinHistoryService.addCoinHistory(new CoinHistory(user, coinUpdateRequestDto.getContent(), + coinUpdateRequestDto.getChange())); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinPolicyAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinPolicyAdminService.java new file mode 100644 index 000000000..b0644ae52 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/CoinPolicyAdminService.java @@ -0,0 +1,42 @@ +package gg.pingpong.api.admin.store.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.store.CoinPolicyAdminRepository; +import gg.admin.repo.user.UserAdminRepository; +import gg.data.store.CoinPolicy; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.response.CoinPolicyAdminListResponseDto; +import gg.pingpong.api.admin.store.controller.response.CoinPolicyAdminResponseDto; +import gg.pingpong.api.admin.store.dto.CoinPolicyAdminAddDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.user.UserNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class CoinPolicyAdminService { + private final CoinPolicyAdminRepository coinPolicyAdminRepository; + private final UserAdminRepository userAdminRepository; + + @Transactional(readOnly = true) + public CoinPolicyAdminListResponseDto findAllCoinPolicy(Pageable pageable) { + Page allCoinPolicy = coinPolicyAdminRepository.findAll(pageable); + Page responseDtos = allCoinPolicy.map(CoinPolicyAdminResponseDto::new); + + return new CoinPolicyAdminListResponseDto(responseDtos.getContent(), + responseDtos.getTotalPages()); + } + + @Transactional + public void addCoinPolicy(UserDto userDto, CoinPolicyAdminAddDto addDto) { + User user = userAdminRepository.findByIntraId(userDto.getIntraId()).orElseThrow(UserNotFoundException::new); + + CoinPolicy coinPolicy = CoinPolicy.from(user, addDto.getAttendance(), addDto.getNormal(), + addDto.getRankWin(), addDto.getRankLose()); + coinPolicyAdminRepository.save(coinPolicy); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ItemAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ItemAdminService.java new file mode 100644 index 000000000..363aded6b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ItemAdminService.java @@ -0,0 +1,99 @@ +package gg.pingpong.api.admin.store.service; + +import java.io.IOException; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import gg.admin.repo.store.ItemAdminRepository; +import gg.data.store.Item; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.admin.store.controller.response.ItemHistoryResponseDto; +import gg.pingpong.api.admin.store.controller.response.ItemListResponseDto; +import gg.pingpong.api.global.utils.aws.AsyncNewItemImageUploader; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.item.ItemNotAvailableException; +import gg.utils.exception.item.ItemNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ItemAdminService { + + private final ItemAdminRepository itemAdminRepository; + private final AsyncNewItemImageUploader asyncNewItemImageUploader; + + /** + *

Item ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

+ * @param pageable + * @return + */ + @Transactional(readOnly = true) + public ItemListResponseDto getAllItemHistory(Pageable pageable) { + Page responseDtos = itemAdminRepository.findAll(pageable) + .map(ItemHistoryResponseDto::new); + return new ItemListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + /** + *

์•„์ดํ…œ ์ˆ˜์ • ์‹œ ์‹ ๊ทœ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ

+ *

๊ธฐ์กด ์•„์ดํ…œ์˜ item.isVisible ๋ฅผ false ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค

+ * @param itemId ํƒ€๊ฒŸ ์•„์ดํ…œ + * @param itemUpdateRequestDto ํƒ€๊ฒŸ ์•„์ดํ…œ ๋ณ€๊ฒฝ dto + * @param itemImageFile ์‹ ๊ทœ ์ด๋ฏธ์ง€ + * @param user ๋ฐ”๊พธ๋Š” ์œ ์ € id + * @throws IOException IOException + * @throws ItemNotFoundException ์•„์ดํ…œ ์—†์Œ + * @throws ItemNotAvailableException ์ ‘๊ทผ ๋ถˆ๊ฐ€ํ•œ ์•„์ดํ…œ + */ + @Transactional + public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, + MultipartFile itemImageFile, UserDto user) throws IOException { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotAvailableException(); + } + item.setVisibility(user.getIntraId()); + Item newItem = itemUpdateRequestDto.toItem(null, user.getIntraId()); + if (itemImageFile != null) { + asyncNewItemImageUploader.upload(newItem, itemImageFile); + } + itemAdminRepository.save(newItem); + } + + /** + *

์•„์ดํ…œ ์ˆ˜์ • ์‹œ ์‹ ๊ทœ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

+ *

๊ธฐ์กด ์•„์ดํ…œ์˜ item.isVisible ๋ฅผ false ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค

+ * @param itemId ํƒ€๊ฒŸ ์•„์ดํ…œ + * @param itemUpdateRequestDto ํƒ€๊ฒŸ ์•„์ดํ…œ ๋ณ€๊ฒฝ dto + * @param user ๋ฐ”๊พธ๋Š” ์œ ์ € id + * @throws ItemNotFoundException ์•„์ดํ…œ ์—†์Œ + * @throws ItemNotAvailableException ์ ‘๊ทผ ๋ถˆ๊ฐ€ํ•œ ์•„์ดํ…œ + */ + @Transactional + public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, UserDto user) { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotAvailableException(); + } + item.setVisibility(user.getIntraId()); + Item newItem = itemUpdateRequestDto.toItem(item.getImageUri(), user.getIntraId()); + itemAdminRepository.save(newItem); + } + + /** + *

์•„์ดํ…œ ์‚ญ์ œ

+ *

item.isVisible ๋ฅผ false ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค

+ * @param itemId ํƒ€๊ฒŸ id + * @param user ์‚ญ์ œํ•˜๋Š” ์œ ์ € + * @throws ItemNotFoundException ์•„์ดํ…œ ์—†์Œ + */ + @Transactional + public void deleteItem(Long itemId, UserDto user) { + Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + item.setVisibility(user.getIntraId()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/MegaphoneAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/MegaphoneAdminService.java new file mode 100644 index 000000000..e83d5d507 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/MegaphoneAdminService.java @@ -0,0 +1,39 @@ +package gg.pingpong.api.admin.store.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import gg.admin.repo.store.MegaphoneAdminRepository; +import gg.pingpong.api.admin.store.controller.response.MegaphoneAdminResponseDto; +import gg.pingpong.api.admin.store.controller.response.MegaphoneHistoryResponseDto; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MegaphoneAdminService { + private final MegaphoneAdminRepository megaphoneAdminRepository; + + /** + *

๋ฉ”๊ฐ€ํฐ ๊ธฐ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

+ * @param pageable + * @return + */ + public MegaphoneHistoryResponseDto getMegaphoneHistory(Pageable pageable) { + Page megaphoneHistory = megaphoneAdminRepository.findAll(pageable) + .map(MegaphoneAdminResponseDto::new); + return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); + } + + /** + *

intraId๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉ”๊ฐ€ํฐ ๊ธฐ๋ก์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

+ * @param intraId ํƒ€๊ฒŸ ์ธํŠธ๋ผid + * @param pageable + * @return + */ + public MegaphoneHistoryResponseDto getMegaphoneHistoryByIntraId(String intraId, Pageable pageable) { + Page megaphoneHistory = megaphoneAdminRepository + .findMegaphonesByUserIntraId(intraId, pageable).map(MegaphoneAdminResponseDto::new); + return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ReceiptAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ReceiptAdminService.java new file mode 100644 index 000000000..560a3510c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/store/service/ReceiptAdminService.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.admin.store.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.store.ReceiptAdminRepository; +import gg.data.store.Receipt; +import gg.pingpong.api.admin.store.controller.response.ReceiptListResponseDto; +import gg.pingpong.api.admin.store.controller.response.ReceiptResponseDto; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ReceiptAdminService { + private final ReceiptAdminRepository receiptAdminRepository; + + @Transactional(readOnly = true) + public ReceiptListResponseDto getAllReceipt(Pageable pageable) { + Page responseDtos = receiptAdminRepository.findAll(pageable).map(ReceiptResponseDto::new); + return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } + + @Transactional(readOnly = true) + public ReceiptListResponseDto findByIntraId(String intraId, Pageable pageable) { + Page receipts = receiptAdminRepository.findReceiptByIntraId(intraId, pageable); + Page responseDtos = receipts.map(ReceiptResponseDto::new); + return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminController.java new file mode 100644 index 000000000..d7bc2ac5d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminController.java @@ -0,0 +1,131 @@ +package gg.pingpong.api.admin.tournament.controller; + +import javax.validation.Valid; +import javax.validation.constraints.Positive; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +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.PostMapping; +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 gg.pingpong.api.admin.tournament.controller.request.TournamentAdminAddUserRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminCreateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminUpdateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentGameUpdateRequestDto; +import gg.pingpong.api.admin.tournament.controller.response.TournamentAdminAddUserResponseDto; +import gg.pingpong.api.admin.tournament.service.TournamentAdminService; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserListResponseDto; +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +@RequestMapping("/pingpong/admin/tournaments") +@Validated +public class TournamentAdminController { + private final TournamentAdminService tournamentAdminService; + + /*** + * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ + * @param tournamentAdminCreateRequestDto ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ + * @return "CREATED" ์‘๋‹ต ์ฝ”๋“œ + */ + @PostMapping() + public ResponseEntity createTournament( + @RequestBody @Valid TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto) { + tournamentAdminService.createTournament(tournamentAdminCreateRequestDto); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์ •๋ณด ์ˆ˜์ •

+ * @param tournamentId ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ id + * @param tournamentAdminUpdateRequestDto ์š”์ฒญ ๋ฐ์ดํ„ฐ + * @return HttpStatus.NO_CONTENT + */ + @PatchMapping("/{tournamentId}") + public ResponseEntity updateTournamentInfo(@PathVariable @Positive Long tournamentId, + @Valid @RequestBody TournamentAdminUpdateRequestDto tournamentAdminUpdateRequestDto) { + tournamentAdminService.updateTournamentInfo(tournamentId, tournamentAdminUpdateRequestDto); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์ •๋ณด ์‚ญ์ œ

+ * @param tournamentId ์‚ญ์ œํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ id + * @return HttpStatus.NO_CONTENT + */ + @DeleteMapping("/{tournamentId}") + public ResponseEntity deleteTournament(@PathVariable @Positive Long tournamentId) { + tournamentAdminService.deleteTournament(tournamentId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์ถ”๊ฐ€

+ *

์ด๋ฏธ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์ฐธ์—ฌ์ค‘์ด๊ฑฐ๋‚˜ ๋Œ€๊ธฐ์ž์ธ ์œ ์ €๋Š” ์‹ ์ฒญํ•  ์ˆ˜ ์—†๋‹ค.

+ * @param tournamentId ์œ ์ €๋ฅผ ์ถ”๊ฐ€ํ•  ํ† ๋„ˆ๋จผํŠธ id + * @param tournamentAdminUserAddRequestDto ์š”์ฒญ ๋ฐ์ดํ„ฐ + * @return TournamentAdminAddUserResponseDto, HttpStatus.CREATED + */ + @PostMapping("/{tournamentId}/users") + public ResponseEntity addTournamentUser( + @PathVariable @Positive Long tournamentId, + @Valid @RequestBody TournamentAdminAddUserRequestDto tournamentAdminUserAddRequestDto) { + TournamentAdminAddUserResponseDto responseDto = tournamentAdminService.addTournamentUser(tournamentId, + tournamentAdminUserAddRequestDto); + + return ResponseEntity.status(HttpStatus.CREATED).body(responseDto); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์กฐํšŒ

+ * @param tournamentId ์œ ์ €๋ฅผ ์กฐํšŒํ•  ํ† ๋„ˆ๋จผํŠธ id + * @param isJoined ์ฐธ์—ฌ์ค‘์ธ ์œ ์ €๋งŒ ์กฐํšŒํ• ์ง€ ์—ฌ๋ถ€ + * @return TournamentUserListResponseDto + */ + @GetMapping("/{tournamentId}/users") + public ResponseEntity getTournamentUserList( + @PathVariable @Positive Long tournamentId, + @RequestParam(required = false) Boolean isJoined) { + TournamentUserListResponseDto responseDto = tournamentAdminService.getTournamentUserList(tournamentId, + isJoined); + return ResponseEntity.status(HttpStatus.OK).body(responseDto); + } + + /** + *

๊ด€๋ฆฌ์ž ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์‚ญ์ œ

+ *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ €๋ฅผ ์‚ญ์ œ์‹œ์ผœ ์ฃผ๋ฉฐ, ์ฐธ๊ฐ€์ž๊ฐ€ ์‚ญ์ œ๋˜๋Š” ๊ฒฝ์šฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋Œ€๊ธฐ์ž๋ฅผ ์ฐธ๊ฐ€์ž๋กœ ๋ฐ”๊พธ์–ด์ค€๋‹ค.

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @param userId ํƒ€๊ฒŸ ์œ ์ € id + */ + @DeleteMapping("/{tournamentId}/users/{userId}") + public ResponseEntity deleteTournamentUser(@PathVariable @Positive Long tournamentId, + @PathVariable @Positive Long userId) { + tournamentAdminService.deleteTournamentUser(tournamentId, userId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ •๋ณด ์ˆ˜์ •

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @param tournamentGameUpdateReqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด + * @return HttpStatus.OK + */ + @PatchMapping("{tournamentId}/games") + public ResponseEntity updateTournamentGame(@PathVariable @Positive Long tournamentId, + @Valid @RequestBody TournamentGameUpdateRequestDto tournamentGameUpdateReqDto) { + tournamentAdminService.updateTournamentGame(tournamentId, tournamentGameUpdateReqDto); + return ResponseEntity.status(HttpStatus.OK).build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminAddUserRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminAddUserRequestDto.java new file mode 100644 index 000000000..afb5164e5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminAddUserRequestDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.admin.tournament.controller.request; + +import javax.validation.constraints.NotNull; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TournamentAdminAddUserRequestDto { + @NotNull(message = "intraId๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + private String intraId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminCreateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminCreateRequestDto.java new file mode 100644 index 000000000..f31951cbc --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminCreateRequestDto.java @@ -0,0 +1,38 @@ +package gg.pingpong.api.admin.tournament.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import gg.data.tournament.type.TournamentType; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class TournamentAdminCreateRequestDto { + @NotNull(message = "์ œ๋ชฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @Length(max = 30, message = "์ œ๋ชฉ์€ 30์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") + private String title; + + @NotNull(message = "๋‚ด์šฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @Length(max = 3000, message = "๋‚ด์šฉ์€ 3000์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") + private String contents; + + @NotNull(message = "์‹œ์ž‘ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + private LocalDateTime startTime; + + @NotNull(message = "์ข…๋ฃŒ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + private LocalDateTime endTime; + + @NotNull(message = "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + private TournamentType type; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminUpdateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminUpdateRequestDto.java new file mode 100644 index 000000000..6121e4722 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentAdminUpdateRequestDto.java @@ -0,0 +1,39 @@ +package gg.pingpong.api.admin.tournament.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.format.annotation.DateTimeFormat.ISO; + +import gg.data.tournament.type.TournamentType; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TournamentAdminUpdateRequestDto { + @NotNull(message = "์ œ๋ชฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @Length(max = 30, message = "์ œ๋ชฉ์€ 30์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") + private String title; + + @NotNull(message = "๋‚ด์šฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @Length(max = 3000, message = "๋‚ด์šฉ์€ 3000์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") + private String contents; + + @NotNull(message = "์‹œ์ž‘ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = ISO.DATE_TIME) + private LocalDateTime startTime; + + @NotNull(message = "์ข…๋ฃŒ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + @DateTimeFormat(iso = ISO.DATE_TIME) + private LocalDateTime endTime; + + @NotNull(message = "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") + private TournamentType type; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentGameUpdateRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentGameUpdateRequestDto.java new file mode 100644 index 000000000..7229861cc --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/request/TournamentGameUpdateRequestDto.java @@ -0,0 +1,36 @@ +package gg.pingpong.api.admin.tournament.controller.request; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import gg.pingpong.api.user.game.dto.TeamReqDto; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class TournamentGameUpdateRequestDto { + + @NotNull + private Long tournamentGameId; + + private Long nextTournamentGameId; + @NotNull + @Valid + private TeamReqDto team1; + @NotNull + @Valid + private TeamReqDto team2; + + @Override + public String toString() { + return "TournamentGameUpdateReqDto{" + + "tournamentGameId=" + tournamentGameId + + ", nextTournamentGameId=" + nextTournamentGameId + + ", team1=" + team1 + ", team2=" + + team2 + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/response/TournamentAdminAddUserResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/response/TournamentAdminAddUserResponseDto.java new file mode 100644 index 000000000..5bf87d581 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/controller/response/TournamentAdminAddUserResponseDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.admin.tournament.controller.response; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TournamentAdminAddUserResponseDto { + private Long userId; + + private String intraId; + + private Boolean isJoined; + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/service/TournamentAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/service/TournamentAdminService.java new file mode 100644 index 000000000..09385a366 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/tournament/service/TournamentAdminService.java @@ -0,0 +1,390 @@ +package gg.pingpong.api.admin.tournament.service; + +import static gg.data.match.type.TournamentMatchStatus.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.match.type.TournamentMatchStatus; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminAddUserRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminCreateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminUpdateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentGameUpdateRequestDto; +import gg.pingpong.api.admin.tournament.controller.response.TournamentAdminAddUserResponseDto; +import gg.pingpong.api.global.config.ConstantConfig; +import gg.pingpong.api.user.game.service.GameService; +import gg.pingpong.api.user.match.service.MatchTournamentService; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserListResponseDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; +import gg.utils.exception.game.ScoreNotInvalidException; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.tournament.TournamentConflictException; +import gg.utils.exception.tournament.TournamentGameNotFoundException; +import gg.utils.exception.tournament.TournamentNotFoundException; +import gg.utils.exception.tournament.TournamentUpdateException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class TournamentAdminService { + private final TournamentRepository tournamentRepository; + private final TournamentUserRepository tournamentUserRepository; + private final UserRepository userRepository; + private final GameRepository gameRepository; + private final TournamentGameRepository tournamentGameRepository; + private final SlotManagementRepository slotManagementRepository; + private final MatchTournamentService matchTournamentService; + private final ConstantConfig constantConfig; + private final GameService gameService; + + /*** + * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ Method + * @param tournamentAdminCreateRequestDto ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ + * @throws TournamentConflictException ํ† ๋„ˆ๋จผํŠธ์˜ ์ œ๋ชฉ์ด ๊ฒน์น  ๋•Œ + * @throws TournamentUpdateException ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์œผ๋กœ ๋ถ€์ ํ•ฉ ํ•  ๋•Œ + * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ && ๊ฒŒ์ž„ ์กด์žฌํ•  ๋•Œ + * @return ์ƒˆ๋กœ ์ƒ์„ฑ๋œ tournament + */ + @Transactional + public void createTournament(TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto) { + checkValidTournamentTime(tournamentAdminCreateRequestDto.getStartTime(), + tournamentAdminCreateRequestDto.getEndTime()); + checkConflictedTournament(-1L, tournamentAdminCreateRequestDto.getStartTime(), + tournamentAdminCreateRequestDto.getEndTime()); + checkGameExistence(tournamentAdminCreateRequestDto.getStartTime(), + tournamentAdminCreateRequestDto.getEndTime()); + + Tournament tournament = Tournament.builder() + .title(tournamentAdminCreateRequestDto.getTitle()) + .contents(tournamentAdminCreateRequestDto.getContents()) + .startTime(tournamentAdminCreateRequestDto.getStartTime()) + .endTime(tournamentAdminCreateRequestDto.getEndTime()) + .type(tournamentAdminCreateRequestDto.getType()) + .status(TournamentStatus.BEFORE).build(); + createTournamentGameList(tournament, 7); + tournamentRepository.save(tournament); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์—…๋ฐ์ดํŠธ Method

+ * @param tournamentId ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ id + * @param requestDto ์š”์ฒญํ•œ Dto + * @throws TournamentNotFoundException ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ + * @throws TournamentUpdateException ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ, ๋ณ€๊ฒฝํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์ด ๋ถ€์ ํ•ฉ ํ•  ๋•Œ + * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ && ๊ฒŒ์ž„ ์กด์žฌํ•  ๋•Œ + */ + @Transactional + public Tournament updateTournamentInfo(Long tournamentId, TournamentAdminUpdateRequestDto requestDto) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + checkValidTournamentTime(requestDto.getStartTime(), requestDto.getEndTime()); + checkConflictedTournament(targetTournament.getId(), requestDto.getStartTime(), requestDto.getEndTime()); + checkGameExistence(requestDto.getStartTime(), requestDto.getEndTime()); + + targetTournament.update( + requestDto.getTitle(), + requestDto.getContents(), + requestDto.getStartTime(), + requestDto.getEndTime(), + requestDto.getType(), + TournamentStatus.BEFORE); + return tournamentRepository.save(targetTournament); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ๋งค์„œ๋“œ

+ *

ํ† ๋„ˆ๋จผํŠธ๋Š” BEFORE ์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ญ์ œ ๊ฐ€๋Šฅํ•˜๋‹ค.

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @throws TournamentNotFoundException ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ + * @throws TournamentUpdateException ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ + */ + @Transactional + public void deleteTournament(Long tournamentId) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + tournamentRepository.deleteById(tournamentId); + } + + /** + *

๊ด€๋ฆฌ์ž ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์œ ์ € ์ถ”๊ฐ€ ๋งค์„œ๋“œ

+ *

ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์ด๋ฏธ ์‹ ์ฒญ ๋˜์–ด ์žˆ์œผ๋ฉด ์ถ”๊ฐ€ ๋ถˆ๊ฐ€

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ + * @param requestDto ์š”์ฒญ dto + * @return TournamentAdminAddUserResponseDto dto ๋ฐ˜ํ™˜ + * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ + * @throws TournamentUpdateException ์ด๋ฏธ ์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋œ ํ† ๋„ˆ๋จผํŠธ + * @throws UserNotFoundException ์œ ์ € ์—†์Œ + * @throws TournamentConflictException ์ด๋ฏธ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ค‘์ธ ์œ ์ € + */ + @Transactional + public TournamentAdminAddUserResponseDto addTournamentUser(Long tournamentId, + TournamentAdminAddUserRequestDto requestDto) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + + User targetUser = userRepository.findByIntraId(requestDto.getIntraId()).orElseThrow(UserNotFoundException::new); + + List tournamentList = targetTournament.getTournamentUsers(); + tournamentList.stream().filter(tu -> tu.getUser().getIntraId().equals(targetUser.getIntraId())) + .findAny() + .ifPresent(a -> { + throw new TournamentConflictException(ErrorCode.TOURNAMENT_ALREADY_PARTICIPANT); + }); + + TournamentUser tournamentUser = new TournamentUser(targetUser, targetTournament, + tournamentList.size() < Tournament.ALLOWED_JOINED_NUMBER, LocalDateTime.now()); + tournamentUserRepository.save(tournamentUser); + + return new TournamentAdminAddUserResponseDto( + targetUser.getId(), + targetUser.getIntraId(), + tournamentUser.getIsJoined() + ); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์‚ญ์ œ ๋งค์„œ๋“œ

+ *

์‚ญ์ œํ•˜๊ณ ์ž ํ•˜๋Š” ์œ ์ €๊ฐ€ ์ฐธ๊ฐ€์ž์ด๊ณ , ํ˜„์žฌ ๋Œ€๊ธฐ์ž๊ฐ€ ์žˆ๋‹ค๋ฉด ์ฐธ๊ฐ€์‹ ์ฒญ์ด ๋น ๋ฅธ ๋Œ€๊ธฐ์ž๋ฅผ ์ฐธ๊ฐ€์ž๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค.

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @param userId ํƒ€๊ฒŸ ์œ ์ € id + * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ + * @throws TournamentUpdateException ์ด๋ฏธ ์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋œ ํ† ๋„ˆ๋จผํŠธ + * @throws UserNotFoundException ์œ ์ € ์—†์Œ || ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹˜ + */ + @Transactional + public void deleteTournamentUser(Long tournamentId, Long userId) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + User targetUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + List tournamentUserList = targetTournament.getTournamentUsers(); + TournamentUser targetTournamentUser = tournamentUserList.stream() + .filter(tu -> tu.getUser().getId().equals(targetUser.getId())) + .findAny() + .orElseThrow(() -> new TournamentNotFoundException(ErrorCode.TOURNAMENT_NOT_PARTICIPANT)); + targetTournamentUser.deleteTournament(); + if (targetTournamentUser.getIsJoined() && tournamentUserList.size() >= Tournament.ALLOWED_JOINED_NUMBER) { + tournamentUserList.get(Tournament.ALLOWED_JOINED_NUMBER - 1).updateIsJoined(true); + } + tournamentUserRepository.delete(targetTournamentUser); + } + + /*** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” ์ƒ์„ฑ Method + * @param tournament ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์— ๋งค์นญ๋  ํ† ๋„ˆ๋จผํŠธ + * @param cnt ํ† ๋„ˆ๋จผํŠธ ์ „์ฒด ๋ผ์šด๋“œ ์ˆ˜ + */ + private void createTournamentGameList(Tournament tournament, int cnt) { + TournamentRound[] rounds = TournamentRound.values(); + while (--cnt >= 0) { + TournamentGame tournamentGame = new TournamentGame(null, tournament, rounds[cnt]); + } + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„ ์ฒดํฌ : + * [ ํ˜„์žฌ ์‹œ๊ฐ„ + ์ตœ์†Œ 2์ผ ], + * [ ํ˜„์žฌ์‹œ๊ฐ„ ๋ณด๋‹ค ๋ฏธ๋ž˜ ], + * [ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ์ข…๋ฃŒ์‹œ๊ฐ„๋ณด๋‹ค ํ˜„์žฌ์‹œ์— ๊ฐ€๊นŒ์›€ ] + * [ ์ง„ํ–‰ ์‹œ๊ฐ„ ์ตœ์†Œ 2์‹œ๊ฐ„ ] + * + * @param startTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @throws InvalidParameterException ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์œผ๋กœ ๋ถ€์ ํ•ฉ ํ•  ๋•Œ + */ + private void checkValidTournamentTime(LocalDateTime startTime, LocalDateTime endTime) { + SlotManagement slotManagement = slotManagementRepository.findCurrent(startTime) + .orElseThrow(SlotNotFoundException::new); + int interval = slotManagement.getGameInterval(); + + if (startTime.isAfter(endTime) + || startTime.isEqual(endTime) + || LocalDate.now().plusDays(constantConfig.getAllowedMinimalStartDays()).isAfter(startTime.toLocalDate()) + || startTime.plusHours(Tournament.MINIMUM_TOURNAMENT_DURATION).isAfter(endTime) + || startTime.getMinute() % interval != 0 + || endTime.getMinute() % interval != 0) { + throw new TournamentUpdateException(ErrorCode.TOURNAMENT_INVALID_TIME); + } + } + + /** + *

tournamentList ์—์„œ targetTournament์„ ์ œ์™ธํ•œ ํ† ๋„ˆ๋จผํŠธ ์ค‘ ๊ฒน์น˜๋Š” ์‹œ๊ฐ„๋Œ€ ์กด์žฌ ์œ ๋ฌด ํ™•์ธ

+ * @param targetTournamentId ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ id + * @param startTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ + */ + private void checkConflictedTournament(Long targetTournamentId, LocalDateTime startTime, LocalDateTime endTime) { + List tournamentList = tournamentRepository.findAllBetween(startTime, endTime); + for (Tournament tournament : tournamentList) { + if (targetTournamentId.equals(tournament.getId()) + || (!tournament.getStatus().equals(TournamentStatus.BEFORE) + && !tournament.getStatus() + .equals(TournamentStatus.LIVE))) { + continue; + } + throw new TournamentConflictException(); + } + } + + /** + *

ํƒ€๊ฒŸ ์‹œ๊ฐ„ ๋‚ด์— ๊ฒŒ์ž„์ด ์กด์žฌํ•˜๋Š”์ง€ ์ฒดํฌ

+ * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ + */ + private void checkGameExistence(LocalDateTime startTime, LocalDateTime endTime) { + gameRepository.findAllBetweenTournament(startTime, endTime).stream() + .findAny() + .ifPresent(a -> { + throw new TournamentConflictException(ErrorCode.TOURNAMENT_CONFLICT_GAME); + }); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ ์กฐํšŒ

+ * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id + * @param isJoined ์ฐธ๊ฐ€์ž์ธ์ง€ ๋Œ€๊ธฐ์ž์ธ์ง€ ์—ฌ๋ถ€ + * @return TournamentUserListResponseDto + * @throws TournamentNotFoundException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ + */ + public TournamentUserListResponseDto getTournamentUserList(Long tournamentId, Boolean isJoined) { + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (isJoined == null) { + return new TournamentUserListResponseDto(tournamentUserRepository.findAllByTournament(tournament)); + } else { + return new TournamentUserListResponseDto( + tournamentUserRepository.findAllByTournamentAndIsJoined(tournament, isJoined)); + } + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ •๋ณด ์ˆ˜์ •

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด + * @throws TournamentUpdateException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์‹œ์ž‘๋˜์ง€ ์•Š์•˜์„ ๋•Œ + */ + @Transactional + public void updateTournamentGame(Long tournamentId, TournamentGameUpdateRequestDto reqDto) { + if (reqDto.getTeam1().getScore() + reqDto.getTeam2().getScore() > 3 + || reqDto.getTeam1().getScore() + reqDto.getTeam2().getScore() < 2 + || reqDto.getTeam1().getScore() == reqDto.getTeam2().getScore()) { + throw new ScoreNotInvalidException(); + } + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (tournament.getStatus() == TournamentStatus.BEFORE) { + throw new TournamentUpdateException(ErrorCode.TOURNAMENT_IS_BEFORE); + } + TournamentGame tournamentGame = tournament.getTournamentGames().stream() + .filter(t -> t.getId().equals(reqDto.getTournamentGameId())).findAny() + .orElseThrow(TournamentGameNotFoundException::new); + Game game = tournamentGame.getGame(); + if (game == null) { + throw new TournamentGameNotFoundException(); + } + if (!canUpdateScore(tournamentGame, reqDto)) { + throw new TournamentUpdateException(ErrorCode.TOURNAMENT_INVALID_SCORE); + } + updateTeamScore(game, reqDto); + TournamentMatchStatus matchStatus = matchTournamentService.checkTournamentGame(game); + TournamentRound nextRound = tournamentGame.getTournamentRound().getNextRound(); + List teamUsers = new ArrayList<>(); + for (Team team : game.getTeams()) { + teamUsers.add(team.getTeamUsers().get(0)); + } + gameService.savePChange(game, teamUsers, teamUsers.get(0).getUser().getId()); + if (REQUIRED.equals(matchStatus)) { + matchTournamentService.matchGames(tournament, nextRound.getRoundNumber()); + } else if (ALREADY_MATCHED.equals(matchStatus)) { + Game nextMatchedGame = tournamentGameRepository.findByTournamentIdAndTournamentRound(tournament.getId(), + nextRound) + .orElseThrow(TournamentGameNotFoundException::new) + .getGame(); + matchTournamentService.updateMatchedGameUser(game, nextMatchedGame); + } + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ˆ˜์ •

+ * @param game ์ˆ˜์ •๋  ๊ฒŒ์ž„ + * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด + */ + private void updateTeamScore(Game game, TournamentGameUpdateRequestDto reqDto) { + + List teams = game.getTeams(); + Team team1 = teams.stream() + .filter(t -> t.getId().equals(reqDto.getTeam1().getTeamId())) + .findAny() + .orElseThrow(TournamentGameNotFoundException::new); + Team team2 = teams.stream() + .filter(t -> t.getId().equals(reqDto.getTeam2().getTeamId())) + .findAny() + .orElseThrow(TournamentGameNotFoundException::new); + team1.updateScore(reqDto.getTeam1().getScore(), reqDto.getTeam1().getScore() > reqDto.getTeam2().getScore()); + team2.updateScore(reqDto.getTeam2().getScore(), reqDto.getTeam2().getScore() > reqDto.getTeam1().getScore()); + if (game.getStatus() == StatusType.LIVE) { + game.updateStatus(); + } + game.updateStatus(); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ˆ˜์ • ๊ฐ€๋Šฅ ์—ฌ๋ถ€

+ * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด + * @return ์ˆ˜์ • ๊ฐ€๋Šฅ ์—ฌ๋ถ€ + */ + private boolean canUpdateScore(TournamentGame tournamentGame, TournamentGameUpdateRequestDto reqDto) { + if (tournamentGame.getGame().getStatus() == StatusType.BEFORE) { + return false; + } + if (reqDto.getNextTournamentGameId() == null) { + return tournamentGame.getTournamentRound() == TournamentRound.THE_FINAL; + } + TournamentGame nextTournamentGame = tournamentGameRepository.findById(reqDto.getNextTournamentGameId()) + .orElseThrow(TournamentGameNotFoundException::new); + if (nextTournamentGame.getGame() == null) { + return true; + } + if (nextTournamentGame.getGame().getStatus() == StatusType.BEFORE) { + return true; + } + return false; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/UserAdminController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/UserAdminController.java new file mode 100644 index 000000000..ebffae2c6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/UserAdminController.java @@ -0,0 +1,125 @@ +package gg.pingpong.api.admin.user.controller; + +import java.io.IOException; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import gg.pingpong.api.admin.user.controller.request.UserSearchAdminRequestDto; +import gg.pingpong.api.admin.user.controller.request.UserUpdateAdminRequestDto; +import gg.pingpong.api.admin.user.controller.response.UserDetailAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserImageListAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserSearchAdminResponseDto; +import gg.pingpong.api.admin.user.service.UserAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.utils.exception.user.UserImageLargeException; +import gg.utils.exception.user.UserImageTypeException; +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +@RequestMapping(value = "/pingpong/admin/users") +public class UserAdminController { + + private final UserAdminService userAdminService; + + @GetMapping + public UserSearchAdminResponseDto userSearchAll(@ModelAttribute @Valid UserSearchAdminRequestDto searchRequestDto) { + Pageable pageable = PageRequest.of(searchRequestDto.getPage() - 1, + searchRequestDto.getSize(), + Sort.by("intraId").ascending()); + if (searchRequestDto.getUserFilter() != null) { + return userAdminService.searchByIntraId(pageable, searchRequestDto.getUserFilter()); + } else if (searchRequestDto.getIntraId() != null) { + return userAdminService.findByPartsOfIntraId(searchRequestDto.getIntraId(), pageable); + } else { + return userAdminService.searchAll(pageable); + } + } + + @GetMapping("/{intraId}") + public UserDetailAdminResponseDto userGetDetail(@PathVariable String intraId) { + return userAdminService.getUserDetailByIntraId(intraId); + } + + @PutMapping("/{intraId}") + public ResponseEntity userUpdateDetail(@PathVariable String intraId, + @RequestPart UserUpdateAdminRequestDto updateUserInfo, + @RequestPart(required = false) MultipartFile imgData) throws IOException { + if (imgData != null) { + if (imgData.getSize() > 50000) { + throw new UserImageLargeException(); + } else if (imgData.getContentType() == null || !imgData.getContentType().equals("image/jpeg")) { + throw new UserImageTypeException(); + } + } + userAdminService.updateUserDetail(intraId, updateUserInfo, imgData); + + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/images/{intraId}") + public ResponseEntity deleteUserProfileImage(@PathVariable String intraId) { + userAdminService.deleteUserProfileImage(intraId); + return ResponseEntity.noContent().build(); + } + + @GetMapping("/delete-list") + public UserImageListAdminResponseDto getUserImageDeleteList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize(), + Sort.by("id").descending()); + return userAdminService.getUserImageDeleteList(pageable); + } + + @GetMapping("/delete-list/{intraId}") + public UserImageListAdminResponseDto getUserImageDeleteListByIntraId( + @ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageDeleteListByIntraId(pageable, intraId); + } + + @GetMapping("/images") + public UserImageListAdminResponseDto getUserImageList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageList(pageable); + } + + @GetMapping("/images/{intraId}") + public UserImageListAdminResponseDto getUserImage(@ModelAttribute @Valid PageRequestDto pageRequestDto, + @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageListByIntraId(pageable, intraId); + } + + @GetMapping("/images/current") + public UserImageListAdminResponseDto getUserImageCurrent(@ModelAttribute @Valid PageRequestDto pageRequestDto) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageCurrent(pageable); + } + + @GetMapping("/images/current/{intraId}") + public UserImageListAdminResponseDto getUserImageCurrentByIntraId( + @ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { + Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, + pageRequestDto.getSize()); + return userAdminService.getUserImageCurrentByIntraId(pageable, intraId); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserSearchAdminRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserSearchAdminRequestDto.java new file mode 100644 index 000000000..13eb69f47 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserSearchAdminRequestDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.admin.user.controller.request; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserSearchAdminRequestDto extends PageRequestDto { + private String intraId; + private String userFilter; + + public UserSearchAdminRequestDto(Integer page, Integer size, String intraId, String userFilter) { + super(page, size); + this.intraId = intraId; + this.userFilter = userFilter; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserUpdateAdminRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserUpdateAdminRequestDto.java new file mode 100644 index 000000000..780ec00f1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/request/UserUpdateAdminRequestDto.java @@ -0,0 +1,45 @@ +package gg.pingpong.api.admin.user.controller.request; + +import gg.data.user.type.RacketType; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class UserUpdateAdminRequestDto { + private RacketType racketType; + private String statusMessage; + private Integer wins; + private Integer losses; + private Integer ppp; + private String email; + private String roleType; + private Integer coin; + + @Override + public String toString() { + return "UserUpdateRequestAdminDto{" + + '\'' + + ", racketType=" + + racketType + + ", statusMessage='" + + statusMessage + + '\'' + + ", wins='" + + wins + '\'' + + ", losses'" + + losses + '\'' + + ", ppp='" + + ppp + '\'' + + ", email='" + + email + + '\'' + + ", roleType='" + + roleType + + '\'' + + ", coin='" + + coin + + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserDetailAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserDetailAdminResponseDto.java new file mode 100644 index 000000000..09a1ead42 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserDetailAdminResponseDto.java @@ -0,0 +1,75 @@ +package gg.pingpong.api.admin.user.controller.response; + +import gg.data.rank.redis.RankRedis; +import gg.data.user.User; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserDetailAdminResponseDto { + private Long userId; + private String intraId; + private String userImageUri; + private String racketType; + private String statusMessage; + private Integer wins; + private Integer losses; + private Integer ppp; + private String email; + private String roleType; + private Integer exp; + private Integer coin; + + public UserDetailAdminResponseDto(User user, RankRedis rank) { + this.userId = user.getId(); + this.intraId = user.getIntraId(); + this.userImageUri = user.getImageUri(); + this.racketType = user.getRacketType().getCode(); + this.statusMessage = rank.getStatusMessage(); + this.wins = rank.getWins(); + this.losses = rank.getLosses(); + this.ppp = rank.getPpp(); + this.email = user.getEMail(); + this.roleType = user.getRoleType().getKey(); + this.exp = user.getTotalExp(); + this.coin = user.getGgCoin(); + } + + public UserDetailAdminResponseDto(User user) { + this.userId = user.getId(); + this.intraId = user.getIntraId(); + this.userImageUri = user.getImageUri(); + this.racketType = user.getRacketType().getCode(); + this.statusMessage = ""; + this.wins = 0; + this.losses = 0; + this.ppp = 0; + this.email = user.getEMail() == null ? "" : user.getEMail(); + this.roleType = user.getRoleType().getKey(); + this.exp = user.getTotalExp(); + this.coin = user.getGgCoin(); + } + + @Override + public String toString() { + return "UserDetailResponseDto{" + + "intraId='" + intraId + '\'' + + ", userImageUri='" + userImageUri + + '\'' + + ", racketType='" + + racketType + '\'' + + ", statusMessage='" + + statusMessage + '\'' + + ", wins='" + wins.toString() + + '\'' + ", losses='" + losses.toString() + + '\'' + ", ppp='" + ppp.toString() + '\'' + + ", email='" + email + '\'' + ", roleType='" + + roleType + '\'' + + ", coin='" + coin + + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserImageListAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserImageListAdminResponseDto.java new file mode 100644 index 000000000..0ce28e093 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserImageListAdminResponseDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.admin.user.controller.response; + +import java.util.List; + +import gg.pingpong.api.admin.user.dto.UserImageAdminDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserImageListAdminResponseDto { + private List userImageList; + private int totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserSearchAdminResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserSearchAdminResponseDto.java new file mode 100644 index 000000000..03afcd776 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/controller/response/UserSearchAdminResponseDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.admin.user.controller.response; + +import java.util.List; +import java.util.stream.Collectors; + +import gg.pingpong.api.admin.user.dto.UserSearchAdminDto; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserSearchAdminResponseDto { + private List userSearchAdminDtos; + private Integer totalPage; + + public void filterUser(String filterString) { + if (filterString == null) { + return; + } + this.userSearchAdminDtos = this.userSearchAdminDtos.stream() + .filter(userSearchAdminDto -> userSearchAdminDto.getIntraId().equals(filterString)) + .collect(Collectors.toList()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserAdminDto.java new file mode 100644 index 000000000..fbf43045e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserAdminDto.java @@ -0,0 +1,61 @@ +package gg.pingpong.api.admin.user.dto; + +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserAdminDto { + private Long id; + private String intraId; + private String eMail; + private String imageUri; + private RacketType racketType; + private RoleType roleType; + private Integer totalExp; + private SnsType snsNotiOpt; + + public static UserAdminDto from(User user, UserImage userImage) { + UserAdminDto userDto; + if (user == null) { + userDto = null; + } else { + userDto = UserAdminDto.builder() + .id(user.getId()) + .intraId(user.getIntraId()) + .eMail(user.getEMail()) + .imageUri(userImage.getImageUri()) + .racketType(user.getRacketType()) + .roleType(user.getRoleType()) + .totalExp(user.getTotalExp()) + .snsNotiOpt(user.getSnsNotiOpt()) + .build(); + } + return userDto; + } + + @Override + public String toString() { + return "UserDto{" + + "id=" + + id + + ", intraId='" + + intraId + '\'' + + ", eMail='" + + eMail + '\'' + + ", imageUri='" + + imageUri + '\'' + + ", racketType=" + + racketType + '\'' + + ", roleType=" + + roleType + '\'' + + ", totalExp=" + + totalExp + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserImageAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserImageAdminDto.java new file mode 100644 index 000000000..4031d8213 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserImageAdminDto.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.admin.user.dto; + +import java.time.LocalDateTime; + +import gg.data.user.UserImage; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserImageAdminDto { + Long id; + String userIntraId; + String imageUri; + LocalDateTime createdAt; + LocalDateTime deletedAt; + Boolean isCurrent; + + public UserImageAdminDto(UserImage userImage) { + this.id = userImage.getId(); + this.userIntraId = userImage.getUser().getIntraId(); + this.imageUri = userImage.getImageUri(); + this.createdAt = userImage.getCreatedAt(); + this.deletedAt = userImage.getDeletedAt(); + this.isCurrent = userImage.getIsCurrent(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserSearchAdminDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserSearchAdminDto.java new file mode 100644 index 000000000..9a40f8e80 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/dto/UserSearchAdminDto.java @@ -0,0 +1,32 @@ +package gg.pingpong.api.admin.user.dto; + +import gg.data.user.User; +import gg.data.user.type.RoleType; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserSearchAdminDto { + private Long id; + private String intraId; + private String statusMessage; + private RoleType roleType; + + public UserSearchAdminDto(User user, String statusMessage) { + this.id = user.getId(); + this.intraId = user.getIntraId(); + this.statusMessage = statusMessage; + this.roleType = user.getRoleType(); + } + + @Override + public String toString() { + return "{" + + "id=" + id + + ", intraId='" + intraId + '\'' + + ", statusMessage='" + statusMessage + '\'' + + ", roleType=" + roleType + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/service/UserAdminService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/service/UserAdminService.java new file mode 100644 index 000000000..f56d50271 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/admin/user/service/UserAdminService.java @@ -0,0 +1,211 @@ +package gg.pingpong.api.admin.user.service; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import gg.admin.repo.season.SeasonAdminRepository; +import gg.admin.repo.user.UserAdminRepository; +import gg.admin.repo.user.UserImageAdminRepository; +import gg.data.rank.Rank; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.data.user.type.RoleType; +import gg.pingpong.api.admin.rank.service.RankRedisAdminService; +import gg.pingpong.api.admin.user.controller.request.UserUpdateAdminRequestDto; +import gg.pingpong.api.admin.user.controller.response.UserDetailAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserImageListAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserSearchAdminResponseDto; +import gg.pingpong.api.admin.user.dto.UserImageAdminDto; +import gg.pingpong.api.admin.user.dto.UserSearchAdminDto; +import gg.pingpong.api.global.utils.aws.AsyncNewUserImageUploader; +import gg.pingpong.api.user.user.service.UserFindService; +import gg.repo.rank.RankRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.rank.RankNotFoundException; +import gg.utils.exception.rank.RedisDataNotFoundException; +import gg.utils.exception.season.SeasonNotFoundException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class UserAdminService { + + private final UserAdminRepository userAdminRepository; + private final SeasonAdminRepository seasonAdminRepository; + private final RankRepository rankRepository; + private final RankRedisRepository rankRedisRepository; + private final RankRedisAdminService rankRedisAdminService; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final UserFindService userFindService; + private final UserImageAdminRepository userImageAdminRepository; + + @Transactional(readOnly = true) + public UserSearchAdminResponseDto searchAll(Pageable pageable) { + Page userPage = userAdminRepository.findAll(pageable); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) { + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + } + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserSearchAdminResponseDto searchByIntraId(Pageable pageable, String intraId) { + Page userPage = userAdminRepository.findByIntraId(pageable, intraId); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) { + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + } + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + /* ๋ฌธ์ž์—ด์„ ํฌํ•จํ•˜๋Š” intraId๋ฅผ ๊ฐ€์ง„ ์œ ์ € ์ฐพ๊ธฐ */ + @Transactional(readOnly = true) + public UserSearchAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { + Page userPage = userAdminRepository.findByIntraIdContains(pageable, intraId); + List userSearchAdminDtos = new ArrayList(); + for (User user : userPage.getContent()) { + userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); + } + return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserDetailAdminResponseDto getUserDetailByIntraId(String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()) + .orElseThrow(SeasonNotFoundException::new); + try { + RankRedis userCurrRank = rankRedisRepository.findRankByUserId( + RedisKeyManager.getHashKey(currSeason.getId()), + user.getId()); + return new UserDetailAdminResponseDto(user, userCurrRank); + } catch (RedisDataNotFoundException e) { + return new UserDetailAdminResponseDto(user); + } + } + + @Transactional + public void updateUserDetail(String intraId, + UserUpdateAdminRequestDto userUpdateAdminRequestDto, + MultipartFile userImageFile) throws IOException { + Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()) + .orElseThrow(() -> new SeasonNotFoundException()); + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + + user.modifyUserDetail(userUpdateAdminRequestDto.getEmail(), userUpdateAdminRequestDto.getRacketType(), + RoleType.of(userUpdateAdminRequestDto.getRoleType()), userUpdateAdminRequestDto.getCoin()); + if (userImageFile != null) { + asyncNewUserImageUploader.update(intraId, userImageFile); + } + updateUserRank(user.getId(), currSeason.getId(), userUpdateAdminRequestDto); + } + + private void updateUserRank(Long userId, Long currSeasonId, UserUpdateAdminRequestDto updateReq) { + Rank userCurrRank = rankRepository.findByUserIdAndSeasonId(userId, currSeasonId) + .orElseThrow(RankNotFoundException::new); + RankRedis userCurrRankRedis = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeasonId), + userId); + + userCurrRank.modifyUserRank(updateReq.getPpp(), + updateReq.getWins(), + updateReq.getLosses()); + userCurrRank.setStatusMessage(updateReq.getStatusMessage()); + + userCurrRankRedis.changedRank(updateReq.getPpp(), + updateReq.getWins(), + updateReq.getLosses()); + userCurrRankRedis.setStatusMessage(updateReq.getStatusMessage()); + rankRedisAdminService.updateRankUser(RedisKeyManager.getHashKey(currSeasonId), + RedisKeyManager.getZSetKey(currSeasonId), + userId, userCurrRankRedis); + } + + public String getUserImageToString(User user) { + UserImage userImage = userImageAdminRepository.findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(user) + .orElse(null); + if (userImage == null) { + return "null"; + } else { + userImage.updateIsCurrent(); + return userImage.getImageUri(); + } + } + + @Transactional + public void deleteUserProfileImage(String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + UserImage userImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user) + .orElseThrow(UserNotFoundException::new); + userImage.updateDeletedAt(LocalDateTime.now()); + String userImageUri = getUserImageToString(user); + user.updateImageUri(userImageUri); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageDeleteList(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllByDeletedAtNotNullOrderByDeletedAtDesc( + pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageDeleteListByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc( + user.getId(), pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageList(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllChangedOrderByCreatedAtDesc(pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageListByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserOrderByCreatedAtDesc(user.getId(), + pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageCurrent(Pageable pageable) { + Page userImagePage = userImageAdminRepository.findAllByIsCurrentTrueOrderByCreatedAtDesc(pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } + + @Transactional(readOnly = true) + public UserImageListAdminResponseDto getUserImageCurrentByIntraId(Pageable pageable, String intraId) { + User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + Page userImagePage = userImageAdminRepository.findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc( + user.getId(), pageable); + Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); + + return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AWSConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AWSConfig.java new file mode 100644 index 000000000..358d0dd99 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AWSConfig.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.global.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; + +@Configuration +public class AWSConfig { + + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3 amazonS3Client() { + AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + + return AmazonS3ClientBuilder + .standard() + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .withRegion(region) + .build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AsyncConfiguration.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AsyncConfiguration.java new file mode 100644 index 000000000..de843ca2c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/AsyncConfiguration.java @@ -0,0 +1,38 @@ +package gg.pingpong.api.global.config; + +import java.util.concurrent.Executor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class AsyncConfiguration implements AsyncConfigurer { + + private static Logger logger = LoggerFactory.getLogger(AsyncConfiguration.class); + + @Override + @Bean(name = "asyncExecutor") + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(20); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("MailExecutor-"); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return (ex, method, params) -> + logger.error("Exception handler for async method '" + method.toGenericString() + + "' threw unexpected exception itself", ex); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/ConstantConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/ConstantConfig.java new file mode 100644 index 000000000..e06151534 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/ConstantConfig.java @@ -0,0 +1,24 @@ +package gg.pingpong.api.global.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import lombok.Getter; + +/** + * ConstantConfig. + * + *

+ * yml ํŒŒ์ผ์— ์ •์˜๋œ ๋ณ€์ˆ˜๋“ค์„ ๊ฐ€์ ธ์˜ค๋Š” ํด๋ž˜์Šค. + *

+ * + */ +@Component +@Getter +public class ConstantConfig { + @Value("${constant.allowedMinimalStartDays}") + private int allowedMinimalStartDays; + + @Value("${constant.tournamentSchedule}") + private String tournamentSchedule; +} diff --git a/src/main/java/com/gg/server/global/config/JpaAuditingConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaAuditingConfig.java similarity index 84% rename from src/main/java/com/gg/server/global/config/JpaAuditingConfig.java rename to gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaAuditingConfig.java index cad341081..5405f9fbe 100644 --- a/src/main/java/com/gg/server/global/config/JpaAuditingConfig.java +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaAuditingConfig.java @@ -1,4 +1,4 @@ -package com.gg.server.global.config; +package gg.pingpong.api.global.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaConfig.java new file mode 100644 index 000000000..6bb8e11f9 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/JpaConfig.java @@ -0,0 +1,11 @@ +package gg.pingpong.api.global.config; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EnableJpaRepositories(basePackages = {"gg.repo", "gg.admin.repo"}) +@EntityScan(basePackages = "gg.data") +public class JpaConfig { +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/RedisConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/RedisConfig.java new file mode 100644 index 000000000..90726d80c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/RedisConfig.java @@ -0,0 +1,117 @@ +package gg.pingpong.api.global.config; + +import java.time.Duration; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.session.data.redis.config.ConfigureRedisAction; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * Redis ์„ค์ • + */ +@Configuration +@EnableCaching +@EnableRedisRepositories +@EnableTransactionManagement +public class RedisConfig { + + /** + * Redis Host + */ + @Value("${spring.redis.host}") + private String host; + + /** + * Redis Port + */ + @Value("${spring.redis.port}") + private int port; + + /** + * Redis Connection Factory + *

+ * redisConnectionFactory() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด RedisConnectionFactory ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ํ†ตํ•ด RedisTemplate ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํ•ด๋‹น + * ๊ธฐ๋Šฅ์€ Spring Boot ์—์„œ ์ž๋™์œผ๋กœ ์ œ๊ณตํ•ด์ฃผ์ง€๋งŒ, RedisConnectionFactory ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•˜๊ธฐ ์œ„ํ•ด ์ง์ ‘ ์ƒ์„ฑ + * + * @return + */ + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(host, port); + } + + /** + * ์บ์‹œ ๊ด€๋ฆฌ์ž + *

+ * RedisCacheManager ๋ฅผ ํ†ตํ•ด Redis ์— ๋Œ€ํ•œ ์บ์‹œ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ์บ์‹œ์˜ ๊ธฐ๋ณธ ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด RedisCacheConfiguration ์„ ์‚ฌ์šฉํ•œ๋‹ค. + * + * @param connectionFactory + * @return + */ + @Bean + public CacheManager gameCacheManager(RedisConnectionFactory connectionFactory) { + RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(redisConnectionFactory()); + RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer( + new GenericJackson2JsonRedisSerializer())) // Value Serializer ๋ณ€๊ฒฝ + .entryTtl(Duration.ofMinutes(30)); // ์บ์‹œ ์ˆ˜๋ช… + builder.cacheDefaults(configuration); + return builder.build(); + } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + final RedisTemplate redisTemplate = new RedisTemplate<>(); + + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + + redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setEnableTransactionSupport(true); // <= + + return redisTemplate; + } + + /** + * StringRedisTemplate + *

+ * StringRedisTemplate ์„ ํ†ตํ•ด Redis ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations redisListTemplate(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * ConfigureRedisAction + *

+ * Elasticache๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, CONFIG ๋ช…๋ น์–ด ์‚ฌ์šฉ์ด ์ œํ•œ๋จ์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ + * + * @return ConfigureRedisAction + */ + @Bean + public ConfigureRedisAction configureRedisAction() { + return ConfigureRedisAction.NO_OP; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/SwaggerConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/SwaggerConfig.java new file mode 100644 index 000000000..7af1049e5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/SwaggerConfig.java @@ -0,0 +1,54 @@ +package gg.pingpong.api.global.config; + +import org.springdoc.core.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; + +@Configuration +public class SwaggerConfig { + @Bean + public GroupedOpenApi group1() { + return GroupedOpenApi.builder() + .group("pingpong") + .pathsToMatch("/pingpong/**") + .packagesToScan("gg.pingpong.api.user") + .build(); + } + + @Bean + public GroupedOpenApi admin_group() { + return GroupedOpenApi.builder() + .group("pingpong admin") + .pathsToMatch("/pingpong/admin/**") + .build(); + } + + @Bean + public OpenAPI springShopOpenAPI() { + String jwtSchemeName = "jwtAuth"; + SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); + Components components = new Components() + .addSecuritySchemes(jwtSchemeName, new SecurityScheme() + .name(jwtSchemeName) + .type(SecurityScheme.Type.HTTP) + .scheme("Bearer") + .bearerFormat("JWT")); + Server server = new Server(); + server.setUrl("/"); + server.setDescription("test Server url"); + return new OpenAPI() + .info(new Info().title("42GG V2 API") + .description("42GG ๋ฐฑ์—”๋“œ ํ”„๋กœ์ ํŠธ API ๋ช…์„ธ์„œ์ž…๋‹ˆ๋‹ค.") + .version("v2.0.0")) + .addServersItem(server) + .addSecurityItem(securityRequirement) + .components(components); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/TimeZoneConfiguration.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/TimeZoneConfiguration.java new file mode 100644 index 000000000..c19f8d3ea --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/TimeZoneConfiguration.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.global.config; + +import java.util.TimeZone; + +import javax.annotation.PostConstruct; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TimeZoneConfiguration { + + @PostConstruct + public void init() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/WebConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/WebConfig.java new file mode 100644 index 000000000..9b8e1c539 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/config/WebConfig.java @@ -0,0 +1,32 @@ +package gg.pingpong.api.global.config; + +import java.util.List; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.utils.argumentresolver.LoginMemberArgumentResolver; +import gg.pingpong.api.global.utils.querytracker.LoggingInterceptor; +import gg.repo.user.UserRepository; +import lombok.RequiredArgsConstructor; + +@Configuration +@RequiredArgsConstructor +public class WebConfig implements WebMvcConfigurer { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + private final LoggingInterceptor loggingInterceptor; + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new LoginMemberArgumentResolver(userRepository, tokenProvider)); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loggingInterceptor); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/dto/PageRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/dto/PageRequestDto.java new file mode 100644 index 000000000..868992210 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/dto/PageRequestDto.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.global.dto; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PageRequestDto { + + @Min(value = 1, message = "page must be greater than 0") + @NotNull(message = "page ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + private Integer page; + + @Min(value = 1, message = "size must be greater than 0") + @Max(value = 30, message = "size must be less than 30") + private Integer size = 20; + + public PageRequestDto(Integer page, Integer size) { + this.page = page; + if (size == null) { + this.size = 20; + } else { + this.size = size; + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/exception/GlobalExceptionHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..697150080 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/exception/GlobalExceptionHandler.java @@ -0,0 +1,134 @@ +package gg.pingpong.api.global.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.ErrorResponse; +import gg.utils.exception.custom.AuthenticationException; +import gg.utils.exception.custom.CustomRuntimeException; +import gg.utils.exception.custom.DBConsistencyException; +import gg.utils.exception.custom.DuplicationException; +import gg.utils.exception.custom.ForbiddenException; +import gg.utils.exception.custom.NotExistException; +import gg.utils.exception.custom.PageNotFoundException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler({BindException.class}) + public ResponseEntity validException(BindException ex) { + log.error("bind error", ex.getBindingResult().getAllErrors().get(0)); + ErrorCode ec = ErrorCode.VALID_FAILED; + ec.setMessage(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage()); + ErrorResponse response = new ErrorResponse(ec); + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler({MethodArgumentTypeMismatchException.class}) + public ResponseEntity typeErrorException(MethodArgumentTypeMismatchException ex) { + log.error("type error", ex.getMessage()); + ErrorCode ec = ErrorCode.VALID_FAILED; + ec.setMessage(ex.getMessage()); + ErrorResponse response = new ErrorResponse(ec); + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler({DBConsistencyException.class}) + public ResponseEntity dbConsistencyException(DBConsistencyException ex) { + log.error("db ์ •ํ•ฉ์„ฑ ์˜ค๋ฅ˜", ex); + return new ResponseEntity<>(new ErrorResponse(ex.getErrorCode()), HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler({NotExistException.class, PageNotFoundException.class}) + public ResponseEntity notFoundException(CustomRuntimeException ex) { + log.error("Not Exist", ex); + ErrorResponse response = new ErrorResponse(ex.getErrorCode()); + return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler({DuplicationException.class}) + public ResponseEntity duplicatedException(DuplicationException ex) { + log.error("Duplicated", ex); + return new ResponseEntity<>(new ErrorResponse(ex.getErrorCode()), HttpStatus.CONFLICT); + } + + @ExceptionHandler({ForbiddenException.class}) + public ResponseEntity forbiddenException(ForbiddenException ex) { + log.error("forbidden", ex); + ErrorResponse response = new ErrorResponse(ex.getErrorCode()); + return new ResponseEntity<>(response, HttpStatus.FORBIDDEN); + } + + @ExceptionHandler({CustomRuntimeException.class}) + public ResponseEntity validException(CustomRuntimeException ex) { + log.error("์˜ˆ์™ธ์ฒ˜๋ฆฌ๋œ ์—๋Ÿฌ", ex.getMessage(), ex.getErrorCode()); + ErrorResponse response = new ErrorResponse(ex.getErrorCode()); + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(AuthenticationException.class) + public ResponseEntity authenticationException(AuthenticationException ex) { + log.error("authentication exception"); + ErrorResponse response = new ErrorResponse(ex.getErrorCode()); + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); + } + + @ExceptionHandler(AmazonServiceException.class) + protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle(AmazonServiceException ex) { + log.error("AmazonServiceException", ex); + ErrorResponse response = new ErrorResponse(ErrorCode.AWS_S3_ERR); + return new ResponseEntity<>(response, HttpStatus.valueOf(ex.getStatusCode())); + } + + @ExceptionHandler(SdkClientException.class) + protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle(SdkClientException ex) { + log.error("AmazonServiceException", ex.getMessage()); + ErrorResponse response = new ErrorResponse(ErrorCode.AWS_SERVER_ERR); + return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler({RuntimeException.class}) + public ResponseEntity runtimeException(RuntimeException ex) { + log.error("์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค.", ex); + ErrorResponse response = new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERR); + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle( + HttpRequestMethodNotSupportedException ex) { + log.error("์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.", ex.getMethod()); + ErrorResponse response = new ErrorResponse(ErrorCode.METHOD_NOT_ALLOWED); + return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception ex) { + log.error("!!!!!! SERVER ERROR !!!!!!", ex.getMessage()); + ErrorResponse response = new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERR); + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + protected ResponseEntity handleException(HttpMessageNotReadableException exception) { + return ResponseEntity.badRequest().body(ErrorCode.UNREADABLE_HTTP_MESSAGE.getMessage()); + } + + @ExceptionHandler(MissingServletRequestParameterException.class) + protected ResponseEntity handleException(MissingServletRequestParameterException exception) { + return ResponseEntity.badRequest().body(ErrorCode.BAD_ARGU.getMessage()); + } +} diff --git a/src/main/java/com/gg/server/global/log/annotation/Trace.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/annotation/Trace.java similarity index 84% rename from src/main/java/com/gg/server/global/log/annotation/Trace.java rename to gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/annotation/Trace.java index 2a71f4788..cf362b3c0 100644 --- a/src/main/java/com/gg/server/global/log/annotation/Trace.java +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/annotation/Trace.java @@ -1,4 +1,4 @@ -package com.gg.server.global.log.annotation; +package gg.pingpong.api.global.log.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/aspect/TraceAspect.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/aspect/TraceAspect.java new file mode 100644 index 000000000..0e41ba5fa --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/aspect/TraceAspect.java @@ -0,0 +1,57 @@ +package gg.pingpong.api.global.log.aspect; + +import java.util.Arrays; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import gg.pingpong.api.global.log.domain.TraceStatus; +import gg.pingpong.api.global.log.service.LogTrace; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Aspect +@AllArgsConstructor +@Component +public class TraceAspect { + private final LogTrace logTrace; + + @Pointcut("execution(* gg.pingpong.api.admin..*(..))") + public void allAdmin() { + } + + @Pointcut("execution(* gg.pingpong.api.user..*(..))") + public void allDomain() { + } + + @Pointcut("execution(* gg.pingpong.api.global.security..*(..))") + public void securityDomain() { + } + + @Pointcut("execution(* gg.pingpong.api.global.scheduler..*(..))") + public void scheduler() { + } + + @Around("(allAdmin() || allDomain() || scheduler()) && !securityDomain()") + public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable { + TraceStatus status = null; + MethodSignature method = (MethodSignature)joinPoint.getSignature(); + Object[] methodArgs = joinPoint.getArgs(); + try { + status = logTrace.begin( + method.getDeclaringType().getSimpleName() + "." + method.getName() + "(): arguments = " + + Arrays.toString(methodArgs)); + Object result = joinPoint.proceed(); + logTrace.end(status); + return result; + } catch (Exception e) { + logTrace.exception(status, e); + throw e; + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceId.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceId.java new file mode 100644 index 000000000..b4e3c1ada --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceId.java @@ -0,0 +1,42 @@ +package gg.pingpong.api.global.log.domain; + +import java.util.UUID; + +public class TraceId { + private String id; + private int level; + + public TraceId() { + this.id = createId(); + this.level = 0; + } + + private TraceId(String id, int level) { + this.id = id; + this.level = level; + } + + private String createId() { + return UUID.randomUUID().toString().substring(0, 8); + } + + public TraceId createNextId() { + return new TraceId(id, level + 1); + } + + public TraceId createPreviousId() { + return new TraceId(id, level - 1); + } + + public boolean isFirstLevel() { + return level == 0; + } + + public String getId() { + return id; + } + + public int getLevel() { + return level; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceStatus.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceStatus.java new file mode 100644 index 000000000..99e180c88 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/domain/TraceStatus.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.global.log.domain; + +import lombok.Getter; + +@Getter +public class TraceStatus { + private TraceId traceId; + private Long startTimeMs; + private String message; + + public TraceStatus(TraceId traceId, Long startTimeMs, String message) { + this.traceId = traceId; + this.startTimeMs = startTimeMs; + this.message = message; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/pointcut/TracePointcut.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/pointcut/TracePointcut.java new file mode 100644 index 000000000..082cc3bc7 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/pointcut/TracePointcut.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.global.log.pointcut; + +import org.aspectj.lang.annotation.Pointcut; + +public class TracePointcut { + @Pointcut("execution(* gg.pingpong.api.user..*(..))") + public void allDomain() { + } + + //ํƒ€์ž… ํŒจํ„ด์ด *Service + @Pointcut("execution(* *..*Service.*(..))") + public void allService() { + } + + //allOrder && allService + @Pointcut("allDomain() && allService()") + public void orderAndService() { + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/LogTrace.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/LogTrace.java new file mode 100644 index 000000000..a7d70b478 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/LogTrace.java @@ -0,0 +1,11 @@ +package gg.pingpong.api.global.log.service; + +import gg.pingpong.api.global.log.domain.TraceStatus; + +public interface LogTrace { + TraceStatus begin(String message); + + void end(TraceStatus status); + + void exception(TraceStatus status, Exception ex); +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/ThreadLocalLogTrace.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/ThreadLocalLogTrace.java new file mode 100644 index 000000000..db9c037c1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/log/service/ThreadLocalLogTrace.java @@ -0,0 +1,79 @@ +package gg.pingpong.api.global.log.service; + +import org.springframework.stereotype.Component; + +import gg.pingpong.api.global.log.domain.TraceId; +import gg.pingpong.api.global.log.domain.TraceStatus; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class ThreadLocalLogTrace implements LogTrace { + + private static final String START_PREFIX = "-->"; + private static final String COMPLETE_PREFIX = "<--"; + private static final String EX_PREFIX = " traceIdHolder = new ThreadLocal<>(); + + public TraceStatus begin(String message) { + syncTraceId(); + TraceId logId = traceIdHolder.get(); + Long startTimeMs = System.currentTimeMillis(); + log.info("[{}] {}{}", logId.getId(), addSpace(START_PREFIX, logId.getLevel()), message); + + return new TraceStatus(logId, startTimeMs, message); + } + + public void end(TraceStatus status) { + complete(status, null); + } + + @Override + public void exception(TraceStatus status, Exception exception) { + if (status != null) { + complete(status, exception); + } + } + + private void complete(TraceStatus status, Exception exception) { + Long stopTimeMs = System.currentTimeMillis(); + long resultTimeMs = stopTimeMs - status.getStartTimeMs(); + TraceId traceId = status.getTraceId(); + if (exception == null) { + log.info("[{}] {}{} time={}ms", traceId.getId(), addSpace(COMPLETE_PREFIX, traceId.getLevel()), + status.getMessage(), resultTimeMs); + } else { + log.info("[{}] {}{} time={}ms ex={}", traceId.getId(), addSpace(EX_PREFIX, traceId.getLevel()), + status.getMessage(), resultTimeMs, exception.toString()); + } + + releaseTraceId(); + } + + private void syncTraceId() { + TraceId traceId = traceIdHolder.get(); + if (traceId == null) { + traceIdHolder.set(new TraceId()); + } else { + traceIdHolder.set(traceId.createNextId()); + } + } + + private void releaseTraceId() { + TraceId traceId = traceIdHolder.get(); + if (traceId.isFirstLevel()) { + traceIdHolder.remove(); + } else { + traceIdHolder.set(traceId.createPreviousId()); + } + } + + private static String addSpace(String prefix, int level) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < level; i++) { + sb.append((i == level - 1) ? "|" + prefix : "| "); + } + return sb.toString(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/AbstractScheduler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/AbstractScheduler.java new file mode 100644 index 000000000..8dd5c1598 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/AbstractScheduler.java @@ -0,0 +1,49 @@ +package gg.pingpong.api.global.scheduler; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; + +import lombok.Getter; + +public abstract class AbstractScheduler { + private ThreadPoolTaskScheduler scheduler; + @Getter + protected String cron; + @Getter + protected Integer interval; + + public abstract Runnable runnable(); + + public void renewScheduler() { + scheduler.shutdown(); + startScheduler(); + } + + protected void setCron(String cron) { + this.cron = cron; + } + + protected void setInterval(Integer interval) { + this.interval = interval; + } + + @PostConstruct + public void init() { + startScheduler(); + } + + @PreDestroy + public void destroy() { + scheduler.shutdown(); + } + + private void startScheduler() { + scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(4); + scheduler.initialize(); + scheduler.schedule(this.runnable(), new CronTrigger(cron)); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/GameStatusScheduler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/GameStatusScheduler.java new file mode 100644 index 000000000..ce06d61ee --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/GameStatusScheduler.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.global.scheduler; + +import org.springframework.stereotype.Component; + +import gg.pingpong.api.user.game.service.GameStatusService; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class GameStatusScheduler extends AbstractScheduler { + private final GameStatusService gameStatusService; + + public GameStatusScheduler(GameStatusService gameStatusService) { + this.gameStatusService = gameStatusService; + this.setCron("0 */5 * * * *"); + } + + @Override + public Runnable runnable() { + return () -> { + log.info("GameStatusScheduler start"); + // BEFORE -> LIVE + gameStatusService.updateBeforeToLiveStatus(); + // LIVE -> WAIT + gameStatusService.updateLiveToWaitStatus(); + // imminent Noti + gameStatusService.imminentGame(); + }; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/MegaphoneScheduler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/MegaphoneScheduler.java new file mode 100644 index 000000000..c14b1961e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/MegaphoneScheduler.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.global.scheduler; + +import java.time.LocalDate; + +import org.springframework.stereotype.Component; + +import gg.pingpong.api.user.store.service.MegaphoneService; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class MegaphoneScheduler extends AbstractScheduler { + private final MegaphoneService megaphoneService; + + public MegaphoneScheduler(MegaphoneService megaphoneService) { + this.megaphoneService = megaphoneService; + this.setCron("0 59 23 * * *"); + } + + @Override + public Runnable runnable() { + return () -> { + log.info("Set Megaphone List "); + megaphoneService.setMegaphoneList(LocalDate.now()); + }; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/TournamentScheduler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/TournamentScheduler.java new file mode 100644 index 000000000..2929d3b92 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/scheduler/TournamentScheduler.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.global.scheduler; + +import org.springframework.stereotype.Component; + +import gg.pingpong.api.global.config.ConstantConfig; +import gg.pingpong.api.user.tournament.service.TournamentService; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class TournamentScheduler extends AbstractScheduler { + private final TournamentService tournamentService; + + private final ConstantConfig constantConfig; + + public TournamentScheduler(TournamentService tournamentService, ConstantConfig constantConfig) { + this.tournamentService = tournamentService; + this.constantConfig = constantConfig; + this.cron = constantConfig.getTournamentSchedule(); // TODO QA ์ดํ›„ 0 0 0 * * * ๋กœ ๋ณ€๊ฒฝ + } + + @Override + public Runnable runnable() { + return () -> { + log.info("Tournament Scheduler Started"); + tournamentService.startTournament(); + }; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/UserPrincipal.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/UserPrincipal.java new file mode 100644 index 000000000..2861aaab7 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/UserPrincipal.java @@ -0,0 +1,85 @@ +package gg.pingpong.api.global.security; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import gg.data.user.User; +import gg.data.user.type.RoleType; +import lombok.Getter; + +@Getter +public class UserPrincipal implements OAuth2User, UserDetails { + private final Long id; + private final String nickname; + private final Collection authorities; + private Map attributes; + + public UserPrincipal(Long id, String nickname, Collection authorities) { + this.id = id; + this.nickname = nickname; + this.authorities = authorities; + } + + public static UserPrincipal create(User user) { + List authorities = new ArrayList<>(); + if (user.getRoleType().getKey().equals("ROLE_USER")) { + authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); + } else if (user.getRoleType().getKey().equals("ROLE_ADMIN")) { + authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); + authorities.add(new SimpleGrantedAuthority(RoleType.ADMIN.getKey())); + } + return new UserPrincipal(user.getId(), user.getIntraId(), authorities); + } + + public static UserPrincipal create(User user, Map attributes) { + UserPrincipal userPrincipal = UserPrincipal.create(user); + userPrincipal.setAttributes(attributes); + return userPrincipal; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return nickname; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public String getName() { + return String.valueOf(id); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/RestAuthenticationEntryPoint.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/RestAuthenticationEntryPoint.java new file mode 100644 index 000000000..2aa870794 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/RestAuthenticationEntryPoint.java @@ -0,0 +1,28 @@ +package gg.pingpong.api.global.security.config; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException + ) throws IOException { + authException.printStackTrace(); + log.info("Responding with unauthorized error. Message := {}", authException.getMessage()); + response.sendError( + HttpServletResponse.SC_UNAUTHORIZED, + authException.getLocalizedMessage() + ); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/SecurityConfig.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/SecurityConfig.java new file mode 100644 index 000000000..d753dc531 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/SecurityConfig.java @@ -0,0 +1,92 @@ +package gg.pingpong.api.global.security.config; + +import java.util.Arrays; + +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import gg.pingpong.api.global.security.config.properties.CorsProperties; +import gg.pingpong.api.global.security.handler.OAuthAuthenticationSuccessHandler; +import gg.pingpong.api.global.security.jwt.utils.TokenAuthenticationFilter; +import gg.pingpong.api.global.security.repository.OAuthAuthorizationRequestBasedOnCookieRepository; +import gg.pingpong.api.global.security.service.CustomUserDetailsService; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final CustomUserDetailsService userDetailsService; + private final OAuthAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; + private final CorsProperties corsProperties; + private final TokenAuthenticationFilter tokenAuthenticationFilter; + private final OAuthAuthorizationRequestBasedOnCookieRepository oAuth2AuthorizationRequestBasedOnCookieRepository; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .cors() + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeRequests() + .antMatchers("/pingpong/admin/**").hasRole("ADMIN") + .antMatchers(HttpMethod.PUT, "/pingpong/users/{intraId}").hasAnyRole("USER", "ADMIN") + .antMatchers(HttpMethod.POST, "/pingpong/match").hasAnyRole("USER", "ADMIN") + .antMatchers(HttpMethod.POST, "/pingpong/tournaments/{tournamentId}/users").hasAnyRole("USER", "ADMIN") + .antMatchers("/login", "/oauth2/authorization/**", "/", "/pingpong/users/oauth/**", + "/pingpong/users/accesstoken", "/actuator/**", + "/swagger-ui/**", "/swagger-ui**", "/v3/api-docs/**", "/v3/api-docs**", "/api-docs").permitAll() + .anyRequest().authenticated() + .and() + .csrf().disable() + .formLogin().disable() + .httpBasic().disable() + .exceptionHandling() + .authenticationEntryPoint(new RestAuthenticationEntryPoint()) + .and() + .oauth2Login() + .authorizationEndpoint() + .baseUri("/oauth2/authorization") + .authorizationRequestRepository(oAuth2AuthorizationRequestBasedOnCookieRepository) + .and() + .successHandler(oAuth2AuthenticationSuccessHandler); + + http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + } + + @Bean + public UrlBasedCorsConfigurationSource corsConfigurationSource() { + UrlBasedCorsConfigurationSource corsConfigSource = new UrlBasedCorsConfigurationSource(); + CorsConfiguration corsConfig = new CorsConfiguration(); + corsConfig.setAllowedHeaders(Arrays.asList(corsProperties.getAllowedHeaders().split(","))); + corsConfig.setAllowedMethods(Arrays.asList(corsProperties.getAllowedMethods().split(","))); + corsConfig.setAllowedOrigins(Arrays.asList(corsProperties.getAllowedOrigins().split(","))); + corsConfig.setAllowCredentials(true); + corsConfig.setMaxAge(corsConfig.getMaxAge()); + corsConfigSource.registerCorsConfiguration("/**", corsConfig); + return corsConfigSource; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/AppProperties.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/AppProperties.java new file mode 100644 index 000000000..7d3a828ae --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/AppProperties.java @@ -0,0 +1,45 @@ +package gg.pingpong.api.global.security.config.properties; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Configuration +@ConfigurationProperties(prefix = "app") +public class AppProperties { + private final Auth auth = new Auth(); + private final OAuth2 oauth2 = new OAuth2(); + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Auth { + private String tokenSecret; + private String refreshTokenSecret; + private long tokenExpiry; + private long refreshTokenExpiry; + } + + public static final class OAuth2 { + private List authorizedRedirectUris = new ArrayList<>(); + + public List getAuthorizedRedirectUris() { + return authorizedRedirectUris; + } + + public OAuth2 authorizedRedirectUris(List authorizedRedirectUris) { + this.authorizedRedirectUris = authorizedRedirectUris; + return this; + } + } +} + diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/CorsProperties.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/CorsProperties.java new file mode 100644 index 000000000..34adeda16 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/config/properties/CorsProperties.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.global.security.config.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Configuration +@ConfigurationProperties(prefix = "cors") +public class CorsProperties { + private String allowedOrigins; + private String allowedMethods; + private String allowedHeaders; + private Long maxAge; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/cookie/CookieUtil.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/cookie/CookieUtil.java new file mode 100644 index 000000000..a7e4663ff --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/cookie/CookieUtil.java @@ -0,0 +1,89 @@ +package gg.pingpong.api.global.security.cookie; + +import java.util.Base64; +import java.util.Optional; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseCookie; +import org.springframework.stereotype.Component; +import org.springframework.util.SerializationUtils; + +import gg.pingpong.api.global.utils.ApplicationYmlRead; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class CookieUtil { + + private final ApplicationYmlRead applicationYmlRead; + + public Optional getCookie(HttpServletRequest request, String name) { + Cookie[] cookies = request.getCookies(); + + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + return Optional.of(cookie); + } + } + } + return Optional.empty(); + } + + public void addCookie(HttpServletResponse response, String name, String value, int maxAge) { + String domain = applicationYmlRead.getDomain(); + ResponseCookie cookie = ResponseCookie.from(name, value) + .maxAge(maxAge) + .domain(domain) + .httpOnly(false) + .path("/") + .secure(true) + .build(); + response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); + } + + public void deleteCookie(HttpServletResponse response, String name) { + String domain = applicationYmlRead.getDomain(); + ResponseCookie cookie = ResponseCookie.from(name, null) + .maxAge(0) + .domain(domain) + .httpOnly(false) + .path("/") + .secure(true) + .build(); + response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); + } + + public void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) { + Cookie[] cookies = request.getCookies(); + + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + if (name.equals(cookie.getName())) { + cookie.setValue(""); + cookie.setPath("/"); + cookie.setMaxAge(0); + response.addCookie(cookie); + } + } + } + } + + public String serialize(Object obj) { + return Base64.getUrlEncoder() + .encodeToString(SerializationUtils.serialize(obj)); + } + + public T deserialize(Cookie cookie, Class cls) { + return cls.cast( + SerializationUtils.deserialize( + Base64.getUrlDecoder().decode(cookie.getValue()) + ) + ); + } +} + diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/handler/OAuthAuthenticationSuccessHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/handler/OAuthAuthenticationSuccessHandler.java new file mode 100644 index 000000000..85fd9754a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/handler/OAuthAuthenticationSuccessHandler.java @@ -0,0 +1,131 @@ +package gg.pingpong.api.global.security.handler; + +import java.io.IOException; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.util.UriComponentsBuilder; + +import gg.data.user.User; +import gg.data.user.type.RoleType; +import gg.pingpong.api.global.security.UserPrincipal; +import gg.pingpong.api.global.security.config.properties.AppProperties; +import gg.pingpong.api.global.security.cookie.CookieUtil; +import gg.pingpong.api.global.security.jwt.repository.JwtRedisRepository; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.security.jwt.utils.TokenHeaders; +import gg.pingpong.api.global.utils.ApplicationYmlRead; +import gg.repo.user.UserRepository; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class OAuthAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { + private final JwtRedisRepository jwtRedisRepository; + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + private final AppProperties appProperties; + private final ApplicationYmlRead applicationYmlRead; + private final CookieUtil cookieUtil; + + @Transactional + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException { + String targetUrl; + try { + targetUrl = determineTargetUrl(request, response, authentication); + } catch (Exception e) { + targetUrl = applicationYmlRead.getFrontUrl(); + } + + if (response.isCommitted()) { + logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); + return; + } + clearAuthenticationAttributes(request, response); + getRedirectStrategy().sendRedirect(request, response, targetUrl); + } + + @Override + protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) { + + UserPrincipal principal = (UserPrincipal)authentication.getPrincipal(); + Cookie[] cookies = request.getCookies(); + for (Cookie cookie : cookies) { + if (cookie.getName().equals(TokenHeaders.REFRESH_TOKEN)) { + Long existUserId = jwtRedisRepository.getUserIdFromRefToken(cookie.getValue()); + if (existUserId != null && !existUserId.equals(principal.getId())) { + jwtRedisRepository.deleteRefToken(cookie.getValue()); + return deleteKakaoUser(existUserId, response, authentication); + } + } + } + + // ์ฟ ํ‚ค ์‹œ๊ฐ„ ์„ค์ • + long refreshTokenExpiry = appProperties.getAuth().getRefreshTokenExpiry(); + + // token ์„ค์ • + String accessToken = tokenProvider.createToken(principal.getId()); + String refreshToken = tokenProvider.refreshToken(principal.getId()); + + cookieUtil.addCookie(response, TokenHeaders.REFRESH_TOKEN, refreshToken, + (int)(refreshTokenExpiry / 1000)); + + jwtRedisRepository.addRefToken(refreshToken, refreshTokenExpiry, principal.getId()); + return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl()) + .queryParam("token", accessToken) + .build().toUriString(); + } + + private String deleteKakaoUser(Long existUserId, HttpServletResponse response, Authentication authentication) { + UserPrincipal principal = (UserPrincipal)authentication.getPrincipal(); + User existUser = userRepository.findById(existUserId).orElseThrow(UserNotFoundException::new); + User newUser = userRepository.findById(principal.getId()).orElseThrow(UserNotFoundException::new); + //kakao ๊ณ„์ • ์‚ฌ์šฉ์ž๊ฐ€ 42 ์ธ์ฆ + if (existUser.getRoleType().equals(RoleType.GUEST)) { + return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl() + "/users/detail") + .queryParam("intraId", newUser.getIntraId()) + .queryParam("token", saveAndGetUserAccessToken(response, newUser, existUser)) + .build().toUriString(); + } + //๊ธฐ์กด user ์‚ฌ์šฉ์ž๊ฐ€ ์นด์นด์˜ค ์ธ์ฆ + if (newUser.getRoleType().equals(RoleType.GUEST)) { + return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl() + "/users/detail") + .queryParam("intraId", existUser.getIntraId()) + .queryParam("token", saveAndGetUserAccessToken(response, existUser, newUser)) + .build().toUriString(); + } + throw new UserNotFoundException(); + } + + private String saveAndGetUserAccessToken(HttpServletResponse response, + User remainedUser, User deletedUser) { + remainedUser.updateKakaoId(deletedUser.getKakaoId()); + // ์ฟ ํ‚ค ์‹œ๊ฐ„ ์„ค์ • + long refreshTokenExpiry = appProperties.getAuth().getRefreshTokenExpiry(); + userRepository.delete(deletedUser); + + // token ์„ค์ • + String accessToken = tokenProvider.createToken(remainedUser.getId()); + String refreshToken = tokenProvider.refreshToken(remainedUser.getId()); + jwtRedisRepository.addRefToken(refreshToken, refreshTokenExpiry, remainedUser.getId()); + + cookieUtil.addCookie(response, TokenHeaders.REFRESH_TOKEN, refreshToken, + (int)(refreshTokenExpiry / 1000)); + return accessToken; + } + + private void clearAuthenticationAttributes(HttpServletRequest request, HttpServletResponse response) { + super.clearAuthenticationAttributes(request); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfo.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfo.java new file mode 100644 index 000000000..b1719d5f8 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfo.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.global.security.info; + +import java.util.Map; + +import gg.data.user.type.RoleType; + +public abstract class OAuthUserInfo { + protected Map attributes; + + public OAuthUserInfo(Map attributes) { + this.attributes = attributes; + } + + public Map getAttributes() { + return attributes; + } + + public abstract String getIntraId(); + + public abstract String getEmail(); + + public abstract String getImageUrl(); + + public abstract RoleType getRoleType(); + + public abstract Long getKakaoId(); +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfoFactory.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfoFactory.java new file mode 100644 index 000000000..02ecec4a2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/OAuthUserInfoFactory.java @@ -0,0 +1,20 @@ +package gg.pingpong.api.global.security.info; + +import java.util.Map; + +import gg.pingpong.api.global.security.info.impl.FortyTwoOAuthUserInfo; +import gg.pingpong.api.global.security.info.impl.KakaoOAuthUserInfo; + +public class OAuthUserInfoFactory { + public static OAuthUserInfo getOAuth2UserInfo(ProviderType providerType, Map attributes) { + switch (providerType) { + case FORTYTWO: + return new FortyTwoOAuthUserInfo(attributes); + case KAKAO: + return new KakaoOAuthUserInfo(attributes); + //case SLACK: return new FacebookOAuth2UserInfo(attributes); + default: + throw new IllegalArgumentException("Invalid Provider Type."); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/ProviderType.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/ProviderType.java new file mode 100644 index 000000000..8571cf250 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/ProviderType.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.global.security.info; + +import lombok.Getter; + +@Getter +public enum ProviderType { + FORTYTWO("42"), KAKAO("KAKAO"); + + private String key; + + ProviderType(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public static ProviderType keyOf(String key) { + for (ProviderType value : ProviderType.values()) { + if (value.key.equalsIgnoreCase(key)) { + return value; + } + } + return null; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/FortyTwoOAuthUserInfo.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/FortyTwoOAuthUserInfo.java new file mode 100644 index 000000000..1e59b3de1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/FortyTwoOAuthUserInfo.java @@ -0,0 +1,48 @@ +package gg.pingpong.api.global.security.info.impl; + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; + +import gg.data.user.type.RoleType; +import gg.pingpong.api.global.security.info.OAuthUserInfo; + +public class FortyTwoOAuthUserInfo extends OAuthUserInfo { + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + + public FortyTwoOAuthUserInfo(Map attributes) { + super(attributes); + } + + @Override + public String getIntraId() { + return attributes.get("login").toString(); + } + + public String getEmail() { + return attributes.get("email").toString(); + } + + public String getImageUrl() { + Map image = (Map)attributes.get("image"); + if (image == null) { + return defaultImageUrl; + } + if (image.get("link") == null) { + return defaultImageUrl; + } + return image.get("link").toString(); + } + + @Override + public RoleType getRoleType() { + return RoleType.USER; + } + + @Override + public Long getKakaoId() { + return null; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/KakaoOAuthUserInfo.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/KakaoOAuthUserInfo.java new file mode 100644 index 000000000..b28bea0cf --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/info/impl/KakaoOAuthUserInfo.java @@ -0,0 +1,48 @@ +package gg.pingpong.api.global.security.info.impl; + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; + +import gg.data.user.type.RoleType; +import gg.pingpong.api.global.security.info.OAuthUserInfo; + +public class KakaoOAuthUserInfo extends OAuthUserInfo { + @Value("${info.image.defaultUrl}") + + private String defaultImageUrl; + + public KakaoOAuthUserInfo(Map attributes) { + super(attributes); + } + + @Override + public String getIntraId() { + return "GUEST" + attributes.get("id").toString(); + } + + @Override + public String getEmail() { + Map kakaoAccount = (Map)attributes.get("kakao_account"); + if (kakaoAccount.get("email") == null) { + return null; + } + return kakaoAccount.get("email").toString(); + } + + @Override + public String getImageUrl() { + Map properties = (Map)attributes.get("properties"); + return properties.get("profile_image").toString(); + } + + @Override + public RoleType getRoleType() { + return RoleType.GUEST; + } + + @Override + public Long getKakaoId() { + return (Long)attributes.get("id"); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/repository/JwtRedisRepository.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/repository/JwtRedisRepository.java new file mode 100644 index 000000000..f98b6141b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/repository/JwtRedisRepository.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.global.security.jwt.repository; + +import java.util.concurrent.TimeUnit; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class JwtRedisRepository { + private final RedisTemplate redisTemplate; + + public void addRefToken(String refreshToken, long timeOut, Long userId) { + redisTemplate.opsForValue().set(refreshToken, userId.toString(), timeOut, TimeUnit.MILLISECONDS); + } + + public Long getUserIdFromRefToken(String refToken) { + String userId = redisTemplate.opsForValue().get(refToken); + if (userId == null) { + return null; + } + return Long.valueOf(userId); + } + + public void deleteRefToken(String refToken) { + redisTemplate.delete(refToken); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/AuthTokenProvider.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/AuthTokenProvider.java new file mode 100644 index 000000000..afbfe1192 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/AuthTokenProvider.java @@ -0,0 +1,85 @@ +package gg.pingpong.api.global.security.jwt.utils; + +import java.security.Key; +import java.util.Date; + +import org.springframework.stereotype.Component; + +import gg.pingpong.api.global.security.config.properties.AppProperties; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.Keys; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class AuthTokenProvider { + + private AppProperties appProperties; + private final Key key; + private final Key refreshKey; + + public AuthTokenProvider(AppProperties appProperties) { + this.appProperties = appProperties; + key = Keys.hmacShaKeyFor(appProperties.getAuth().getTokenSecret().getBytes()); + refreshKey = Keys.hmacShaKeyFor(appProperties.getAuth().getRefreshTokenSecret().getBytes()); + log.info(key.getAlgorithm()); + } + + public String refreshToken(Long userId) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + + appProperties.getAuth().getRefreshTokenExpiry()); + return Jwts.builder() + .setSubject(userId.toString()) + .setIssuedAt(new Date()) + .setExpiration(expiryDate) + .signWith(refreshKey) + .compact(); + } + + public String createToken(Long userId) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + + appProperties.getAuth().getTokenExpiry()); + return Jwts.builder() + .setSubject(Long.toString(userId)) + .setIssuedAt(new Date()) + .setExpiration(expiryDate) + .signWith(key) + .compact(); + } + + private Claims getClaims(String token, Key key) { + try { + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + } catch (SecurityException e) { + log.info("Invalid JWT signature."); + } catch (MalformedJwtException e) { + log.info("Invalid JWT token."); + } catch (ExpiredJwtException e) { + log.info("Expired JWT token."); + } catch (UnsupportedJwtException e) { + log.info("Unsupported JWT token."); + } catch (IllegalArgumentException e) { + log.info("JWT token compact of handler are invalid."); + } + return null; + } + + public Long getUserIdFromAccessToken(String accessToken) { + Claims claims = getClaims(accessToken, key); + if (claims == null) { + return null; + } + return Long.valueOf(claims.getSubject()); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenAuthenticationFilter.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenAuthenticationFilter.java new file mode 100644 index 000000000..f9beda9b5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenAuthenticationFilter.java @@ -0,0 +1,64 @@ +package gg.pingpong.api.global.security.jwt.utils; + +import static org.apache.commons.lang3.StringUtils.*; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.HttpHeaders; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import gg.pingpong.api.global.security.service.CustomUserDetailsService; +import gg.pingpong.api.global.utils.HeaderUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequiredArgsConstructor +@Component +public class TokenAuthenticationFilter extends OncePerRequestFilter { + private final AuthTokenProvider tokenProvider; + private final CustomUserDetailsService customUserDetailsService; + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + try { + String tokenHeader = request.getHeader(HttpHeaders.AUTHORIZATION); + if (isEmpty(tokenHeader) || !tokenHeader.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + OAuth2AuthenticationToken authentication = validate(request); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } catch (Exception e) { + log.error("Security Context์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ์„ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", e); + } + filterChain.doFilter(request, response); + } + + private OAuth2AuthenticationToken validate(HttpServletRequest request) { + String accessToken = HeaderUtil.getAccessToken(request); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + //access token ๊ฒ€์ฆ + if (userId != null) { + UserDetails userDetails = customUserDetailsService.loadUserById(userId); + return new OAuth2AuthenticationToken((OAuth2User)userDetails, userDetails.getAuthorities(), "42"); + } + throw new RuntimeException("token not validated"); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenHeaders.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenHeaders.java new file mode 100644 index 000000000..139c30e09 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/jwt/utils/TokenHeaders.java @@ -0,0 +1,6 @@ +package gg.pingpong.api.global.security.jwt.utils; + +public class TokenHeaders { + public static final String REFRESH_TOKEN = "refresh_token"; + public static final String ACCESS_TOKEN = "access_token"; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java new file mode 100644 index 000000000..574f0474c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java @@ -0,0 +1,57 @@ +package gg.pingpong.api.global.security.repository; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.stereotype.Repository; + +import com.nimbusds.oauth2.sdk.util.StringUtils; + +import gg.pingpong.api.global.security.cookie.CookieUtil; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class OAuthAuthorizationRequestBasedOnCookieRepository + implements AuthorizationRequestRepository { + + public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; + public static final String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; + private static final int cookieExpireSeconds = 180; + private final CookieUtil cookieUtil; + + @Override + public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { + return cookieUtil.getCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + .map(cookie -> cookieUtil.deserialize(cookie, OAuth2AuthorizationRequest.class)) + .orElse(null); + } + + @Override + public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, + HttpServletResponse response) { + if (authorizationRequest == null) { + cookieUtil.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + cookieUtil.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); + return; + } + + cookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, + cookieUtil.serialize(authorizationRequest), + cookieExpireSeconds); + String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); + if (StringUtils.isNotBlank(redirectUriAfterLogin)) { + cookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, + cookieExpireSeconds); + } + } + + @Override + public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) { + return this.loadAuthorizationRequest(request); + } + +} + diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomOAuth2UserService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomOAuth2UserService.java new file mode 100644 index 000000000..3976762b5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomOAuth2UserService.java @@ -0,0 +1,113 @@ +package gg.pingpong.api.global.security.service; + +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.security.UserPrincipal; +import gg.pingpong.api.global.security.info.OAuthUserInfo; +import gg.pingpong.api.global.security.info.OAuthUserInfoFactory; +import gg.pingpong.api.global.security.info.ProviderType; +import gg.pingpong.api.global.utils.aws.AsyncNewUserImageUploader; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class CustomOAuth2UserService extends DefaultOAuth2UserService { + private final UserRepository userRepository; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final RankRepository rankRepository; + private final SeasonRepository seasonRepository; + private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + OAuth2User user = super.loadUser(userRequest); + + try { + return this.process(userRequest, user); + } catch (AuthenticationException ex) { + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause()); + } + } + + private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) { + ProviderType providerType = ProviderType.keyOf( + userRequest.getClientRegistration().getRegistrationId().toUpperCase()); + User savedUser; + OAuthUserInfo userInfo = OAuthUserInfoFactory.getOAuth2UserInfo(providerType, user.getAttributes()); + if (providerType.equals(ProviderType.FORTYTWO)) { + savedUser = userRepository.findByIntraId(userInfo.getIntraId()) + .orElse(null); + } else { + savedUser = userRepository.findByKakaoId(userInfo.getKakaoId()) + .orElse(null); + } + if (savedUser == null) { + savedUser = createUser(userInfo); + if (providerType.equals(ProviderType.FORTYTWO)) { + createUserRank(savedUser); + } + if (userInfo.getImageUrl().startsWith("https://cdn.intra.42.fr/")) { + asyncNewUserImageUploader.upload(userInfo.getIntraId(), userInfo.getImageUrl()); + } + } + return UserPrincipal.create(savedUser, user.getAttributes()); + } + + private void createUserRank(User savedUser) { + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + seasonRepository.findCurrentAndNewSeason(LocalDateTime.now()).forEach( + season -> { + Rank userRank = Rank.from(savedUser, season, season.getStartPpp(), tier); + rankRepository.save(userRank); + RankRedis rankRedis = RankRedis.from(savedUser.getId(), savedUser.getIntraId(), + savedUser.getTextColor(), season.getStartPpp(), tier.getImageUri()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(hashKey, savedUser.getId(), rankRedis); + } + ); + } + + private User createUser(OAuthUserInfo userInfo) { + User user = User.builder() + .intraId(userInfo.getIntraId()) + .roleType(userInfo.getRoleType()) + .kakaoId(userInfo.getKakaoId()) + .snsNotiOpt(SnsType.EMAIL) + .racketType(RacketType.NONE) + .totalExp(0) + .eMail(userInfo.getEmail()) + .build(); + return userRepository.saveAndFlush(user); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomUserDetailsService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomUserDetailsService.java new file mode 100644 index 000000000..ea0fd803d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/security/service/CustomUserDetailsService.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.global.security.service; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.user.User; +import gg.pingpong.api.global.security.UserPrincipal; +import gg.pingpong.api.user.user.service.UserFindService; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class CustomUserDetailsService implements UserDetailsService { + + private final UserFindService userFindService; + + @Override + public UserDetails loadUserByUsername(String username) throws UserNotFoundException { + User user = userFindService.findByIntraId(username); + return UserPrincipal.create(user); + } + + public UserDetails loadUserById(Long id) { + User user = userFindService.findUserById(id); + return UserPrincipal.create(user); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ApplicationYmlRead.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ApplicationYmlRead.java new file mode 100644 index 000000000..b675bbc22 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ApplicationYmlRead.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.global.utils; + +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import lombok.Setter; + +@Configuration +@Setter +@ConfigurationProperties(prefix = "info") +public class ApplicationYmlRead { + private Map web; + + public String getFrontUrl() { + return web.get("frontUrl"); + } + + public String getDomain() { + return web.get("domain"); + } + + public String getFrontLoginUrl() { + return web.get("frontUrl") + "/login"; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/AsyncMailSender.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/AsyncMailSender.java new file mode 100644 index 000000000..0eba18d45 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/AsyncMailSender.java @@ -0,0 +1,26 @@ +package gg.pingpong.api.global.utils; + +import javax.mail.internet.MimeMessage; + +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@AllArgsConstructor +@Slf4j +public class AsyncMailSender { + private final JavaMailSender javaMailSender; + + @Async("asyncExecutor") + public void send(MimeMessage message) { + try { + javaMailSender.send(message); + } catch (Exception ex) { + log.error(ex.getMessage()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/EloRating.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/EloRating.java new file mode 100644 index 000000000..95745738f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/EloRating.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.global.utils; + +public class EloRating { + public static Integer pppChange(Integer myPPP, Integer opponentPPP, Boolean isWin, Boolean isOneSide) { + Double we = 1.0 / (Math.pow(10.0, (opponentPPP - myPPP) / 400.0) + 1.0); + Double change = 40 * ((isWin ? 1 : 0) - we); + if (isOneSide) { + change = change + change * 0.21; + } + if (change < 0) { + change = change * 0.9; + } + return change.intValue(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ExpLevelCalculator.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ExpLevelCalculator.java new file mode 100644 index 000000000..a0b64e6d5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ExpLevelCalculator.java @@ -0,0 +1,46 @@ +package gg.pingpong.api.global.utils; + +public class ExpLevelCalculator { + private static Integer expPerGame = 100; + private static Integer expBonus = 10; + private static int[] accumulatedExpForEachLevel = { + 0, 100, 200, 300, 500, 700, 900, 1200, 1500, 1800, + 2200, 2600, 3000, 3400, 3800, 4300, 4800, 5300, 5800, 6300, + 6900, 7500, 8100, 8700, 9300, 10000, 10700, 11400, 12100, 12800, + 13600, 14400, 15200, 16000, 16800, 17700, 18600, 19500, 20400, 21300, + 22300, 25100, Integer.MAX_VALUE + }; + + private static int[] expForEachLevel = { + 0, 100, 100, 100, 200, 200, 200, 300, 300, 300, + 400, 400, 400, 400, 400, 500, 500, 500, 500, 500, + 600, 600, 600, 600, 600, 700, 700, 700, 700, 700, + 800, 800, 800, 800, 800, 900, 900, 900, 900, 900, + 1000, 2800, Integer.MAX_VALUE + }; + + public static int getLevel(int totalExp) { + int idx = 0; + while (totalExp >= accumulatedExpForEachLevel[idx]) { + ++idx; + } + return idx; + } + + public static int getCurrentLevelMyExp(int totalExp) { + int level = getLevel(totalExp); + return totalExp - accumulatedExpForEachLevel[level - 1]; + } + + public static int getLevelMaxExp(int level) { + return expForEachLevel[level]; + } + + public static int getExpPerGame() { + return expPerGame; + } + + public static int getExpBonus() { + return expBonus; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/FileDownloader.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/FileDownloader.java new file mode 100644 index 000000000..b7a080041 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/FileDownloader.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.global.utils; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +@Component +public class FileDownloader { + private RestTemplate restTemplate; + + public FileDownloader() { + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); + factory.setConnectTimeout(5000); // ํƒ€์ž„์•„์›ƒ ์„ค์ • 5์ดˆ + factory.setReadTimeout(5000); // ํƒ€์ž„์•„์›ƒ ์„ค์ • 5์ดˆ + + //Apache HttpComponents : ๊ฐ ํ˜ธ์ŠคํŠธ(IP์™€ Port์˜ ์กฐํ•ฉ)๋‹น ์ปค๋„ฅ์…˜ ํ’€์— ์ƒ์„ฑ๊ฐ€๋Šฅํ•œ ์ปค๋„ฅ์…˜ ์ˆ˜ + HttpClient httpClient = HttpClientBuilder.create() + .setMaxConnTotal(50)//์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜ + .setMaxConnPerRoute(20).build(); + factory.setHttpClient(httpClient); + + // 2. RestTemplate ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + this.restTemplate = new RestTemplate(factory); + } + + public byte[] downloadFromUrl(String imageUrl) { + UriComponents uri = UriComponentsBuilder.fromHttpUrl(imageUrl).build(false); + return restTemplate.getForObject(uri.toString(), byte[].class); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/HeaderUtil.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/HeaderUtil.java new file mode 100644 index 000000000..7bc680609 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/HeaderUtil.java @@ -0,0 +1,22 @@ +package gg.pingpong.api.global.utils; + +import javax.servlet.http.HttpServletRequest; + +public class HeaderUtil { + + private static final String HEADER_AUTHORIZATION = "Authorization"; + private static final String TOKEN_PREFIX = "Bearer "; + + public static String getAccessToken(HttpServletRequest request) { + String headerValue = request.getHeader(HEADER_AUTHORIZATION); + + if (headerValue == null) { + return null; + } + + if (headerValue.startsWith(TOKEN_PREFIX)) { + return headerValue.substring(TOKEN_PREFIX.length()); + } + return null; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ImageResizingUtil.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ImageResizingUtil.java new file mode 100644 index 000000000..f6e586987 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ImageResizingUtil.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.global.utils; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +public class ImageResizingUtil { + public static byte[] resizeImageBytes(byte[] downloadedImageBytes, double ratio) throws IOException { + InputStream inputStream = new ByteArrayInputStream(downloadedImageBytes); + BufferedImage image = resize(ImageIO.read(inputStream), ratio); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(image, "jpeg", baos); + return baos.toByteArray(); + } + + private static BufferedImage resize(BufferedImage img, double ratio) { + int newWidth = (int)(img.getWidth() * ratio); + int newHeight = (int)(img.getHeight() * ratio); + Image imageToResize = img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH); + BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB); + resizedImage.getGraphics().drawImage(imageToResize, 0, 0, newWidth, newHeight, null); + return resizedImage; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ItemImageHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ItemImageHandler.java new file mode 100644 index 000000000..5b87aacc4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/ItemImageHandler.java @@ -0,0 +1,54 @@ +package gg.pingpong.api.global.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; + +import gg.data.store.Item; + +@Component +public class ItemImageHandler { + private final AmazonS3 amazonS3; + + public ItemImageHandler(AmazonS3 amazonS3) { + this.amazonS3 = amazonS3; + } + + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${cloud.aws.s3.dir}") + private String dir; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + + public String updateAndGetS3ImageUri(MultipartFile multipartFile, Item item) throws IOException { + String itemFileName = item.getName() + "-" + UUID.randomUUID() + ".jpeg"; + if (itemFileName.equals("small_default.jpeg")) { + return defaultImageUrl; + } else { + String s3ImageUrl = uploadToS3(multipartFile, itemFileName); + return s3ImageUrl; + } + } + + public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException { + String s3FileName = dir + fileName; + InputStream inputStream = multipartFile.getInputStream(); + ObjectMetadata objMeta = new ObjectMetadata(); + objMeta.setContentLength(multipartFile.getSize()); + amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl( + CannedAccessControlList.PublicRead)); + return amazonS3.getUrl(bucketName, s3FileName).toString(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/JpegMultipartFile.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/JpegMultipartFile.java new file mode 100644 index 000000000..3426c5906 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/JpegMultipartFile.java @@ -0,0 +1,66 @@ +package gg.pingpong.api.global.utils; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.web.multipart.MultipartFile; + +public class JpegMultipartFile implements MultipartFile { + + private final byte[] bytes; + String name; + String originalFilename; + String contentType; + boolean isEmpty; + long size; + + public JpegMultipartFile(byte[] bytes, String name) { + this.bytes = bytes; + this.name = name; + this.originalFilename = name + ".jpeg"; + this.contentType = "image/jpeg"; + this.size = bytes.length; + this.isEmpty = false; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getOriginalFilename() { + return originalFilename; + } + + @Override + public String getContentType() { + return contentType; + } + + @Override + public boolean isEmpty() { + return isEmpty; + } + + @Override + public long getSize() { + return size; + } + + @Override + public byte[] getBytes() throws IOException { + return bytes; + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(bytes); + } + + @Override + public void transferTo(File dest) throws IllegalStateException { + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/UserImageHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/UserImageHandler.java new file mode 100644 index 000000000..21d46a36e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/UserImageHandler.java @@ -0,0 +1,79 @@ +package gg.pingpong.api.global.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; + +import gg.data.user.User; +import gg.repo.user.UserImageRepository; + +@Component +public class UserImageHandler { + private final AmazonS3 amazonS3; + private final FileDownloader fileDownloader; + + public UserImageHandler(AmazonS3 amazonS3, FileDownloader fileDownloader, + UserImageRepository userImageRepository) { + this.amazonS3 = amazonS3; + this.fileDownloader = fileDownloader; + this.userImageRepository = userImageRepository; + } + + @Value("${cloud.aws.s3.bucket}") + private String bucketName; + + @Value("${cloud.aws.s3.dir}") + private String dir; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + private final UserImageRepository userImageRepository; + + public String uploadAndGetS3ImageUri(String intraId, String imageUrl) { + if (!isStringValid(intraId) || !isStringValid(imageUrl)) { + return defaultImageUrl; + } + byte[] downloadedImageBytes = fileDownloader.downloadFromUrl(imageUrl); + try { + byte[] resizedImageBytes = ImageResizingUtil.resizeImageBytes(downloadedImageBytes, 0.5); + MultipartFile multipartFile = new JpegMultipartFile(resizedImageBytes, intraId); + return uploadToS3(multipartFile, multipartFile.getOriginalFilename()); + } catch (IOException e) { + return defaultImageUrl; + } + } + + public String updateAndGetS3ImageUri(MultipartFile multipartFile, User user) throws IOException { + String updateFileName = user.getIntraId() + "-" + UUID.randomUUID().toString() + ".jpeg"; + if (updateFileName.equals("small_default.jpeg")) { + return defaultImageUrl; + } else { + String s3ImageUrl = uploadToS3(multipartFile, updateFileName); + ; + return s3ImageUrl; + } + } + + private Boolean isStringValid(String intraId) { + return intraId != null && intraId.length() != 0; + } + + public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException { + String s3FileName = dir + fileName; + InputStream inputStream = multipartFile.getInputStream(); + ObjectMetadata objMeta = new ObjectMetadata(); + objMeta.setContentLength(multipartFile.getSize()); + amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl( + CannedAccessControlList.PublicRead)); + return amazonS3.getUrl(bucketName, s3FileName).toString(); + } +} diff --git a/src/main/java/com/gg/server/global/utils/argumentresolver/Login.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/Login.java similarity index 82% rename from src/main/java/com/gg/server/global/utils/argumentresolver/Login.java rename to gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/Login.java index a12a91b00..a2721766f 100644 --- a/src/main/java/com/gg/server/global/utils/argumentresolver/Login.java +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/Login.java @@ -1,4 +1,4 @@ -package com.gg.server.global.utils.argumentresolver; +package gg.pingpong.api.global.utils.argumentresolver; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/LoginMemberArgumentResolver.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/LoginMemberArgumentResolver.java new file mode 100644 index 000000000..69a63945f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/argumentresolver/LoginMemberArgumentResolver.java @@ -0,0 +1,40 @@ +package gg.pingpong.api.global.utils.argumentresolver; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.utils.HeaderUtil; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.user.UserRepository; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class); + boolean hasUserType = UserDto.class.isAssignableFrom(parameter.getParameterType()); + return hasLoginAnnotation && hasUserType; + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); + String accessToken = HeaderUtil.getAccessToken(request); + Long loginUserId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(loginUserId).orElseThrow(); + UserDto userDto = UserDto.from(user); + return userDto; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewItemImageUploader.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewItemImageUploader.java new file mode 100644 index 000000000..fafc55d89 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewItemImageUploader.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.global.utils.aws; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import gg.data.store.Item; +import gg.pingpong.api.global.utils.ItemImageHandler; + +@Component +public class AsyncNewItemImageUploader { + + private final ItemImageHandler itemImageHandler; + + @Value("${info.image.itemNotFoundUrl}") + private String defaultImageUrl; + + public AsyncNewItemImageUploader(ItemImageHandler itemImageHandler) { + this.itemImageHandler = itemImageHandler; + } + + @Transactional + public void upload(Item item, + MultipartFile multipartFile) throws IOException { + String s3ImageUrl = itemImageHandler.updateAndGetS3ImageUri(multipartFile, item); + if (s3ImageUrl == null) { + item.imageUpdate(defaultImageUrl); + } else { + item.imageUpdate(s3ImageUrl); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewUserImageUploader.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewUserImageUploader.java new file mode 100644 index 000000000..5f8673d33 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/aws/AsyncNewUserImageUploader.java @@ -0,0 +1,65 @@ +package gg.pingpong.api.global.utils.aws; + +import java.io.IOException; +import java.time.LocalDateTime; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.pingpong.api.global.utils.UserImageHandler; +import gg.repo.user.UserImageRepository; +import gg.repo.user.UserRepository; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class AsyncNewUserImageUploader { + private final UserImageHandler userImageHandler; + private final UserRepository userRepository; + @PersistenceContext + private EntityManager entityManager; + + @Value("${info.image.defaultUrl}") + private String defaultImageUrl; + private final UserImageRepository userImageRepository; + + public AsyncNewUserImageUploader(UserImageHandler userImageHandler, UserRepository userRepository, + UserImageRepository userImageRepository) { + this.userImageHandler = userImageHandler; + this.userRepository = userRepository; + this.userImageRepository = userImageRepository; + } + + @Async("asyncExecutor") + @Transactional + public void upload(String intraId, String imageUrl) { + String s3ImageUrl = userImageHandler.uploadAndGetS3ImageUri(intraId, imageUrl); + if (defaultImageUrl.equals(s3ImageUrl)) { + return; + } + userRepository.findByIntraId(intraId).ifPresent(user -> { + UserImage userImage = new UserImage(user, (s3ImageUrl != null) ? s3ImageUrl : defaultImageUrl, + LocalDateTime.now(), null, true); + userImageRepository.save(userImage); + userRepository.updateUserImage(user.getId(), userImage.getImageUri()); + }); + } + + @Transactional + public void update(String intraId, MultipartFile multipartFile) throws IOException { + User user = userRepository.findByIntraId(intraId).get(); + String s3ImageUrl = userImageHandler.updateAndGetS3ImageUri(multipartFile, user); + s3ImageUrl = s3ImageUrl == null ? defaultImageUrl : s3ImageUrl; + UserImage userImage = new UserImage(user, s3ImageUrl, LocalDateTime.now(), null, true); + userImageRepository.saveAndFlush(userImage); + user.updateImageUri(s3ImageUrl); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/external/ApiUtil.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/external/ApiUtil.java new file mode 100644 index 000000000..ef30fb58d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/external/ApiUtil.java @@ -0,0 +1,52 @@ +package gg.pingpong.api.global.utils.external; + +import java.util.Map; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +@Component +public class ApiUtil { + private final RestTemplate restTemplate; + private final ObjectMapper objectMapper; + + public ApiUtil(ObjectMapper objectMapper, RestTemplateBuilder restTemplateBuilder) { + this.objectMapper = objectMapper; + this.restTemplate = restTemplateBuilder.build(); + } + + public T apiCall(String url, Class responseType, HttpHeaders headers, + MultiValueMap parameters, HttpMethod method) { + HttpEntity> request = new HttpEntity<>(parameters, headers); + ResponseEntity res = restTemplate.exchange(url, method, request, responseType); + if (!res.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("api call error"); + } + return res.getBody(); + } + + public T apiCall(String url, Class responseType, HttpHeaders headers, + Map bodyJson, HttpMethod method) { + String contentBody = null; + try { + contentBody = objectMapper.writeValueAsString(bodyJson); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + HttpEntity request = new HttpEntity<>(contentBody, headers); + ResponseEntity res = restTemplate.exchange(url, method, request, responseType); + if (!res.getStatusCode().is2xxSuccessful()) { + throw new RuntimeException("api call error"); + } + return res.getBody(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounter.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounter.java new file mode 100644 index 000000000..96692962f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounter.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.global.utils.querytracker; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; + +import lombok.Getter; + +@Component +@RequestScope +@Getter +public class ApiQueryCounter { + private int count; + + public void increaseCount() { + this.count++; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounterAop.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounterAop.java new file mode 100644 index 000000000..ecddc15a6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryCounterAop.java @@ -0,0 +1,28 @@ +package gg.pingpong.api.global.utils.querytracker; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.cglib.proxy.Proxy; +import org.springframework.stereotype.Component; + +@Component +@Aspect +public class ApiQueryCounterAop { + + private final ApiQueryCounter apiQueryCounter; + + public ApiQueryCounterAop(final ApiQueryCounter apiQueryCounter) { + this.apiQueryCounter = apiQueryCounter; + } + + @Around("execution(* javax.sql.DataSource.getConnection())") + public Object getConnection(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + Object connection = proceedingJoinPoint.proceed(); + return Proxy.newProxyInstance( + connection.getClass().getClassLoader(), + connection.getClass().getInterfaces(), + new ConnectionProxyHandler(connection, apiQueryCounter) + ); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryInspector.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryInspector.java new file mode 100644 index 000000000..6e6935d55 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ApiQueryInspector.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.global.utils.querytracker; + +import java.util.Objects; + +import org.hibernate.resource.jdbc.spi.StatementInspector; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; + +@Component +public class ApiQueryInspector implements StatementInspector { + + private final ApiQueryCounter apiQueryCounter; + + public ApiQueryInspector(final ApiQueryCounter apiQueryCounter) { + this.apiQueryCounter = apiQueryCounter; + } + + @Override + public String inspect(final String sql) { + if (isInRequestScope()) { + apiQueryCounter.increaseCount(); + } + return sql; + } + + private boolean isInRequestScope() { + return Objects.nonNull(RequestContextHolder.getRequestAttributes()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ConnectionProxyHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ConnectionProxyHandler.java new file mode 100644 index 000000000..2a38f5fd8 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/ConnectionProxyHandler.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.global.utils.querytracker; + +import java.lang.reflect.Method; + +import org.springframework.cglib.proxy.InvocationHandler; +import org.springframework.cglib.proxy.Proxy; + +public class ConnectionProxyHandler implements InvocationHandler { + + private final Object connection; + private final ApiQueryCounter apiQueryCounter; + + public ConnectionProxyHandler(final Object connection, final ApiQueryCounter apiQueryCounter) { + this.connection = connection; + this.apiQueryCounter = apiQueryCounter; + } + + @Override + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + Object invokeResult = method.invoke(connection, args); // (1) + if (method.getName().equals("prepareStatement")) { + return Proxy.newProxyInstance( + invokeResult.getClass().getClassLoader(), + invokeResult.getClass().getInterfaces(), + new PreparedStatementProxyHandler(invokeResult, apiQueryCounter) + ); + } + return invokeResult; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/LoggingInterceptor.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/LoggingInterceptor.java new file mode 100644 index 000000000..828bf0beb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/LoggingInterceptor.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.global.utils.querytracker; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class LoggingInterceptor implements HandlerInterceptor { + + private static final String QUERY_COUNT_LOG_FORMAT = "STATUS_CODE: {}, METHOD: {}, URL: {}, QUERY_COUNT: {}"; + + private final ApiQueryCounter apiQueryCounter; + + public LoggingInterceptor(final ApiQueryCounter apiQueryCounter) { + this.apiQueryCounter = apiQueryCounter; + } + + @Override + public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, + final Object handler, final Exception ex) { + final int queryCount = apiQueryCounter.getCount(); + + log.info(QUERY_COUNT_LOG_FORMAT, response.getStatus(), request.getMethod(), request.getRequestURI(), + queryCount); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/PreparedStatementProxyHandler.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/PreparedStatementProxyHandler.java new file mode 100644 index 000000000..9f36a40ed --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/global/utils/querytracker/PreparedStatementProxyHandler.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.global.utils.querytracker; + +import java.lang.reflect.Method; +import java.util.Objects; + +import org.springframework.cglib.proxy.InvocationHandler; +import org.springframework.web.context.request.RequestContextHolder; + +public class PreparedStatementProxyHandler implements InvocationHandler { + + private final Object preparedStatement; + private final ApiQueryCounter apiQueryCounter; + + public PreparedStatementProxyHandler(final Object preparedStatement, final ApiQueryCounter apiQueryCounter) { + this.preparedStatement = preparedStatement; + this.apiQueryCounter = apiQueryCounter; + } + + @Override // (1) + public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + if (isExecuteQuery(method) && isInRequestScope()) { // (2) + apiQueryCounter.increaseCount(); + } + return method.invoke(preparedStatement, args); // (3) + } + + private boolean isExecuteQuery(final Method method) { + String methodName = method.getName(); + return methodName.equals("executeQuery") || methodName.equals("execute") || methodName.equals("executeUpdate"); + } + + private boolean isInRequestScope() { + return Objects.nonNull(RequestContextHolder.getRequestAttributes()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/GameController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/GameController.java new file mode 100644 index 000000000..b8138959c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/GameController.java @@ -0,0 +1,152 @@ +package gg.pingpong.api.user.game.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +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 gg.data.game.type.Mode; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.game.controller.request.GameListReqDto; +import gg.pingpong.api.user.game.controller.request.NormalGameListReqDto; +import gg.pingpong.api.user.game.controller.request.NormalResultReqDto; +import gg.pingpong.api.user.game.controller.request.RankGameListReqDto; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.pingpong.api.user.game.controller.request.TournamentResultReqDto; +import gg.pingpong.api.user.game.controller.response.GameListResDto; +import gg.pingpong.api.user.game.controller.response.GamePChangeResultResDto; +import gg.pingpong.api.user.game.dto.GameTeamInfo; +import gg.pingpong.api.user.game.service.GameFindService; +import gg.pingpong.api.user.game.service.GameService; +import gg.pingpong.api.user.rank.redis.RankRedisService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; +import gg.utils.exception.custom.InvalidParameterException; +import gg.utils.exception.game.ScoreNotMatchedException; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/games") +public class GameController { + private final GameService gameService; + private final GameFindService gameFindService; + private final RankRedisService rankRedisService; + + /** + * ์ „์ฒด ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ API + * @param gameReq - page size [status] [intraId] + *

status๊ฐ€ "LIVE" -> ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„๋„ ํฌํ•จํ•ด์„œ ์กฐํšŒ

+ *

null -> ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„๋งŒ ์กฐํšŒ

+ * @return GameListResDto - games isLast + * @throws InvalidParameterException - status๊ฐ€ "LIVE"๊ฐ€ ์•„๋‹Œ๋ฐ ๋‹ค๋ฅธ ๊ฐ’์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ + */ + @GetMapping + GameListResDto allGameList(@Valid GameListReqDto gameReq) { + if (gameReq.getStatus() != null && !gameReq.getStatus().name().equals("LIVE")) { + throw new InvalidParameterException("status not valid", ErrorCode.VALID_FAILED); + } + Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), + Sort.by(Sort.Direction.DESC, "startTime")); + if (gameReq.getIntraId() != null) { + return gameFindService.allGameListUser(pageable, gameReq.getIntraId(), + gameReq.getStatus() != null ? gameReq.getStatus().name() : "NULL"); + } + return gameFindService.allGameList(pageable, gameReq.getStatus() != null ? gameReq.getStatus().name() : "NULL"); + } + + @GetMapping("/normal") + GameListResDto normalGameList(@ModelAttribute @Valid NormalGameListReqDto gameReq) { + Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), + Sort.by(Sort.Direction.DESC, "startTime")); + if (gameReq.getIntraId() == null) { + return gameFindService.getNormalGameList(pageable); + } + return gameFindService.normalGameListByIntra(pageable, gameReq.getIntraId()); + } + + @GetMapping("/rank") + GameListResDto rankGameList(@ModelAttribute @Valid RankGameListReqDto gameReq) { + Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), + Sort.by(Sort.Direction.DESC, "startTime")); + if (gameReq.getIntraId() == null) { + return gameFindService.rankGameList(pageable, gameReq.getSeasonId()); + } + return gameFindService.rankGameListByIntra(pageable, gameReq.getSeasonId(), gameReq.getIntraId()); + } + + @GetMapping("/{gameId}") + GameTeamInfo getGameInfo(@PathVariable Long gameId, @Parameter(hidden = true) @Login UserDto userDto) { + return gameService.getUserGameInfo(gameId, userDto.getId()); + } + + @PostMapping("/rank") + synchronized ResponseEntity createRankResult(@Valid @RequestBody RankResultReqDto reqDto, + @Parameter(hidden = true) @Login UserDto user) { + if (reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() > 3 + || reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() < 2 + || reqDto.getMyTeamScore() == reqDto.getEnemyTeamScore()) { + throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); + } + if (!gameService.createRankResult(reqDto, user.getId())) { + throw new ScoreNotMatchedException(); + } + rankRedisService.updateAllTier(reqDto.getGameId()); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PostMapping("/normal") + ResponseEntity createNormalResult(@Valid @RequestBody NormalResultReqDto reqDto, + @Parameter(hidden = true) @Login UserDto user) { + if (gameService.normalExpResult(reqDto, user.getId())) { + return new ResponseEntity<>(HttpStatus.CREATED); + } + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋“ฑ๋ก + * @param reqDto ์š”์ฒญ Dto + * @param user ์‚ฌ์šฉ์ž + * @exception InvalidParameterException ์œ ํšจํ•˜์ง€ ์•Š์€ ์ ์ˆ˜ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ + * @return 201 created + */ + @PostMapping("/tournament") + synchronized ResponseEntity createTournamentGameResult(@Valid @RequestBody TournamentResultReqDto reqDto, + @Parameter(hidden = true) @Login UserDto user) { + if (reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() > 3 + || reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() < 2 + || reqDto.getMyTeamScore() == reqDto.getEnemyTeamScore()) { + throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); + } + gameService.createTournamentGameResult(reqDto, user.getId()); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + /** + * RANK, NORMAL, TOURNAMENT ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜. + */ + @GetMapping("/{gameId}/pchange/result") + ResponseEntity getGamePChangeResult(@PathVariable Long gameId, + @Parameter(hidden = true) @Login UserDto user, @RequestParam Mode mode) { + if (mode == Mode.RANK) { + return ResponseEntity.ok(gameService.pppChangeResult(gameId, user.getId())); + } else if (mode == Mode.NORMAL || mode == Mode.TOURNAMENT) { + return ResponseEntity.ok(gameService.expChangeResult(gameId, user.getId())); + } + throw new BusinessException(ErrorCode.BAD_ARGU); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/GameListReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/GameListReqDto.java new file mode 100644 index 000000000..0ec4e79aa --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/GameListReqDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.user.game.controller.request; + +import gg.data.game.type.StatusType; +import lombok.Getter; + +@Getter +public class GameListReqDto extends NormalGameListReqDto { + private StatusType status; + + public GameListReqDto(Integer pageNum, Integer pageSize, String nickname, StatusType status) { + super(pageNum, pageSize, nickname); + this.status = status; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalGameListReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalGameListReqDto.java new file mode 100644 index 000000000..98c4380ea --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalGameListReqDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.user.game.controller.request; + +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class NormalGameListReqDto extends PageRequestDto { + private String intraId; + + public NormalGameListReqDto(Integer page, Integer size, String intraId) { + super(page, size); + this.intraId = intraId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalResultReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalResultReqDto.java new file mode 100644 index 000000000..7c4578424 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/NormalResultReqDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.user.game.controller.request; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + +import lombok.Getter; + +@Getter +public class NormalResultReqDto { + @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive(message = "gameId ๋Š” ์–‘์ˆ˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") + private Long gameId; + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankGameListReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankGameListReqDto.java new file mode 100644 index 000000000..34bb9d52e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankGameListReqDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.user.game.controller.request; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + +import lombok.Getter; + +@Getter +public class RankGameListReqDto extends NormalGameListReqDto { + @Positive + @NotNull(message = "seasonId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + private Long seasonId; + + public RankGameListReqDto(Integer pageNum, Integer pageSize, String nickname, Long seasonId) { + super(pageNum, pageSize, nickname); + this.seasonId = seasonId; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankResultReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankResultReqDto.java new file mode 100644 index 000000000..9a1eb4420 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/RankResultReqDto.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.user.game.controller.request; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class RankResultReqDto { + + @Positive + @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + private Long gameId; + @NotNull(message = "myTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long myTeamId; + @NotNull(message = "myTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int myTeamScore; + @NotNull(message = "enemyTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long enemyTeamId; + @NotNull(message = "enemyTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int enemyTeamScore; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/TournamentResultReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/TournamentResultReqDto.java new file mode 100644 index 000000000..a95b70b44 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/request/TournamentResultReqDto.java @@ -0,0 +1,33 @@ +package gg.pingpong.api.user.game.controller.request; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class TournamentResultReqDto { + @Positive + @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + private Long gameId; + @NotNull(message = "myTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long myTeamId; + @NotNull(message = "myTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int myTeamScore; + @NotNull(message = "enemyTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @Positive + private Long enemyTeamId; + @NotNull(message = "enemyTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") + @PositiveOrZero + @Max(2) + private int enemyTeamScore; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameListResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameListResDto.java new file mode 100644 index 000000000..ae2b3e29a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameListResDto.java @@ -0,0 +1,39 @@ +package gg.pingpong.api.user.game.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class GameListResDto { + private List games; + Boolean isLast; + + public GameListResDto(List games, Boolean isLast) { + this.games = games; + this.isLast = isLast; + } + + @Override + public String toString() { + return "GameListResDto{" + + "games=" + games + + ", isLast=" + isLast + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof GameListResDto)) { + return false; + } else { + GameListResDto other = (GameListResDto)obj; + return this.isLast == other.getIsLast() + && this.games.equals(other.getGames()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePChangeResultResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePChangeResultResDto.java new file mode 100644 index 000000000..b47b26e7b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePChangeResultResDto.java @@ -0,0 +1,56 @@ +package gg.pingpong.api.user.game.controller.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import gg.pingpong.api.user.store.dto.UserGameCoinResultDto; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@JsonInclude(Include.NON_NULL) +public class GamePChangeResultResDto { + private Integer beforeExp; + private Integer beforeMaxExp; + private Integer beforeLevel; + private Integer increasedExp; + private Integer increasedLevel; + private Integer afterMaxExp; + private int beforeCoin; + private int afterCoin; + private int coinIncrement; + protected Integer changedPpp; + protected Integer beforePpp; + + public GamePChangeResultResDto(Integer beforeExp, Integer currentExp, UserGameCoinResultDto userGameCoinResultDto) { + this.beforeExp = ExpLevelCalculator.getCurrentLevelMyExp(beforeExp); + this.beforeLevel = ExpLevelCalculator.getLevel(beforeExp); + this.beforeMaxExp = ExpLevelCalculator.getLevelMaxExp(beforeLevel); + this.increasedExp = currentExp - beforeExp; + this.increasedLevel = ExpLevelCalculator.getLevel(currentExp) - this.beforeLevel; + this.afterMaxExp = ExpLevelCalculator.getLevelMaxExp(this.beforeLevel + this.increasedLevel); + this.beforeCoin = userGameCoinResultDto.getBeforeCoin(); + this.afterCoin = userGameCoinResultDto.getAfterCoin(); + this.coinIncrement = userGameCoinResultDto.getCoinIncrement(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof GamePChangeResultResDto)) { + return false; + } else { + GamePChangeResultResDto other = (GamePChangeResultResDto)obj; + return this.beforeExp.equals(other.getBeforeExp()) + && this.beforeLevel.equals(other.getBeforeLevel()) + && this.beforeMaxExp.equals(other.getBeforeMaxExp()) + && this.increasedExp.equals(other.getIncreasedExp()) + && this.increasedLevel.equals(other.getIncreasedLevel()) + && this.afterMaxExp.equals(other.getAfterMaxExp()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePPPChangeResultResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePPPChangeResultResDto.java new file mode 100644 index 000000000..08b285a29 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GamePPPChangeResultResDto.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.user.game.controller.response; + +import gg.pingpong.api.user.store.dto.UserGameCoinResultDto; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class GamePPPChangeResultResDto extends GamePChangeResultResDto { + + public GamePPPChangeResultResDto(Integer beforeExp, Integer currentExp, Integer beforePpp, + Integer afterPpp, UserGameCoinResultDto userGameCoinResultDto) { + super(beforeExp, currentExp, userGameCoinResultDto); + this.changedPpp = afterPpp - beforePpp; + this.beforePpp = beforePpp; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof GamePPPChangeResultResDto)) { + return false; + } else { + GamePPPChangeResultResDto other = (GamePPPChangeResultResDto)obj; + return this.changedPpp.equals(other.getChangedPpp()) + && this.beforePpp.equals(other.getBeforePpp()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameResultResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameResultResDto.java new file mode 100644 index 000000000..77e51ae73 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/controller/response/GameResultResDto.java @@ -0,0 +1,89 @@ +package gg.pingpong.api.user.game.controller.response; + +import java.time.LocalDateTime; +import java.util.Arrays; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import gg.data.game.type.Mode; +import gg.pingpong.api.user.game.dto.TeamUserInfoDto; +import gg.pingpong.api.user.game.dto.TeamUserListDto; +import gg.repo.game.out.GameTeamUser; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class GameResultResDto { + private Long gameId; + private String status; + private Mode mode; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime time; + private TeamUserListDto team1; + private TeamUserListDto team2; + + public GameResultResDto(GameTeamUser game) { + this.gameId = game.getGameId(); + this.status = game.getStatus().name(); //name -> ๋Œ€๋ฌธ์ž + this.time = game.getStartTime(); + this.mode = game.getMode(); + if (mode == Mode.NORMAL) { + team1 = new TeamUserListDto(Arrays.asList( + new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), null, null)), null, null); + team2 = new TeamUserListDto(Arrays.asList( + new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), null, null)), null, null); + } else if (mode == Mode.RANK) { + team1 = new TeamUserListDto(Arrays.asList( + new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), game.getT1Wins(), + game.getT1Losses())), game.getT1IsWin(), game.getT1Score()); + team2 = new TeamUserListDto(Arrays.asList( + new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), game.getT2Wins(), + game.getT2Losses())), game.getT2IsWin(), game.getT2Score()); + } else if (mode == Mode.TOURNAMENT) { + team1 = new TeamUserListDto( + game.getT1TeamId(), + Arrays.asList( + new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), game.getT1Wins(), + game.getT1Losses())), + game.getT1IsWin(), game.getT1Score()); + team2 = new TeamUserListDto(game.getT2TeamId(), + Arrays.asList( + new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), game.getT2Wins(), + game.getT2Losses())), + game.getT2IsWin(), game.getT2Score()); + } + } + + @Override + public String toString() { + return "NormalGameResDto{" + + "gameId=" + gameId + + ", status='" + status + '\'' + + ", time=" + time + + ", team1=" + team1 + + ", team2=" + team2 + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof GameResultResDto)) { + return false; + } else { + GameResultResDto other = (GameResultResDto)obj; + return this.gameId.equals(other.getGameId()) + && this.status.equals(other.getStatus()) + && this.mode.equals(other.getMode()) + && this.time.equals(other.getTime()) + && this.team1.equals(other.getTeam1()) + && this.team2.equals(other.getTeam2()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/GameTeamInfo.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/GameTeamInfo.java new file mode 100644 index 000000000..e0016a67d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/GameTeamInfo.java @@ -0,0 +1,66 @@ +package gg.pingpong.api.user.game.dto; + +import java.time.LocalDateTime; +import java.util.List; + +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.repo.game.out.GameTeamUserInfo; +import gg.utils.exception.game.GameDataConsistencyException; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Getter +@NoArgsConstructor +@ToString +@Slf4j +public class GameTeamInfo { + private Mode mode; + private Long gameId; + private LocalDateTime startTime; + private StatusType status; + private Boolean isScoreExist; + private MatchTeamsInfoDto matchTeamsInfo; + + public GameTeamInfo(List infos, Long userId) { + this.mode = infos.get(0).getMode(); + this.gameId = infos.get(0).getGameId(); + this.startTime = infos.get(0).getStartTime(); + this.status = infos.get(0).getStatus(); + Long myTeamId = null; + for (GameTeamUserInfo info : + infos) { + if (info.getScore() > -1) { + this.isScoreExist = true; + } + if (!this.mode.equals(info.getMode()) || !this.gameId.equals(info.getGameId()) + || !this.startTime.equals(info.getStartTime()) || !this.status.equals(info.getStatus())) { + log.error("data error: gid 1: ", infos.get(0).getGameId(), ", gid 2:", infos.get(1).getGameId()); + throw new GameDataConsistencyException(); + } + if (info.getUserId().equals(userId)) { + myTeamId = info.getTeamId(); + } + } + this.matchTeamsInfo = new MatchTeamsInfoDto(infos, myTeamId); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof GameTeamInfo)) { + return false; + } else { + GameTeamInfo other = (GameTeamInfo)obj; + return this.status.equals(other.getStatus()) + && this.gameId.equals(other.getGameId()) + && this.isScoreExist.equals(other.getIsScoreExist()) + && this.mode.equals(other.getMode()) + && this.startTime.equals(other.getStartTime()) + && this.matchTeamsInfo.equals(other.getMatchTeamsInfo()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/MatchTeamsInfoDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/MatchTeamsInfoDto.java new file mode 100644 index 000000000..7067bc15a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/MatchTeamsInfoDto.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.user.game.dto; + +import java.util.List; + +import gg.repo.game.out.GameTeamUserInfo; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@NoArgsConstructor +@ToString +public class MatchTeamsInfoDto { + private TeamInfo myTeam; + private TeamInfo enemyTeam; + + public MatchTeamsInfoDto(List infos, Long teamId) { + if (teamId == null) { + return; + } + myTeam = new TeamInfo(); + enemyTeam = new TeamInfo(); + for (GameTeamUserInfo info : + infos) { + if (teamId.equals(info.getTeamId())) { + myTeam.setTeam(info.getTeamId(), info.getScore()); + myTeam.addPlayer(info); + } else { + enemyTeam.setTeam(info.getTeamId(), info.getScore()); + enemyTeam.addPlayer(info); + } + } + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof MatchTeamsInfoDto)) { + return false; + } else { + MatchTeamsInfoDto other = (MatchTeamsInfoDto)obj; + return this.myTeam.equals(other.getMyTeam()) + && this.enemyTeam.equals(other.getEnemyTeam()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamInfo.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamInfo.java new file mode 100644 index 000000000..f55dfecb5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamInfo.java @@ -0,0 +1,43 @@ +package gg.pingpong.api.user.game.dto; + +import java.util.ArrayList; +import java.util.List; + +import gg.repo.game.out.GameTeamUserInfo; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +public class TeamInfo { + private Integer teamScore; + private Long teamId; + private List players; + + public TeamInfo() { + this.players = new ArrayList<>(); + } + + public void setTeam(Long teamId, Integer teamScore) { + this.teamId = teamId; + this.teamScore = teamScore; + } + + public void addPlayer(GameTeamUserInfo info) { + this.players.add(new TeamUserInfoDto(info.getIntraId(), info.getImage(), info.getExp(), null, null)); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof TeamInfo)) { + return false; + } else { + TeamInfo other = (TeamInfo)obj; + return this.teamScore.equals(other.getTeamScore()) + && this.teamId.equals(other.getTeamId()) + && this.players.equals(other.getPlayers()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamReqDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamReqDto.java new file mode 100644 index 000000000..848f3dae2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamReqDto.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.user.game.dto; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TeamReqDto { + + @NotNull + private Long teamId; + + @NotNull + @Max(value = 2, message = "์ ์ˆ˜๋Š” ์ตœ๋Œ€ 2์  ์ž…๋‹ˆ๋‹ค.") + @Min(value = 0, message = "์ ์ˆ˜๋Š” ์ตœ์†Œ 0์  ์ž…๋‹ˆ๋‹ค.") + private int score; + + public TeamReqDto(Long teamId, int score) { + this.teamId = teamId; + this.score = score; + } + + @Override + public String toString() { + return "TeamReqDto{" + + "teamId=" + teamId + + ", score=" + score + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserInfoDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserInfoDto.java new file mode 100644 index 000000000..71fddf0ae --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserInfoDto.java @@ -0,0 +1,52 @@ +package gg.pingpong.api.user.game.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class TeamUserInfoDto { + private String intraId; + private String userImageUri; + private Integer level; + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer wins; + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer losses; + + public TeamUserInfoDto(String intraId, String userImageUri, Integer exp, Integer wins, Integer losses) { + this.intraId = intraId; + this.userImageUri = userImageUri; + this.level = ExpLevelCalculator.getLevel(exp); + this.wins = wins; + this.losses = losses; + } + + @Override + public String toString() { + return "TeamUserInfoDto{" + + "intraId='" + intraId + '\'' + + ", userImageUri='" + userImageUri + '\'' + + ", level=" + level + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof TeamUserInfoDto)) { + return false; + } else { + TeamUserInfoDto other = (TeamUserInfoDto)obj; + return this.intraId.equals(other.getIntraId()) + && this.level.equals(other.getLevel()) + && this.userImageUri.equals(other.getUserImageUri()) + && (this.wins == other.getWins() || this.wins.equals(other.getWins())) + && (this.losses == other.getLosses() || this.losses.equals(other.getLosses())); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserListDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserListDto.java new file mode 100644 index 000000000..86d28ef1c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/dto/TeamUserListDto.java @@ -0,0 +1,55 @@ +package gg.pingpong.api.user.game.dto; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class TeamUserListDto { + Long teamId; + + List players; + + @JsonInclude(JsonInclude.Include.NON_NULL) + Boolean isWin; + @JsonInclude(JsonInclude.Include.NON_NULL) + Integer score; + + public TeamUserListDto(List players, Boolean isWin, Integer score) { + this.isWin = isWin; + this.score = score; + this.players = players; + } + + public TeamUserListDto(Long teamId, List players, Boolean isWin, Integer score) { + this.teamId = teamId; + this.players = players; + this.isWin = isWin; + this.score = score == -1 ? null : score; + } + + @Override + public String toString() { + return "TeamUserListDto{" + + "players=" + players + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof TeamUserListDto)) { + return false; + } else { + TeamUserListDto other = (TeamUserListDto)obj; + return (isWin == other.getIsWin() || this.isWin.equals(other.getIsWin())) + && (score == other.getScore() || this.score.equals(other.getScore())) + && this.players.equals(other.getPlayers()); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameFindService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameFindService.java new file mode 100644 index 000000000..caaf78c60 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameFindService.java @@ -0,0 +1,159 @@ +package gg.pingpong.api.user.game.service; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.pingpong.api.user.game.controller.response.GameListResDto; +import gg.pingpong.api.user.game.controller.response.GameResultResDto; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameTeamUser; +import gg.utils.exception.game.GameNotExistException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class GameFindService { + private final GameRepository gameRepository; + + /** + * ํŠน์ • User์˜ NORMAL ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + * @param pageable + * @param intra - ์กฐํšŒํ•  ์œ ์ €์˜ intraId + * @return GameListResDto - games isLast + */ + @Transactional(readOnly = true) + @Cacheable(value = "normalGameListByIntra", cacheManager = "gameCacheManager") + public GameListResDto normalGameListByIntra(Pageable pageable, String intra) { + Slice games = gameRepository.findGamesByUserAndModeAndStatus(intra, Mode.NORMAL.name(), + StatusType.END.name(), pageable); + return new GameListResDto(getNormalGameResultList(games.getContent()), games.isLast()); + } + + /** + * NORMAL ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + * @param pageable + * @return + */ + @Transactional(readOnly = true) + @Cacheable(value = "normalGameList", cacheManager = "gameCacheManager") + public GameListResDto getNormalGameList(Pageable pageable) { + Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); + return new GameListResDto( + getNormalGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.isLast()); + } + + /** + * ํŠน์ • User์˜ RANK ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + * @param pageable + * @param seasonId - ์กฐํšŒํ•  ์‹œ์ฆŒ์˜ id + * @param intra - ์กฐํšŒํ•  ์œ ์ €์˜ intraId + * @return GameListResDto - games isLast + */ + @Transactional(readOnly = true) + @Cacheable(value = "rankGameListByIntra", cacheManager = "gameCacheManager") + public GameListResDto rankGameListByIntra(Pageable pageable, Long seasonId, String intra) { + Slice games = gameRepository.findGamesByUserAndModeAndSeason(intra, Mode.RANK.name(), seasonId, + StatusType.END.name(), pageable); + return new GameListResDto(getGameResultList(games.getContent()), games.isLast()); + } + + /** + * RANK ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + * @param pageable + * @param seasonId - ์กฐํšŒํ•  ์‹œ์ฆŒ์˜ id + * @return GameListResDto - games isLast + */ + @Transactional(readOnly = true) + @Cacheable(value = "rankGameList", cacheManager = "gameCacheManager") + public GameListResDto rankGameList(Pageable pageable, Long seasonId) { + Slice games = gameRepository.findAllByModeAndStatusAndSeasonId(Mode.RANK, StatusType.END, seasonId, + pageable); + return new GameListResDto( + getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.isLast()); + } + + /** + * NORMAL, RANDOM ๋ชจ๋“œ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + *

+ * status๊ฐ€ "LIVE" -> ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„๋„ ํฌํ•จํ•ด์„œ ์กฐํšŒ (END, LIVE, WAIT)
+ * status๊ฐ€ null -> ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„๋งŒ ์กฐํšŒ (END) + *

+ * @param pageable + * @param status - "LIVE" or null + * @return GameListResDto - games isLast + */ + @Transactional(readOnly = true) + @Cacheable(value = "allGameList", + cacheManager = "gameCacheManager", + key = "#pageable.pageNumber + #pageable.pageSize + #pageable.sort.toString() + #status") + public GameListResDto allGameList(Pageable pageable, String status) { + Slice games; + if (status != null && status.equals("LIVE")) { + games = gameRepository.findAllByModeInAndStatusIn(Arrays.asList(Mode.RANK, Mode.NORMAL), + Arrays.asList(StatusType.END, StatusType.LIVE, StatusType.WAIT), pageable); + } else { + games = gameRepository.findAllByModeInAndStatus(Arrays.asList(Mode.RANK, Mode.NORMAL), StatusType.END, + pageable); + } + return new GameListResDto( + getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.isLast()); + } + + /** + * allGameList()์™€ ๋™์ผํ•œ ๋กœ์ง + intraId๋กœ ์กฐํšŒ + * @param pageable + * @param intra - ์กฐํšŒํ•  intraId + * @param status - "LIVE" or null + * @return GameListResDto - games isLast + * @throws GameNotExistException - intraId๋กœ ์กฐํšŒํ•œ ๊ฒŒ์ž„์ด ์—†์„ ๊ฒฝ์šฐ + */ + @Transactional(readOnly = true) + @Cacheable(value = "allGameListByUser", cacheManager = "gameCacheManager", + key = "#pageable.pageNumber + #pageable.pageSize + #pageable.sort.toString() + #status + #intra") + public GameListResDto allGameListUser(Pageable pageable, String intra, String status) { + List statusTypes = Arrays.asList(StatusType.END.name()); + if (status != null && status.equals("LIVE")) { + statusTypes.add(StatusType.LIVE.name()); + statusTypes.add(StatusType.WAIT.name()); + } + Slice games = gameRepository.findGamesByUserAndModeInAndStatusIn(intra, + Arrays.asList(Mode.RANK.name(), Mode.NORMAL.name()), statusTypes, pageable); + return new GameListResDto(getGameResultList(games.getContent()), games.isLast()); + } + + public Game findByGameId(Long gameId) { + return gameRepository.findById(gameId) + .orElseThrow(GameNotExistException::new); + } + + public Game findGameWithPessimisticLockById(Long id) { + return gameRepository.findWithPessimisticLockById(id) + .orElseThrow(GameNotExistException::new); + } + + /** + * private method + */ + private List getGameResultList(List games) { + List teamViews = gameRepository.findTeamsByGameIsIn(games); + return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); + } + + private List getNormalGameResultList(List games) { + List teamViews = gameRepository.findTeamsByGameIsInAndNormalMode(games); + return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameService.java new file mode 100644 index 000000000..9f9fba0ab --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameService.java @@ -0,0 +1,307 @@ +package gg.pingpong.api.user.game.service; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.game.TeamUser; +import gg.data.game.type.StatusType; +import gg.data.match.type.TournamentMatchStatus; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.RoundNumber; +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import gg.pingpong.api.user.game.controller.request.NormalResultReqDto; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.pingpong.api.user.game.controller.request.TournamentResultReqDto; +import gg.pingpong.api.user.game.controller.response.GamePChangeResultResDto; +import gg.pingpong.api.user.game.controller.response.GamePPPChangeResultResDto; +import gg.pingpong.api.user.game.dto.GameTeamInfo; +import gg.pingpong.api.user.match.service.MatchTournamentService; +import gg.pingpong.api.user.rank.redis.RankRedisService; +import gg.pingpong.api.user.rank.service.TierService; +import gg.pingpong.api.user.store.dto.UserGameCoinResultDto; +import gg.pingpong.api.user.store.service.UserCoinChangeService; +import gg.repo.game.GameRepository; +import gg.repo.game.PChangeRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.game.out.GameTeamUserInfo; +import gg.repo.tournarment.TournamentGameRepository; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; +import gg.utils.exception.game.GameNotExistException; +import gg.utils.exception.game.GameStatusNotMatchedException; +import gg.utils.exception.game.ScoreAlreadyEnteredException; +import gg.utils.exception.pchange.PChangeNotExistException; +import gg.utils.exception.team.TeamIdNotMatchException; +import gg.utils.exception.tournament.TournamentGameNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class GameService { + private final GameRepository gameRepository; + private final TeamUserRepository teamUserRepository; + private final RankRedisService rankRedisService; + private final PChangeService pChangeService; + private final PChangeRepository pChangeRepository; + private final GameFindService gameFindService; + private final UserCoinChangeService userCoinChangeService; + private final TierService tierService; + private final TournamentGameRepository tournamentGameRepository; + private final MatchTournamentService matchTournamentService; + + /** + * ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. + * + * @param gameId + * @param userId + * @return GameTeamInfo ๊ฒŒ์ž„ ์ •๋ณด + * @throws GameNotExistException ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ + */ + @Transactional(readOnly = true) + public GameTeamInfo getUserGameInfo(Long gameId, Long userId) { + List infos = gameRepository.findTeamGameUser(gameId); + if (infos.isEmpty()) { + throw new GameNotExistException(); + } + return new GameTeamInfo(infos, userId); + } + + /** + * rank ๊ฒŒ์ž„ ๊ฒฐ๊ณผ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค. + * WAIT, LIVE ์ƒํƒœ์ผ ๋•Œ๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅ + * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€ + */ + @Transactional + @Caching(evict = { + @CacheEvict(value = "rankGameListByIntra", allEntries = true), + @CacheEvict(value = "rankGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true), + @CacheEvict(value = "ranking", allEntries = true), + @CacheEvict(value = "expRanking", allEntries = true) + }) + public Boolean createRankResult(RankResultReqDto scoreDto, Long userId) { + // ํ˜„์žฌ ๊ฒŒ์ž„ id + Game game = gameFindService.findGameWithPessimisticLockById(scoreDto.getGameId()); + if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { + return false; + } + return updateRankGameScore(game, scoreDto, userId); + } + + /** + * tournament ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋“ฑ๋ก + * @param scoreDto ์š”์ฒญ Dto + * @param userId ์‚ฌ์šฉ์ž Id + * @exception GameStatusNotMatchedException ๊ฒŒ์ž„ ์ƒํƒœ๊ฐ€ WAIT, LIVE๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ + * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€ + */ + @Transactional + public void createTournamentGameResult(TournamentResultReqDto scoreDto, Long userId) { + Game game = gameFindService.findGameWithPessimisticLockById(scoreDto.getGameId()); + if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { + throw new GameStatusNotMatchedException(); + } + updateTournamentGameScore(game, scoreDto, userId); + if (TournamentMatchStatus.REQUIRED.equals(matchTournamentService.checkTournamentGame(game))) { + TournamentGame tournamentGame = tournamentGameRepository.findByGameId(game.getId()) + .orElseThrow(TournamentGameNotFoundException::new); + Tournament tournament = tournamentGame.getTournament(); + RoundNumber matchRound = tournamentGame.getTournamentRound().getNextRound().getRoundNumber(); + matchTournamentService.matchGames(tournament, matchRound); + } + } + + /** + * normal ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•˜๊ณ  exp(๊ฒฝํ—˜์น˜)๋ฅผ ๋ถ€์—ฌํ•œ๋‹ค. + * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€: false + * @throws InvalidParameterException team ์ •๋ณด๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์„ ๋•Œ + * @throws PChangeNotExistException pchange ์ •๋ณด๊ฐ€ ์—†์„ ๋•Œ + */ + @Transactional + @Caching(evict = { + @CacheEvict(value = "normalGameListByIntra", allEntries = true), + @CacheEvict(value = "normalGameList", allEntries = true), + @CacheEvict(value = "allGameList", allEntries = true), + @CacheEvict(value = "allGameListByUser", allEntries = true), + @CacheEvict(value = "ranking", allEntries = true), + @CacheEvict(value = "expRanking", allEntries = true) + }) + public Boolean normalExpResult(NormalResultReqDto normalResultReqDto, Long loginUserId) { + Game game = gameFindService.findGameWithPessimisticLockById(normalResultReqDto.getGameId()); + List teamUsers = teamUserRepository.findAllByGameId(game.getId()); + if (teamUsers.size() == 2 + && (game.getStatus() == StatusType.WAIT || game.getStatus() == StatusType.LIVE)) { + expUpdates(game, teamUsers); + savePChange(game, teamUsers, loginUserId); + return true; + } else if (teamUsers.size() == 2 && game.getStatus() == StatusType.END) { + updatePchangeIsChecked(game, loginUserId); + return true; + } else if (teamUsers.size() != 2) { + throw new InvalidParameterException("team ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); + } + // BEFORE ์ƒํƒœ์ผ ๋•Œ false + return false; + } + + /** + * normal ๊ฒŒ์ž„์— ๋Œ€ํ•œ exp ๋ณ€ํ™” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. + * @param gameId + * @param userId + * @return GamePChangeResultResDto ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ๊ฒฐ๊ณผ + */ + @Transactional + public GamePChangeResultResDto expChangeResult(Long gameId, Long userId) { + List pChanges = pChangeService.findExpChangeHistory(gameId, userId); + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); + + if (pChanges.size() == 1) { + return new GamePChangeResultResDto(0, pChanges.get(0).getExp(), userGameCoinResultDto); + } else { + return new GamePChangeResultResDto(pChanges.get(1).getExp(), pChanges.get(0).getExp(), + userGameCoinResultDto); + } + } + + /** + * rank ๊ฒŒ์ž„์— ๋Œ€ํ•œ exp, ppp ๋ณ€ํ™” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. + * @param gameId ๊ฒŒ์ž„ id + * @param userId ๊ฒŒ์ž„์— ์ฐธ์—ฌํ•œ ์œ ์ € id + * @return GamePPPChangeResultResDto ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ๊ฒฐ๊ณผ + * @throws PChangeNotExistException + */ + @Transactional + public GamePPPChangeResultResDto pppChangeResult(Long gameId, Long userId) throws PChangeNotExistException { + Season season = gameFindService.findByGameId(gameId).getSeason(); + List pppHistory = pChangeService.findPPPChangeHistory(gameId, userId, season.getId()); + List expHistory = pChangeService.findExpChangeHistory(gameId, userId); + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addRankGameCoin(gameId, userId); + return new GamePPPChangeResultResDto(expHistory.size() <= 1 ? 0 : expHistory.get(1).getExp(), + pppHistory.get(0).getExp(), + pppHistory.size() <= 1 ? season.getStartPpp() : pppHistory.get(1).getPppResult(), + pppHistory.get(0).getPppResult(), userGameCoinResultDto); + } + + public void expUpdates(Game game, List teamUsers) { + LocalDateTime time = getToday(game.getStartTime()); + for (TeamUser tu : + teamUsers) { + expUpdate(tu, time); + } + if (game.getStatus() == StatusType.LIVE) { + game.updateStatus(); + } + game.updateStatus(); + } + + /** + * PRIVATE METHOD + */ + private void updatePchangeIsChecked(Game game, Long loginUserId) { + pChangeRepository.findPChangeByUserIdAndGameId(loginUserId, game.getId()) + .ifPresentOrElse( + pChange -> { + pChange.checkPChange(); + pChangeRepository.save(pChange); + }, + () -> { + throw new PChangeNotExistException(); + }); + } + + public void savePChange(Game game, List teamUsers, Long loginUserId) { + if (!pChangeRepository.findPChangesByGameId(game.getId()).isEmpty()) { + return; + } + Long team1UserId = teamUsers.get(0).getUser().getId(); + Long team2UserId = teamUsers.get(1).getUser().getId(); + pChangeService.addPChange(game, teamUsers.get(0).getUser(), + rankRedisService.getUserPpp(team1UserId, game.getSeason().getId()), team1UserId.equals(loginUserId)); + pChangeService.addPChange(game, teamUsers.get(1).getUser(), + rankRedisService.getUserPpp(team2UserId, game.getSeason().getId()), team2UserId.equals(loginUserId)); + } + + private void expUpdate(TeamUser teamUser, LocalDateTime time) { + Integer gamePerDay = teamUserRepository.findByDateAndUser(time, teamUser.getUser().getId()); + teamUser.getUser().addExp(ExpLevelCalculator.getExpPerGame() + (ExpLevelCalculator.getExpBonus() * gamePerDay)); + } + + private static LocalDateTime getToday(LocalDateTime gameTime) { + return LocalDateTime.of(gameTime.getYear(), gameTime.getMonthValue(), gameTime.getDayOfMonth(), 0, 0); + } + + private void setTeamScore(TeamUser tu, int teamScore, Boolean isWin) { + tu.getTeam().updateScore(teamScore, isWin); + } + + private TeamUser findTeamId(Long teamId, List teamUsers) { + for (TeamUser tu : + teamUsers) { + if (tu.getTeam().getId().equals(teamId)) { + return tu; + } + } + throw new TeamIdNotMatchException(); + } + + private Boolean updateRankGameScore(Game game, RankResultReqDto scoreDto, Long userId) { + List teams = teamUserRepository.findAllByGameId(game.getId()); + TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); + TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); + if (!myTeam.getUser().getId().equals(userId)) { + throw new InvalidParameterException("team user ์ •๋ณด ๋ถˆ์ผ์น˜.", ErrorCode.VALID_FAILED); + } else { + if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)) { + setTeamScore(myTeam, scoreDto.getMyTeamScore(), + scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); + setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), + scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); + expUpdates(game, teams); + rankRedisService.updateRankRedis(myTeam, enemyTeam, game); + tierService.updateAllTier(game.getSeason()); + } else { + // score ๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋จ + return false; + } + return true; + } + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์—…๋ฐ์ดํŠธ ๋ฉ”์†Œ๋“œ + * @param game + * @param scoreDto + * @param userId + * @exception InvalidParameterException ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ userId๊ฐ€ myTeam์˜ userId์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + * @exception ScoreAlreadyEnteredException ๊ฒŒ์ž„ ์ ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ + */ + private void updateTournamentGameScore(Game game, TournamentResultReqDto scoreDto, Long userId) { + List teams = teamUserRepository.findAllByGameId(game.getId()); + TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); + TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); + if (!myTeam.getUser().getId().equals(userId)) { + throw new InvalidParameterException("team user ์ •๋ณด๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); + } + if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)) { + setTeamScore(myTeam, scoreDto.getMyTeamScore(), scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); + setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), + scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); + expUpdates(game, teams); + savePChange(game, teams, userId); + } else { + // score ๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋จ + throw new ScoreAlreadyEnteredException(ErrorCode.SCORE_ALREADY_ENTERED.getMessage(), + ErrorCode.SCORE_ALREADY_ENTERED); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameStatusService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameStatusService.java new file mode 100644 index 000000000..987541416 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/GameStatusService.java @@ -0,0 +1,106 @@ +package gg.pingpong.api.user.game.service; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.noti.service.SnsNotiService; +import gg.pingpong.api.user.user.service.UserService; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameUser; +import gg.repo.manage.SlotManagementRepository; +import gg.utils.exception.game.GameDataConsistencyException; +import gg.utils.exception.match.SlotNotFoundException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class GameStatusService { + + private final GameRepository gameRepository; + private final SnsNotiService snsNotiService; + private final NotiService notiService; + private final UserService userService; + private final SlotManagementRepository slotManagementRepository; + + @Transactional + @Caching(evict = { + @CacheEvict(value = "allGameList", allEntries = true), + }) + public void updateBeforeToLiveStatus() { + // game before ์ค‘์— ํ˜„์žฌ ์‹œ์ž‘ ์‹œ๊ฐ„์ธ ๊ฒฝ์šฐ LIVE๋กœ update + List game = gameRepository.findAllByStatusAndStartTimeLessThanEqual(StatusType.BEFORE, getTime(0)); + if (!game.isEmpty()) { + cacheDelete(); + } + for (Game g : game) { + g.updateStatus(); + } + } + + void cacheDelete() { + } + + @Transactional + @Caching(evict = { + @CacheEvict(value = "allGameList", allEntries = true), + }) + public void updateLiveToWaitStatus() { + // game live ์ค‘์— ์ข…๋ฃŒ ์‹œ๊ฐ„์ธ ๊ฒฝ์šฐ wait ๋กœ update + LocalDateTime endTime = getTime(1); + List game = gameRepository.findAllByStatusAndEndTimeLessThanEqual(StatusType.LIVE, endTime); + if (!game.isEmpty()) { + cacheDelete(); + } + for (Game g : game) { + g.updateStatus(); + } + } + + @Transactional + public void imminentGame() { + SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) + .orElseThrow(SlotNotFoundException::new); + List games = gameRepository.findAllByStartTimeLessThanEqual(getTime(slotManagement.getOpenMinute())); + if (games.size() > 2) { + log.error("imminent game size is not 2 -> size: " + games.size() + ", check time: " + getTime( + slotManagement.getOpenMinute())); + throw new GameDataConsistencyException(); + } else if (games.isEmpty()) { + log.info("์‹œ์ž‘ " + slotManagement.getOpenMinute() + "๋ถ„ ์ „์ธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); + return; + } else { + notiProcess(games.get(0), games.get(1).getIntraId(), slotManagement.getOpenMinute()); + notiProcess(games.get(1), games.get(0).getIntraId(), slotManagement.getOpenMinute()); + } + } + + /** + * private method + */ + private void notiProcess(GameUser game, String enemyIntra, Integer gameOpenMinute) { + Noti noti = notiService.createImminentNoti(userService.getUser(game.getUserId()), enemyIntra, NotiType.IMMINENT, + gameOpenMinute); + snsNotiService.sendSnsNotification(noti, new UserNotiDto(game)); + } + + private LocalDateTime getTime(int plusMiniute) { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime endTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), + now.getHour(), now.getMinute(), 10); + return endTime.plusMinutes(plusMiniute); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/PChangeService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/PChangeService.java new file mode 100644 index 000000000..53150d946 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/game/service/PChangeService.java @@ -0,0 +1,63 @@ +package gg.pingpong.api.user.game.service; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.user.User; +import gg.repo.game.PChangeRepository; +import gg.utils.exception.pchange.PChangeNotExistException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class PChangeService { + private final PChangeRepository pChangeRepository; + + /** + * PPP ๋ณ€ํ™”๋ฅผ ์ €์žฅ ํ•œ๋‹ค. + * + * @param game ๊ฒŒ์ž„ + * @param user ์œ ์ € + * @param pppResult PPP ๋ณ€ํ™”๋Ÿ‰ + * @param isChecked ํ™•์ธ ์—ฌ๋ถ€ + */ + @Transactional + public void addPChange(Game game, User user, Integer pppResult, Boolean isChecked) { + pChangeRepository.save(new PChange(game, user, pppResult, isChecked)); + } + + /** + * ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ์ด๋ ฅ์„ ์กฐํšŒ ํ•œ๋‹ค. + * + * @param gameId ๊ฒŒ์ž„ ์•„์ด๋”” + * @param userId ์œ ์ € ์•„์ด๋”” + * @return ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ์ด๋ ฅ + */ + public List findExpChangeHistory(Long gameId, Long userId) { + List pChanges = pChangeRepository.findExpHistory(userId, gameId); + if (pChanges.isEmpty()) { + throw new PChangeNotExistException(); + } + return pChanges; + } + + /** + * PPP ๋ณ€ํ™” ์ด๋ ฅ์„ ์กฐํšŒ ํ•œ๋‹ค. + * + * @param gameId ๊ฒŒ์ž„ ์•„์ด๋”” + * @param userId ์œ ์ € ์•„์ด๋”” + * @param seasonId ์‹œ์ฆŒ ์•„์ด๋”” + * @return PPP ๋ณ€ํ™” ์ด๋ ฅ + */ + public List findPPPChangeHistory(Long gameId, Long userId, Long seasonId) { + List pChanges = pChangeRepository.findPPPHistory(userId, gameId, seasonId); + if (pChanges.isEmpty()) { + throw new PChangeNotExistException(); + } + return pChanges; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/AnnouncementController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/AnnouncementController.java new file mode 100644 index 000000000..00d4ff9d2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/AnnouncementController.java @@ -0,0 +1,21 @@ +package gg.pingpong.api.user.manage.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.user.manage.controller.response.AnnouncementResponseDto; +import gg.pingpong.api.user.manage.service.AnnouncementService; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/pingpong/announcement") +public class AnnouncementController { + private final AnnouncementService announcementService; + + @GetMapping + public AnnouncementResponseDto findLastAnnounceContent() { + return new AnnouncementResponseDto(announcementService.findLastAnnouncement().getContent()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/FeedbackController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/FeedbackController.java new file mode 100644 index 000000000..d66bafeaf --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/FeedbackController.java @@ -0,0 +1,33 @@ +package gg.pingpong.api.user.manage.controller; + +import javax.validation.Valid; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.manage.controller.request.FeedbackRequestDto; +import gg.pingpong.api.user.manage.service.FeedbackService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.user.UserRepository; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/pingpong") +public class FeedbackController { + private final FeedbackService feedbackService; + private final UserRepository userRepository; + + @PostMapping(value = "/feedback") + public ResponseEntity feedbackSave(@Valid @RequestBody FeedbackRequestDto feedbackRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + feedbackService.addFeedback(feedbackRequestDto, user.getId()); + return new ResponseEntity(HttpStatus.CREATED); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/request/FeedbackRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/request/FeedbackRequestDto.java new file mode 100644 index 000000000..4a5066ce7 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/request/FeedbackRequestDto.java @@ -0,0 +1,26 @@ +package gg.pingpong.api.user.manage.controller.request; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import gg.data.manage.type.FeedbackType; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class FeedbackRequestDto { + @NotNull(message = "plz. not null FeedbackType") + private FeedbackType category; + @NotNull(message = "plz. not null content") + @Length(max = 600, message = "plz. maxSizeMessage 600") + private String content; + + @Builder + public FeedbackRequestDto(FeedbackType category, String content) { + this.category = category; + this.content = content; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/response/AnnouncementResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/response/AnnouncementResponseDto.java new file mode 100644 index 000000000..9db74d402 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/controller/response/AnnouncementResponseDto.java @@ -0,0 +1,10 @@ +package gg.pingpong.api.user.manage.controller.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AnnouncementResponseDto { + private String content; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/dto/AnnouncementDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/dto/AnnouncementDto.java new file mode 100644 index 000000000..7b0aa791f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/dto/AnnouncementDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.user.manage.dto; + +import gg.data.manage.Announcement; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class AnnouncementDto { + private String content; + + public static AnnouncementDto from(Announcement announcement) { + return new AnnouncementDto(announcement.getContent()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/redis/PenaltyUserRedisRepository.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/redis/PenaltyUserRedisRepository.java new file mode 100644 index 000000000..3194b11e5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/redis/PenaltyUserRedisRepository.java @@ -0,0 +1,31 @@ +package gg.pingpong.api.user.manage.redis; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.manage.type.PenaltyKey; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class PenaltyUserRedisRepository { + private final RedisTemplate redisTemplate; + + public void addPenaltyUser(RedisPenaltyUser penaltyUser, LocalDateTime releaseTime) { + LocalDateTime now = LocalDateTime.now(); + Duration duration = Duration.between(now, releaseTime); + redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, + duration.getSeconds(), TimeUnit.SECONDS); + } + + public Optional findByIntraId(String intraId) { + RedisPenaltyUser penaltyUser = redisTemplate.opsForValue().get(PenaltyKey.USER_ADMIN + intraId); + return Optional.ofNullable(penaltyUser); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/AnnouncementService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/AnnouncementService.java new file mode 100644 index 000000000..e1678b3ca --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/AnnouncementService.java @@ -0,0 +1,33 @@ +package gg.pingpong.api.user.manage.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.manage.Announcement; +import gg.pingpong.api.user.manage.dto.AnnouncementDto; +import gg.repo.manage.AnnouncementRepository; +import gg.utils.exception.announcement.AnnounceNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class AnnouncementService { + private final AnnouncementRepository announcementRepository; + + /** + *

๊ฐ€์žฅ ์ตœ๊ทผ ๊ณต์ง€๋ฅผ ์ฐพ์•„์„œ dto๋กœ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

+ *

๋งŒ์•ฝ ๊ฐ€์žฅ ์ตœ๊ทผ ๊ณต์ง€๊ฐ€ ์‚ญ์ œ ๋˜์—ˆ๋‹ค๋ฉด dto์— ๋นˆ๊ฐ’์„ ๋„ฃ์–ด์„œ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

+ * @throws AnnounceNotFoundException ๊ณต์ง€ ์—†์Œ + * @return AnnouncementDto + */ + @Transactional(readOnly = true) + public AnnouncementDto findLastAnnouncement() { + Announcement announcement = announcementRepository.findFirstByOrderByIdDesc() + .orElseThrow(AnnounceNotFoundException::new); + if (announcement.getDeletedAt() != null) { + return new AnnouncementDto(""); + } + + return AnnouncementDto.from(announcement); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/FeedbackService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/FeedbackService.java new file mode 100644 index 000000000..3642277a3 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/FeedbackService.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.manage.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.manage.Feedback; +import gg.data.user.User; +import gg.pingpong.api.user.manage.controller.request.FeedbackRequestDto; +import gg.repo.manage.FeedbackRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class FeedbackService { + private final FeedbackRepository feedbackRepository; + private final UserRepository userRepository; + + @Transactional + public void addFeedback(FeedbackRequestDto feedbackRequestDto, Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + Feedback feedback = new Feedback(user, feedbackRequestDto.getCategory(), feedbackRequestDto.getContent()); + feedbackRepository.save(feedback); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/PenaltyService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/PenaltyService.java new file mode 100644 index 000000000..107eb584d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/manage/service/PenaltyService.java @@ -0,0 +1,56 @@ +package gg.pingpong.api.user.manage.service; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.springframework.stereotype.Service; + +import gg.data.manage.Penalty; +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.manage.type.PenaltyType; +import gg.data.user.User; +import gg.pingpong.api.user.manage.redis.PenaltyUserRedisRepository; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.pingpong.api.user.user.service.UserFindService; +import gg.repo.manage.PenaltyRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class PenaltyService { + private final PenaltyRepository penaltyRepository; + private final PenaltyUserRedisRepository penaltyUserRedisRepository; + private final UserFindService userFindService; + + /** + * penalty 1๋ถ„ ๋ถ€์—ฌ + * **/ + public void givePenalty(UserDto userDto, Integer penaltyMinutes) { + + User user = userFindService.findUserById(userDto.getId()); + Optional redisPenaltyUser = penaltyUserRedisRepository + .findByIntraId(userDto.getIntraId()); + LocalDateTime releaseTime; + RedisPenaltyUser penaltyUser; + Penalty penalty; + LocalDateTime now = LocalDateTime.now(); + if (redisPenaltyUser.isPresent()) { + releaseTime = redisPenaltyUser.get().getReleaseTime().plusMinutes(penaltyMinutes); + penaltyUser = new RedisPenaltyUser(userDto.getIntraId(), + redisPenaltyUser.get().getPenaltyTime() + penaltyMinutes, + releaseTime, redisPenaltyUser.get().getStartTime(), "[AUTO] ๋งค์นญ ์ทจ์†Œ"); + penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] ๋งค์นญ ์ทจ์†Œ", redisPenaltyUser.get().getReleaseTime(), + penaltyMinutes); + } else { + releaseTime = now.plusMinutes(penaltyMinutes); + penaltyUser = new RedisPenaltyUser(user.getIntraId(), penaltyMinutes, releaseTime, now, "[AUTO] ๋งค์นญ ์ทจ์†Œ"); + penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] ๋งค์นญ ์ทจ์†Œ", now, penaltyMinutes); + } + penaltyRepository.save(penalty); + penaltyUserRedisRepository.addPenaltyUser(penaltyUser, releaseTime); + } + + public Boolean isPenaltyUser(String intraId) { + return penaltyUserRedisRepository.findByIntraId(intraId).isPresent(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/MatchController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/MatchController.java new file mode 100644 index 000000000..f515312ba --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/MatchController.java @@ -0,0 +1,74 @@ +package gg.pingpong.api.user.match.controller; + +import java.time.LocalDateTime; + +import javax.validation.Valid; + +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +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 gg.data.match.type.Option; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.match.controller.request.MatchRequestDto; +import gg.pingpong.api.user.match.controller.response.MatchStatusResponseListDto; +import gg.pingpong.api.user.match.controller.response.SlotStatusResponseListDto; +import gg.pingpong.api.user.match.service.MatchFindService; +import gg.pingpong.api.user.match.service.MatchService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/match") +public class MatchController { + private final MatchService matchService; + private final MatchFindService matchFindService; + + /** + * ์œ ์ € ์Šฌ๋กฏ ์ž…์žฅ ์š”์ฒญ API (== ๋งค์นญ ์š”์ฒญ API) + * @param matchRequestDto + * @param user ๋งค์นญ ์š”์ฒญํ•œ ์œ ์ € + * @return 201 (Created) + */ + @PostMapping + public ResponseEntity createUserMatch(@RequestBody @Valid MatchRequestDto matchRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + matchService.makeMatch(user, matchRequestDto.getOption(), matchRequestDto.getStartTime()); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping + public ResponseEntity deleteUserMatch( + @RequestParam("startTime") @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") LocalDateTime startTime, + @Parameter(hidden = true) @Login UserDto user) { + matchService.cancelMatch(user, startTime); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + /** + * ํŠน์ • ์‹œ๊ฐ„๋Œ€์˜ ๊ฒฝ๊ธฐ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ์กฐํšŒ API + * @param mode : BOTH, NORMAL, RANK + * @param user + * @return + */ + @GetMapping("/time/scope") + public SlotStatusResponseListDto getMatchTimeScope(@RequestParam(required = true) String mode, + @Parameter(hidden = true) @Login UserDto user) { + return matchFindService.getAllMatchStatus(user, Option.getEnumValue(mode)); + } + + @GetMapping + public MatchStatusResponseListDto getCurrentMatch(@Parameter(hidden = true) @Login UserDto user) { + return matchFindService.getCurrentMatch(user); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/request/MatchRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/request/MatchRequestDto.java new file mode 100644 index 000000000..46f588629 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/request/MatchRequestDto.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.user.match.controller.request; + +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import gg.data.match.type.Option; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MatchRequestDto { + + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") + private LocalDateTime startTime; + @NotNull + @JsonProperty("mode") + private Option option; + + public MatchRequestDto(LocalDateTime startTime, Option option) { + this.startTime = startTime; + this.option = option; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/MatchStatusResponseListDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/MatchStatusResponseListDto.java new file mode 100644 index 000000000..3d15d5c3a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/MatchStatusResponseListDto.java @@ -0,0 +1,25 @@ +package gg.pingpong.api.user.match.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.match.dto.MatchStatusDto; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class MatchStatusResponseListDto { + private List match; + + @Override + public String toString() { + return "MatchStatusResponseListDto{" + + "match=" + match + + '}'; + } + + public MatchStatusResponseListDto(List match) { + this.match = match; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/SlotStatusResponseListDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/SlotStatusResponseListDto.java new file mode 100644 index 000000000..ef65c4cf5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/controller/response/SlotStatusResponseListDto.java @@ -0,0 +1,25 @@ +package gg.pingpong.api.user.match.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.match.dto.SlotStatusDto; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class SlotStatusResponseListDto { + private List> matchBoards; + + @Override + public String toString() { + return "MatchStatusResponseListDto{" + + "matchBoards=" + matchBoards + + '}'; + } + + public SlotStatusResponseListDto(List> matchBoards) { + this.matchBoards = matchBoards; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/GameAddDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/GameAddDto.java new file mode 100644 index 000000000..2938b7b14 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/GameAddDto.java @@ -0,0 +1,44 @@ +package gg.pingpong.api.user.match.dto; + +import java.time.LocalDateTime; +import java.util.List; + +import gg.data.game.type.Mode; +import gg.data.match.RedisMatchUser; +import gg.data.match.type.Option; +import gg.data.season.Season; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class GameAddDto { + private LocalDateTime startTime; + private Season season; + private Long playerId; + private Long enemyId; + private Mode mode; + + public GameAddDto(LocalDateTime startTime, Season season, RedisMatchUser player, + RedisMatchUser enemy) { + this.startTime = startTime; + this.season = season; + this.playerId = player.getUserId(); + this.enemyId = enemy.getUserId(); + this.mode = ofPlayers(List.of(player, enemy), season.getPppGap()); + } + + public Mode ofPlayers(List players, Integer pppGap) { + if (players.stream().allMatch(player -> player.getOption().equals(Option.BOTH))) { + if (Math.abs(players.get(0).getPpp() - players.get(1).getPpp()) <= pppGap) { + return Mode.RANK; + } + return Mode.NORMAL; + } + if (!players.get(0).getOption().equals(Option.BOTH)) { + return Mode.getEnumValue(players.get(0).getOption().getCode()); + } + return Mode.getEnumValue(players.get(1).getOption().getCode()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/MatchStatusDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/MatchStatusDto.java new file mode 100644 index 000000000..62f813079 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/MatchStatusDto.java @@ -0,0 +1,61 @@ +package gg.pingpong.api.user.match.dto; + +import java.time.LocalDateTime; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.manage.SlotManagement; +import gg.data.match.RedisMatchTime; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MatchStatusDto { + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime startTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime endTime; + private Boolean isMatched; + private Boolean isImminent; + private List myTeam; + private List enemyTeam; + + public MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement) { + this.startTime = game.getStartTime(); + this.endTime = game.getEndTime(); + this.isMatched = true; + this.isImminent = game.getStartTime().minusMinutes(slotManagement.getOpenMinute()) + .isBefore(LocalDateTime.now()); + if (game.getMode() == Mode.TOURNAMENT) { + isImminent = true; + } + this.myTeam = List.of(userIntraId); + this.enemyTeam = List.of(enemyIntraId); + + } + + public MatchStatusDto(RedisMatchTime redisMatchTime, Integer interval) { + this.startTime = redisMatchTime.getStartTime(); + this.endTime = redisMatchTime.getStartTime().plusMinutes(interval); + this.isMatched = false; + this.isImminent = false; + this.myTeam = List.of(); + this.enemyTeam = List.of(); + } + + @Override + public String toString() { + return "CurrentMatchResponseDto{" + + "startTime=" + startTime + + "endTIme=" + endTime + + ", myTeam=" + myTeam + + ", enemyTeam=" + enemyTeam + + ", isMatched=" + isMatched + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/SlotStatusDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/SlotStatusDto.java new file mode 100644 index 000000000..dbab08775 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/dto/SlotStatusDto.java @@ -0,0 +1,41 @@ +package gg.pingpong.api.user.match.dto; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import gg.data.match.type.SlotStatus; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class SlotStatusDto { + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime startTime; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") + private LocalDateTime endTime; + private String status; + + public SlotStatusDto(LocalDateTime startTime, LocalDateTime endTime, SlotStatus status) { + this.startTime = startTime; + this.endTime = endTime; + this.status = status.getCode(); + } + + public SlotStatusDto(LocalDateTime startTime, SlotStatus status, Integer interval) { + this.startTime = startTime; + this.endTime = startTime.plusMinutes(interval); + this.status = status.getCode(); + } + + @Override + public String toString() { + return "SlotStatusDto{" + + "startTime = " + startTime + + "endTime = " + endTime + + "status = " + status + + "}"; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/GameUpdateService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/GameUpdateService.java new file mode 100644 index 000000000..90753d0ab --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/GameUpdateService.java @@ -0,0 +1,81 @@ +package gg.pingpong.api.user.match.service; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.stereotype.Service; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.manage.SlotManagement; +import gg.data.noti.Noti; +import gg.data.user.User; +import gg.pingpong.api.user.match.dto.GameAddDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.noti.service.SnsNotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class GameUpdateService { + private final GameRepository gameRepository; + private final TeamRepository teamRepository; + private final UserRepository userRepository; + private final TeamUserRepository teamUserRepository; + private final SlotManagementRepository slotManagementRepository; + private final NotiService notiService; + private final SnsNotiService snsNotiService; + + /** + * ๊ฒŒ์ž„ ์ƒ์„ฑ ๋ฉ”์„œ๋“œ + * 1) ๊ฒŒ์ž„ ์ทจ์†Œํ–ˆ์„ ๊ฒฝ์šฐ, 2) ๊ฒŒ์ž„ ๋งค์นญ๋์„ ๊ฒฝ์šฐ, 3) ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ƒ์„ฑ + * @param addDto ๊ฒŒ์ž„ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ์ •๋ณด + * @param recoveredUserId ๊ฒŒ์ž„ ์ทจ์†Œ ๋‹นํ•œ ์œ ์ €์˜ id, -1์ด๋ฉด ๋ฌด์˜๋ฏธํ•จ + */ + public void make(GameAddDto addDto, Long recoveredUserId) { + SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) + .orElseThrow(SlotNotFoundException::new); + Game game = new Game(addDto.getSeason(), addDto.getMode(), addDto.getStartTime(), + slotManagement.getGameInterval()); + gameRepository.save(game); + Team enemyTeam = new Team(game, -1, false); + Team myTeam = new Team(game, -1, false); + List matchPair = List.of(enemyTeam, myTeam); + teamRepository.saveAll(matchPair); + User playerUser = userRepository.findById(addDto.getPlayerId()).orElseThrow(UserNotFoundException::new); + User enemyUser = userRepository.findById(addDto.getEnemyId()).orElseThrow(UserNotFoundException::new); + TeamUser myTeamUser = new TeamUser(myTeam, playerUser); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + List matchTeamUser = List.of(enemyTeamUser, myTeamUser); + teamUserRepository.saveAll(matchTeamUser); + if (!playerUser.getId().equals(recoveredUserId)) { + Noti playerNoti = notiService.createMatched(playerUser, addDto.getStartTime()); + snsNotiService.sendSnsNotification(playerNoti, UserDto.from(playerUser)); + } + if (!enemyUser.getId().equals(recoveredUserId)) { + Noti enemyNoti = notiService.createMatched(enemyUser, addDto.getStartTime()); + snsNotiService.sendSnsNotification(enemyNoti, UserDto.from(enemyUser)); + } + } + + public void delete(Game game, List enemyTeam) { + enemyTeam.forEach(enemy -> { + Noti noti = notiService.createMatchCancel(enemy, game.getStartTime()); + snsNotiService.sendSnsNotification(noti, UserDto.from(enemy)); + }); + gameRepository.delete(game); + } + + public void delete(Game game) { + gameRepository.delete(game); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchFindService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchFindService.java new file mode 100644 index 000000000..0b928053b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchFindService.java @@ -0,0 +1,134 @@ +package gg.pingpong.api.user.match.service; + +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.match.RedisMatchTime; +import gg.data.match.RedisMatchUser; +import gg.data.match.type.Option; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.data.user.type.RoleType; +import gg.pingpong.api.user.match.controller.response.MatchStatusResponseListDto; +import gg.pingpong.api.user.match.controller.response.SlotStatusResponseListDto; +import gg.pingpong.api.user.match.dto.MatchStatusDto; +import gg.pingpong.api.user.match.utils.SlotGenerator; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.match.RedisMatchTimeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MatchFindService { + private final SlotManagementRepository slotManagementRepository; + private final GameRepository gameRepository; + private final UserRepository userRepository; + private final RedisMatchUserRepository redisMatchUserRepository; + private final SeasonFindService seasonFindService; + private final RankRedisRepository rankRedisRepository; + private final RedisMatchTimeRepository redisMatchTimeRepository; + private final TierRepository tierRepository; + + @Transactional(readOnly = true) + public MatchStatusResponseListDto getCurrentMatch(UserDto userDto) { + SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) + .orElseThrow(SlotNotFoundException::new); + Optional myGame = gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()); + if (myGame.isPresent()) { + List enemyTeam = userRepository.findEnemyByGameAndUser(myGame.get().getId(), userDto.getId()); + return new MatchStatusResponseListDto(List.of(new MatchStatusDto( + myGame.get(), userDto.getIntraId(), enemyTeam.get(0).getIntraId(), slotManagement + ))); + } + Set enrolledSlots = redisMatchUserRepository.getAllMatchTime(userDto.getId()); + List dtos = enrolledSlots.stream() + .map(e -> new MatchStatusDto(e, slotManagement.getGameInterval())) + .sorted(Comparator.comparing(MatchStatusDto::getStartTime)) + .collect(Collectors.toList()); + return new MatchStatusResponseListDto(dtos); + } + + @Transactional(readOnly = true) + public SlotStatusResponseListDto getAllMatchStatus(UserDto userDto, Option option) { + SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) + .orElseThrow(SlotNotFoundException::new); + Season season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + RankRedis user; + if (userDto.getRoleType().equals(RoleType.GUEST)) { + user = RankRedis.from(userDto.getId(), userDto.getIntraId(), userDto.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + } else { + user = rankRedisRepository + .findRankByUserId(RedisKeyManager.getHashKey(season.getId()), userDto.getId()); + } + SlotGenerator slotGenerator = new SlotGenerator(user, slotManagement, season, option); + List games = gameRepository.findAllBetween(slotGenerator.getNow(), slotGenerator.getMaxTime()); + slotGenerator.addPastSlots(); + slotGenerator.addMatchedSlots(games); + + Optional myGame = gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()); + Set gameTimes = games.stream().map(Game::getStartTime).collect(Collectors.toSet()); + if (myGame.isPresent()) { + groupEnrolledSlots(slotGenerator, myGame.get(), gameTimes); + } else { + groupEnrolledSlots(slotGenerator, gameTimes); + } + return slotGenerator.getResponseListDto(); + } + + private void groupEnrolledSlots(SlotGenerator slotGenerator, Game myGame, Set gameTimes) { + Set enrolledTimes = redisMatchTimeRepository.getAllEnrolledStartTimes(); + slotGenerator.addMySlots(myGame); + Set notMyEnrolledTimes = enrolledTimes.stream() + .filter(e -> !e.equals(myGame.getStartTime()) && !gameTimes.contains(e)) + .collect(Collectors.toSet()); + notMyEnrolledTimes.stream() + .forEach( + time -> { + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(time); + slotGenerator.groupEnrolledSlot(time, allMatchUsers); + } + ); + } + + private void groupEnrolledSlots(SlotGenerator slotGenerator, Set gameTimes) { + Set enrolledTimes = redisMatchTimeRepository.getAllEnrolledStartTimes(); + Set allMatchTime = redisMatchUserRepository.getAllMatchTime( + slotGenerator.getMatchUser().getUserId()); + slotGenerator.addMySlots(allMatchTime); + Set times = allMatchTime.stream().map(RedisMatchTime::getStartTime) + .collect(Collectors.toSet()); + Set notMyEnrolledTimes = enrolledTimes.stream() + .filter(e -> !times.contains(e) && !gameTimes.contains(e)) + .collect(Collectors.toSet()); + notMyEnrolledTimes.stream().forEach( + time -> { + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(time); + slotGenerator.groupEnrolledSlot(time, allMatchUsers); + } + ); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchService.java new file mode 100644 index 000000000..42993ffcb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchService.java @@ -0,0 +1,231 @@ +package gg.pingpong.api.user.match.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.match.RedisMatchTime; +import gg.data.match.RedisMatchUser; +import gg.data.match.type.Option; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.pingpong.api.user.manage.service.PenaltyService; +import gg.pingpong.api.user.match.dto.GameAddDto; +import gg.pingpong.api.user.match.utils.MatchCalculator; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.match.RedisMatchTimeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; +import gg.utils.exception.game.GameAlreadyExistException; +import gg.utils.exception.match.EnrolledSlotException; +import gg.utils.exception.match.PenaltyUserSlotException; +import gg.utils.exception.match.SlotCountException; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.tournament.TournamentConflictException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MatchService { + private final RedisMatchTimeRepository redisMatchTimeRepository; + private final RedisMatchUserRepository redisMatchUserRepository; + private final SeasonFindService seasonFindService; + private final RankRedisRepository rankRedisRepository; + private final GameRepository gameRepository; + private final PenaltyService penaltyService; + private final GameUpdateService gameUpdateService; + private final UserRepository userRepository; + private final TournamentRepository tournamentRepository; + private final SlotManagementRepository slotManagementRepository; + + /** + * 1) ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์œ ์ € ์žˆ์„ ๊ฒฝ์šฐ : ๊ฒŒ์ž„ ์ƒ์„ฑ + * 2) ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์œ ์ € ์—†์„ ๊ฒฝ์šฐ : ์œ ์ €๋ฅผ ํ์— ๋„ฃ์–ด์คŒ + */ + @Transactional + public synchronized void makeMatch(UserDto userDto, Option option, LocalDateTime startTime) { + checkValid(userDto, startTime); + Season season = seasonFindService.findCurrentSeason(startTime); + RankRedis rank = rankRedisRepository + .findRankByUserId(RedisKeyManager.getHashKey(season.getId()), userDto.getId()); + RedisMatchUser player = new RedisMatchUser(userDto.getId(), rank.getPpp(), option); + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); + MatchCalculator matchCalculator = new MatchCalculator(season.getPppGap(), player); + Optional enemy = matchCalculator.findEnemy(allMatchUsers); + if (enemy.isPresent()) { + GameAddDto gameDto = new GameAddDto(startTime, season, player, enemy.get()); + gameUpdateService.make(gameDto, -1L); + redisMatchTimeRepository.addMatchUser(startTime, player); + cancelEnrolledSlots(List.of(enemy.get(), player), startTime); + } else { + addUserToQueue(startTime, player, option); + } + } + + /** + * 1) ๋งค์นญ๋˜์–ด ๊ฒŒ์ž„ ์ƒ์„ฑ๋œ ํ›„ : ๊ฒŒ์ž„ ์‚ญ์ œํ•˜๊ณ  ์•Œ๋ฆผ ์ „์†ก, ์ทจ์†Œํ•œ ์œ ์ € ํŒจ๋„ํ‹ฐ ๋ถ€๊ณผ + * ๋ณต๊ท€ ์œ ์ €๋Š” ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€ ์กด์žฌํ•˜๋ฉด ๋‹ค์‹œ ๋งค์นญํ•ด์ฃผ๊ณ  ์•„๋‹ˆ๋ฉด ์ทจ์†Œ ์•Œ๋ฆผ ๋ณด๋‚ด๊ณ  ํ์— ๋“ฑ๋ก ์‹œํ‚ด + * 2) ๋งค์นญ ์ „ : ํ์—์„œ ์œ ์ € ์‚ญ์ œ + * game ๋งค์นญ๋œ user ์ด์™ธ์— ๋‹ค๋ฅธ user๊ฐ€ ์ทจ์†Œํ•  ๊ฒฝ์šฐ, ์—๋Ÿฌ ๋ฐœ์ƒ + */ + @Transactional + public synchronized void cancelMatch(UserDto userDto, LocalDateTime startTime) { + Optional game = gameRepository.findByStartTime(startTime); + if (game.isPresent()) { + List enemyTeam = userRepository.findEnemyByGameAndUser(game.get().getId(), userDto.getId()); + if (enemyTeam.size() > 1) { + throw new SlotNotFoundException(); + } + if (game.get().getMode().equals(Mode.TOURNAMENT)) { + throw new BusinessException(ErrorCode.TOURNAMENT_GAME_CAN_NOT_CANCELED); + } + cancelGame(userDto, startTime, game.get(), enemyTeam); + } else { + deleteUserFromQueue(userDto, startTime); + } + } + + private void cancelGame(UserDto userDto, LocalDateTime startTime, Game game, List enemyTeam) { + /*์ทจ์†Œํ•œ ์œ ์ € ํ์—์„œ ์‚ญ์ œ ํ›„ ํŒจ๋„ํ‹ฐ ๋ถ€๊ณผ*/ + Long recoveredUserId = enemyTeam.get(0).getId(); + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); + RedisMatchUser penaltyUser = allMatchUsers.stream() + .filter(ele -> ele.getUserId().equals(userDto.getId())) + .findFirst() + .orElseThrow(UserNotFoundException::new); + RedisMatchUser recoveredUser = allMatchUsers.stream() + .filter(ele -> ele.getUserId().equals(recoveredUserId)) + .findFirst() + .orElseThrow(UserNotFoundException::new); + redisMatchTimeRepository.deleteMatchUser(startTime, penaltyUser); + penaltyService.givePenalty(userDto, 30); + /*์ทจ์†Œ ๋‹นํ•œ ์œ ์ € ๋งค์นญ ์ƒ๋Œ€ ์ฐพ๊ณ  ์žˆ์œผ๋ฉด ๋‹ค์‹œ ๊ฒŒ์ž„ ์ƒ์„ฑ ์•„๋‹ˆ๋ฉด ์ทจ์†Œ ์•Œ๋ฆผ*/ + Season season = seasonFindService.findCurrentSeason(startTime); + MatchCalculator matchCalculator = new MatchCalculator(season.getPppGap(), recoveredUser); + List targetPlayers = allMatchUsers.stream() + .filter(ele -> !ele.getUserId().equals(userDto.getId()) + && !ele.getUserId().equals(recoveredUserId)) + .collect(Collectors.toList()); + Optional enemy = matchCalculator.findEnemy(targetPlayers); + if (enemy.isPresent()) { + gameUpdateService.delete(game); + GameAddDto gameDto = new GameAddDto(startTime, season, recoveredUser, enemy.get()); + gameUpdateService.make(gameDto, recoveredUserId); + } else { + gameUpdateService.delete(game, enemyTeam); + redisMatchUserRepository.addMatchTime(recoveredUserId, startTime, recoveredUser.getOption()); + } + } + + /** + * ๋งค์นญ ์š”์ฒญ ์‹œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ + * @param userDto ๋งค์นญ ์š”์ฒญํ•œ ์œ ์ € + * @param startTime ๋งค์นญ ์š”์ฒญ ์‹œ๊ฐ„ + * @throws PenaltyUserSlotException ํŒจ๋„ํ‹ฐ ์œ ์ €์ผ ๊ฒฝ์šฐ + * @throws TournamentConflictException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ + * @throws GameAlreadyExistException ๊ฒŒ์ž„์ด ์ด๋ฏธ ์กด์žฌํ•  ๊ฒฝ์šฐ + * @throws EnrolledSlotException ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์ด๋ฏธ ์žˆ์„ ๊ฒฝ์šฐ || ์œ ์ € ์ด๋ฏธ ํ์— ๋“ฑ๋กํ•  ๊ฒฝ์šฐ + * @throws SlotCountException 4๋ฒˆ ์ด์ƒ ๋งค์น˜ ๋„ฃ์„ ๊ฒฝ์šฐ + * + */ + private void checkValid(UserDto userDto, LocalDateTime startTime) { + if (penaltyService.isPenaltyUser(userDto.getIntraId())) { + throw new PenaltyUserSlotException(); + } + if (isExistTournamentNotEnded(startTime)) { + throw new TournamentConflictException(); + } + if (gameRepository.findByStartTime(startTime).isPresent()) { + throw new GameAlreadyExistException(); + } + if (gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()).isPresent()) { + throw new EnrolledSlotException(); + } + //์œ ์ € ์ด๋ฏธ ํ์— ๋“ฑ๋ก ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ + if (redisMatchUserRepository.getUserTime(userDto.getId(), startTime).isPresent()) { + throw new EnrolledSlotException(); + } + //4๋ฒˆ ์ด์ƒ ๋งค์น˜ ๋„ฃ์„ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ + if (redisMatchUserRepository.countMatchTime(userDto.getId()) >= 3) { + throw new SlotCountException(); + } + } + + private void addUserToQueue(LocalDateTime startTime, RedisMatchUser matchUser, Option option) { + redisMatchTimeRepository.addMatchUser(startTime, matchUser); + redisMatchTimeRepository.setMatchTimeWithExpiry(startTime); + redisMatchUserRepository.addMatchTime(matchUser.getUserId(), startTime, option); + } + + private void cancelEnrolledSlots(List players, LocalDateTime targetTIme) { + for (RedisMatchUser player : players) { + Set matchTimes = redisMatchUserRepository + .getAllMatchTime(player.getUserId()) + .stream() + .filter( + ele -> !ele.getStartTime().equals(targetTIme)) + .collect(Collectors.toSet()); + matchTimes.forEach(ele -> redisMatchTimeRepository.deleteMatchUser(ele.getStartTime(), player)); + redisMatchUserRepository.deleteMatchUser(player.getUserId()); + } + } + + private void deleteUserFromQueue(UserDto userDto, LocalDateTime startTime) { + if (redisMatchUserRepository.getUserTime(userDto.getId(), startTime).isEmpty()) { + throw new SlotNotFoundException(); + } + redisMatchUserRepository.deleteMatchTime(userDto.getId(), startTime); + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); + for (RedisMatchUser matchUser : allMatchUsers) { + if (matchUser.getUserId().equals(userDto.getId())) { + redisMatchTimeRepository.deleteMatchUser(startTime, matchUser); + break; + } + } + } + + /** + * LIVE, BEFORE ์ƒํƒœ์ธ ํ† ๋„ˆ๋จผํŠธ์™€ ์ง„ํ–‰ ์‹œ๊ฐ„์ด ๊ฒน์น˜์ง€ ์•Š์œผ๋ฉด true, ๊ฒน์น˜๋ฉด false + * @param startTime ํ˜„์žฌ ์‹œ๊ฐ„ + * @return ์ข…๋ฃŒ๋˜์ง€ ์•Š์€ ํ† ๋„ˆ๋จผํŠธ ์žˆ์œผ๋ฉด true, ์—†์œผ๋ฉด false + * @throws SlotNotFoundException ํ˜„์žฌ ์‹œ๊ฐ„์— ํ•ด๋‹นํ•˜๋Š” ์Šฌ๋กฏ์ด ์—†์„ ๊ฒฝ์šฐ + */ + private boolean isExistTournamentNotEnded(LocalDateTime startTime) { + List tournamentList = tournamentRepository.findAllByStatusIsNot(TournamentStatus.END); + int gameInterval = slotManagementRepository.findCurrent(startTime) + .orElseThrow(SlotNotFoundException::new) + .getGameInterval(); + LocalDateTime endTime = startTime.plusMinutes(gameInterval); + for (Tournament tournament : tournamentList) { + if (startTime.isAfter(tournament.getStartTime()) && startTime.isBefore(tournament.getEndTime()) + || endTime.isAfter(tournament.getStartTime()) && endTime.isBefore(tournament.getEndTime())) { + return true; + } + if (startTime.isEqual(tournament.getStartTime()) || endTime.isEqual(tournament.getEndTime()) + || endTime.isEqual(tournament.getStartTime()) || startTime.isEqual(tournament.getEndTime())) { + return true; + } + } + return false; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchTournamentService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchTournamentService.java new file mode 100644 index 000000000..1b03f19b5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/service/MatchTournamentService.java @@ -0,0 +1,287 @@ +package gg.pingpong.api.user.match.service; + +import static gg.data.match.type.TournamentMatchStatus.*; +import static gg.data.tournament.type.RoundNumber.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; + +import javax.transaction.Transactional; + +import org.springframework.stereotype.Service; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.match.type.TournamentMatchStatus; +import gg.data.noti.type.NotiType; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.RoundNumber; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.utils.exception.match.EnrolledSlotException; +import gg.utils.exception.match.LosingTeamNotFoundException; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.match.WinningTeamNotFoundException; +import gg.utils.exception.tournament.TournamentGameNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MatchTournamentService { + private final TournamentGameRepository tournamentGameRepository; + private final GameRepository gameRepository; + private final SlotManagementRepository slotManagementRepository; + private final SeasonFindService seasonFindService; + private final NotiAdminService notiAdminService; + + /** + * ํ† ๋„ˆ๋จผํŠธ ์ง„ํ–‰์ค‘ ๋‹ค์Œ ๋ผ์šด๋“œ ๊ฒŒ์ž„ ๋งค์นญ์ด ํ•„์š”ํ•œ์ง€ ํ™•์ธ + *

๊ฒฐ์Šน์ „ ์ ์ˆ˜ ์ž…๋ ฅ ํ›„ ํ† ๋„ˆ๋จผํŠธ END ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธ

+ * @param game ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + * @return TournamentMatchStatus - ๋งค์นญ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ + * @throws TournamentGameNotFoundException ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public TournamentMatchStatus checkTournamentGame(Game game) { + TournamentGame tournamentGame = tournamentGameRepository.findByGameId(game.getId()) + .orElseThrow(TournamentGameNotFoundException::new); + + // ํ† ๋„ˆ๋จผํŠธ ๊ฒฐ์Šน์ „ ๊ฒŒ์ž„์ผ ๊ฒฝ์šฐ, ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ END๋กœ ๋ณ€๊ฒฝ + if (TournamentRound.THE_FINAL.equals(tournamentGame.getTournamentRound())) { + closeTournament(tournamentGame.getTournament(), game); + return NO_MORE_MATCHES; + } + + // ๊ฐ™์€ round์˜ ๋ชจ๋“  ๊ฒŒ์ž„์ด END์ธ ๊ฒฝ์šฐ, ๋‹ค์Œ round์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋งค์นญ ๊ฐ€๋Šฅ + TournamentRound round = tournamentGame.getTournamentRound(); + List tournamentGames = tournamentGameRepository.findAllByTournamentId( + tournamentGame.getTournament().getId()); + List sameRoundGames = tournamentGames.stream() + .filter(tg -> tg.getTournamentRound().getRoundNumber() == round.getRoundNumber()) + .collect(Collectors.toList()); + for (TournamentGame tg : sameRoundGames) { + if (!StatusType.END.equals(tg.getGame().getStatus())) { + return UNNECESSARY; + } + } + if (isAlreadyExistMatchedGame(tournamentGame.getTournament(), round.getNextRound().getRoundNumber())) { + return ALREADY_MATCHED; + } + return REQUIRED; + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋งค์นญ + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ์ƒˆ๋กœ ๋งค์นญํ•  ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ + * @throws EnrolledSlotException ์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ + * @throws SlotNotFoundException ์Šฌ๋กฏ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public void matchGames(Tournament tournament, RoundNumber roundNumber) { + if (isAlreadyExistMatchedGame(tournament, roundNumber)) { + throw new EnrolledSlotException(); + } + Season season = seasonFindService.findCurrentSeason(tournament.getStartTime()); + SlotManagement slotManagement = slotManagementRepository.findCurrent(tournament.getStartTime()) + .orElseThrow(SlotNotFoundException::new); + int gameInterval = slotManagement.getGameInterval(); + List allTournamentGames = tournamentGameRepository.findAllByTournamentId(tournament.getId()); + List tournamentGames = findSameRoundGames(allTournamentGames, roundNumber); + List players = findSortedPlayers(tournament, roundNumber); + LocalDateTime startTime = calculateStartTime(tournament, roundNumber, gameInterval); + + for (int i = 0; i < tournamentGames.size(); ++i) { + Game game = new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, startTime, + startTime.plusMinutes(gameInterval)); + Team team1 = new Team(game, -1, false); + Team team2 = new Team(game, -1, false); + User user1 = players.get(i * 2); + User user2 = players.get(i * 2 + 1); + new TeamUser(team1, user1); + new TeamUser(team2, user2); + gameRepository.save(game); + tournamentGames.get(i).updateGame(game); + startTime = startTime.plusMinutes((long)gameInterval); + } + players.stream().distinct() + .forEach(user -> notiAdminService.sendAnnounceNotiToUser( + new SendNotiAdminRequestDto(user.getIntraId(), NotiType.TOURNAMENT_GAME_MATCHED.getMessage()))); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์˜ ์Šน์ž๋ฅผ ํ† ๋„ˆ๋จผํŠธ ๋‹ค์Œ ๋ผ์šด๋“œ์˜ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด์–ด๋กœ ์—…๋ฐ์ดํŠธ + * @param modifiedGame ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ๊ฐ€ ์ˆ˜์ •๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + * @param nextMatchedGame ์ˆ˜์ •๋œ ์šฐ์Šน์ž๋กœ ์ˆ˜์ •ํ•  ๋‹ค์Œ ๊ฒŒ์ž„ + * @throws WinningTeamNotFoundException ์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + * @throws LosingTeamNotFoundException ํŒจ์žํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public void updateMatchedGameUser(Game modifiedGame, Game nextMatchedGame) { + User winner = getWinningTeam(modifiedGame).getTeamUsers().get(0).getUser(); + User loser = getLosingTeam(modifiedGame).getTeamUsers().get(0).getUser(); + List players = modifiedGame.getTeams().stream() + .map(team -> team.getTeamUsers().get(0).getUser()) + .collect(Collectors.toList()); + List nextMatchedGameTeamUsers = nextMatchedGame.getTeams().stream() + .map(team -> team.getTeamUsers().get(0)) + .collect(Collectors.toList()); + for (TeamUser nextGameTeamUser : nextMatchedGameTeamUsers) { + if (players.contains(nextGameTeamUser.getUser())) { + nextGameTeamUser.updateUser(winner); + break; + } + } + notiAdminService.sendAnnounceNotiToUser( + new SendNotiAdminRequestDto(winner.getIntraId(), NotiType.TOURNAMENT_GAME_MATCHED.getMessage())); + notiAdminService.sendAnnounceNotiToUser( + new SendNotiAdminRequestDto(loser.getIntraId(), NotiType.TOURNAMENT_GAME_CANCELED.getMessage())); + } + + /** + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ + * @param gameInterval ๊ฒฝ๊ธฐ ๊ฐ„๊ฒฉ + * @return ๋งˆ์ง€๋ง‰ ๊ฒฝ๊ธฐ ์ข…๋ฃŒ ์‹œ๊ฐ„ + interval + *

8๊ฐ•์˜ ๊ฒฝ์šฐ ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„

+ *

4๊ฐ•, ๊ฒฐ์Šน์ผ ๊ฒฝ์šฐ ์ด์ „ ๋ผ์šด๋“œ์˜ ๋งˆ์ง€๋ง‰ ๊ฒฝ๊ธฐ ์ข…๋ฃŒ ์‹œ๊ฐ„ + 15๋ถ„

+ */ + private LocalDateTime calculateStartTime(Tournament tournament, RoundNumber roundNumber, int gameInterval) { + if (QUARTER_FINAL == roundNumber) { + return tournament.getStartTime(); + } + List previousRoundTournamentGames = findSameRoundGames(tournament.getTournamentGames(), + TournamentRound.getPreviousRoundNumber(roundNumber)); + TournamentGame lastGame = previousRoundTournamentGames.get(previousRoundTournamentGames.size() - 1); + return lastGame.getGame().getEndTime().plusMinutes(gameInterval); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ์— ๋งค์นญ๋  ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์ฐพ๋Š”๋‹ค. + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ๋งค์นญํ•  ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ + * @return ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ์— ๋งค์นญ๋  ํ”Œ๋ ˆ์ด์–ด List (์ •๋ ฌ๋œ ์ƒํƒœ) + */ + private List findSortedPlayers(Tournament tournament, RoundNumber roundNumber) { + List players = new ArrayList<>(); + + if (QUARTER_FINAL == roundNumber) { + Map randomNumbers = new LinkedHashMap<>(); + Random random = new Random(); + while (randomNumbers.size() < Tournament.ALLOWED_JOINED_NUMBER) { + int randomNumber = random.nextInt(Tournament.ALLOWED_JOINED_NUMBER); + if (!randomNumbers.containsValue(randomNumber)) { + randomNumbers.put(randomNumbers.size(), randomNumber); + } + } + for (Integer randomNumber : randomNumbers.values()) { + List tournamentUsers = tournament.getTournamentUsers(); + User user = tournamentUsers.get(randomNumber).getUser(); + players.add(user); + } + } else { + List previousRoundTournamentGames = findSameRoundGames(tournament.getTournamentGames(), + TournamentRound.getPreviousRoundNumber(roundNumber)); + int roundNum = roundNumber.getRound(); + for (int i = 0; i < roundNum; ++i) { + User user = getWinningTeam(previousRoundTournamentGames.get(i).getGame()) + .getTeamUsers().get(0).getUser(); + players.add(user); + } + } + return players; + } + + /** + * round์— ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ + * @return true - ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌ, false - ์•„์ง ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ + * @throws TournamentGameNotFoundException ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + private boolean isAlreadyExistMatchedGame(Tournament tournament, RoundNumber roundNumber) { + List sameRounds = TournamentRound.getSameRounds(roundNumber); + List tournamentGames = tournamentGameRepository.findByTournamentIdAndTournamentRoundIn( + tournament.getId(), sameRounds); + for (TournamentGame tournamentGame : tournamentGames) { + if (tournamentGame.getGame() != null) { + return true; + } + } + return false; + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ํ•จ์ˆ˜ + *

ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ END๋กœ ์—…๋ฐ์ดํŠธ

+ *

ํ† ๋„ˆ๋จผํŠธ winner ์—…๋ฐ์ดํŠธ

+ * @param tournament ์ข…๋ฃŒํ•  ํ† ๋„ˆ๋จผํŠธ + * @param finalGame ํ† ๋„ˆ๋จผํŠธ์˜ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„ + * @throws WinningTeamNotFoundException ์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + private void closeTournament(Tournament tournament, Game finalGame) { + User winner = getWinningTeam(finalGame) + .getTeamUsers().get(0).getUser(); + tournament.updateStatus(TournamentStatus.END); + tournament.updateEndTime(finalGame.getEndTime()); + tournament.updateWinner(winner); + + } + + /** + * ๊ฐ™์€ round์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ฐพ๋Š”๋‹ค. + * @param tournamentGames ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ List + * @param roundNum ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ number (2, 4, 8, ...) (์ž˜๋ชป๋œ roundNum์ผ ๊ฒฝ์šฐ Empty List ๋ฐ˜ํ™˜ํ•œ๋‹ค.) + * @return tournamentGames ์ค‘ roundNum๊ณผ ๋™์ผํ•œ roundNum์„ ๊ฐ€์ง„ round ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ tournamentGame List ๋ฐ˜ํ™˜ + */ + private List findSameRoundGames(List tournamentGames, RoundNumber roundNum) { + return tournamentGames.stream() + .filter(tournamentGame -> roundNum == tournamentGame.getTournamentRound().getRoundNumber()) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + } + + /** + * game์˜ ์Šน์ž๋ฅผ ์ฐพ๋Š”๋‹ค. + * @param game + * @return + */ + private Team getWinningTeam(Game game) { + return game.getTeams().stream() + .filter(team -> Boolean.TRUE.equals(team.getWin())) + .findAny() + .orElseThrow(WinningTeamNotFoundException::new); + } + + /** + * game์˜ ํŒจ์ž๋ฅผ ์ฐพ๋Š”๋‹ค. + * @param game + * @return + */ + private Team getLosingTeam(Game game) { + return game.getTeams().stream() + .filter(team -> Boolean.FALSE.equals(team.getWin())) + .findAny() + .orElseThrow(LosingTeamNotFoundException::new); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/MatchCalculator.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/MatchCalculator.java new file mode 100644 index 000000000..413bb987e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/MatchCalculator.java @@ -0,0 +1,92 @@ +package gg.pingpong.api.user.match.utils; + +import java.util.List; +import java.util.Optional; + +import gg.data.match.RedisMatchUser; +import gg.data.match.type.Option; +import gg.data.match.type.SlotStatus; + +public class MatchCalculator { + private final Integer pppGap; + private final RedisMatchUser matchUser; + + public MatchCalculator(Integer pppGap, RedisMatchUser matchUser) { + this.pppGap = pppGap; + this.matchUser = matchUser; + } + + /**์œ ์ €๋“ค์ด ์ž…์žฅํ•  ๋•Œ๋งˆ๋‹ค Queue ๋งค์นญ ๊ฒ€์‚ฌ + * ๋งˆ์ง€๋ง‰์œผ๋กœ ์ž…์žฅํ•œ ์œ ์ €๋ž‘ ๊ทธ์ „ ์œ ์ €๋“ค๋งŒ ๋น„๊ตํ•˜๋ฉด ๋œ๋‹ค. + * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ both : normal ์ž…์žฅ ์œ ์ €์™€ ๊ฒฝ๊ธฐ ๊ฐ€๋Šฅํ•œ rank ์ž…์žฅ ์œ ์ € ๋งค์นญ + * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ normal : normal user ํƒ์ƒ‰ + * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ rank : ๊ฒฝ๊ธฐ ๊ฐ€๋Šฅํ•œ rank ์ž…์žฅ ์œ ์ € ๋งค์นญ + * ์ด๋•Œ ํƒ์ƒ‰ ์šฐ์„  ์œ„๋Š” ๋จผ์ € ๋“ค์–ด์˜จ ์‚ฌ๋žŒ๋ถ€ํ„ฐ**/ + public Optional findEnemy(List allMatchUsers) { + if (allMatchUsers.size() == 0) { + return Optional.empty(); + } + if (matchUser.getOption().equals(Option.NORMAL)) { + return allMatchUsers.stream() + .filter(player -> player.getOption().equals(Option.NORMAL) + || player.getOption().equals(Option.BOTH)) + .findFirst(); + } + if (matchUser.getOption().equals(Option.RANK)) { + return allMatchUsers.stream() + .filter(player -> (player.getOption().equals(Option.RANK) + || player.getOption().equals(Option.BOTH)) + && Math.abs(player.getPpp() - matchUser.getPpp()) <= pppGap) + .findFirst(); + } + return allMatchUsers.stream() + .filter(player -> player.getOption().equals(Option.NORMAL) + || player.getOption().equals(Option.BOTH) + || (player.getOption().equals(Option.RANK) + && Math.abs(player.getPpp() - matchUser.getPpp()) <= pppGap)) + .findFirst(); + } + + /** + * + * @param allMatchUsers : ํ์— ๋“ค์–ด์žˆ๋Š” ํ”Œ๋ ˆ์ด์–ด๋“ค + * @return 1) ๋งค์นญ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ: SlotStatus.MATCH + * 2) ๋งค์นญ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ: SlotStatus.OPEN + */ + public SlotStatus findEnemyStatus(List allMatchUsers) { + if (matchUser.getOption().equals(Option.NORMAL)) { + return getNormalSlotStatus(allMatchUsers); + } + if (matchUser.getOption().equals(Option.RANK)) { + return getRankSlotStatus(allMatchUsers); + } + return getBothSlotStatus(allMatchUsers); + } + + private SlotStatus getRankSlotStatus(List allMatchUsers) { + if (allMatchUsers.stream().anyMatch(e -> (e.getOption().equals(Option.RANK) + || e.getOption().equals(Option.BOTH)) && (e.getPpp() - matchUser.getPpp()) <= pppGap)) { + return SlotStatus.MATCH; + } + return SlotStatus.OPEN; + } + + private SlotStatus getNormalSlotStatus(List allMatchUsers) { + if (allMatchUsers.stream().anyMatch(e -> e.getOption().equals(Option.NORMAL) + || e.getOption().equals(Option.BOTH))) { + return SlotStatus.MATCH; + } + return SlotStatus.OPEN; + } + + private SlotStatus getBothSlotStatus(List allMatchUsers) { + if (allMatchUsers.stream().anyMatch(e -> + e.getOption().equals(Option.NORMAL) + || e.getOption().equals(Option.BOTH) + || (e.getOption().equals(Option.RANK) + && e.getPpp() - matchUser.getPpp() <= pppGap))) { + return SlotStatus.MATCH; + } + return SlotStatus.OPEN; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/SlotGenerator.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/SlotGenerator.java new file mode 100644 index 000000000..da68bcb16 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/match/utils/SlotGenerator.java @@ -0,0 +1,117 @@ +package gg.pingpong.api.user.match.utils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.manage.SlotManagement; +import gg.data.match.RedisMatchTime; +import gg.data.match.RedisMatchUser; +import gg.data.match.type.Option; +import gg.data.match.type.SlotStatus; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.pingpong.api.user.match.controller.response.SlotStatusResponseListDto; +import gg.pingpong.api.user.match.dto.SlotStatusDto; +import lombok.Getter; + +@Getter +public class SlotGenerator { + /** + * minTime ~ maxTime : ์Šฌ๋กฏ์ด ๋ณด์—ฌ์ง€๋Š” ์‹œ๊ฐ„ ๋ฒ”์œ„ + * matchUser : ํ˜„์žฌ ์œ ์ € ์ •๋ณด + * matchCalculator : ๋งค์นญ ๊ด€๋ จ ์Šฌ๋กฏ ์ƒํƒœ ๊ฒฐ์ • + * option : ์œ ์ €๊ฐ€ ํ˜„์žฌ ์„ ํƒํ•œ mode(random, normal, both) + */ + private final HashMap slots; + private final Integer interval; + private final LocalDateTime minTime; + private final LocalDateTime now; + private final LocalDateTime maxTime; + private final RedisMatchUser matchUser; + private final MatchCalculator matchCalculator; + private final Option option; + + public SlotGenerator(RankRedis user, SlotManagement slotManagement, Season season, Option option) { + this.interval = slotManagement.getGameInterval(); + this.now = LocalDateTime.now(); + this.minTime = LocalDateTime.of( + now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0) + .minusHours(slotManagement.getPastSlotTime()); + this.maxTime = setMaxTime(slotManagement); + this.option = option; + this.slots = new HashMap(); + this.matchUser = new RedisMatchUser(user.getUserId(), user.getPpp(), option); + this.matchCalculator = new MatchCalculator(season.getPppGap(), matchUser); + } + + public void addPastSlots() { + for (LocalDateTime time = minTime; time.isBefore(now); time = time.plusMinutes(interval)) { + slots.put(time, new SlotStatusDto(time, SlotStatus.CLOSE, interval)); + } + } + + public void addMatchedSlots(List games) { + games.stream().forEach(e -> slots.put(e.getStartTime(), + new SlotStatusDto(e.getStartTime(), SlotStatus.CLOSE, interval))); + } + + public void addMySlots(Game myGame) { + slots.put(myGame.getStartTime(), + new SlotStatusDto(myGame.getStartTime(), myGame.getEndTime(), + getMySlotStatus(myGame.getMode(), option))); + } + + public void addMySlots(Set allMatchTime) { + allMatchTime.stream().forEach(match -> slots.put(match.getStartTime(), + new SlotStatusDto(match.getStartTime(), + getMySlotStatus(match.getOption(), option), interval))); + } + + private SlotStatus getMySlotStatus(Option myOption, Option viewOption) { + if (myOption.equals(viewOption)) { + return SlotStatus.MYTABLE; + } + return SlotStatus.CLOSE; + } + + private SlotStatus getMySlotStatus(Mode myMode, Option viewOption) { + if (myMode.getCode().equals(viewOption.getCode())) { + return SlotStatus.MYTABLE; + } + return SlotStatus.CLOSE; + } + + public void groupEnrolledSlot(LocalDateTime startTime, List players) { + slots.put(startTime, new SlotStatusDto(startTime, matchCalculator.findEnemyStatus(players), interval)); + } + + public SlotStatusResponseListDto getResponseListDto() { + long slotCountPerHour = 60 / interval; + List> matchBoards = new ArrayList>(); + for (LocalDateTime time = minTime; time.isBefore(maxTime); time = time.plusHours(1)) { + List hourBoard = new ArrayList(); + for (long i = 0; i < slotCountPerHour; i++) { + SlotStatusDto dto = slots.getOrDefault(time.plusMinutes(i * interval), + new SlotStatusDto(time.plusMinutes(i * interval), SlotStatus.OPEN, interval)); + hourBoard.add(dto); + } + matchBoards.add(hourBoard); + } + return new SlotStatusResponseListDto(matchBoards); + } + + private LocalDateTime setMaxTime(SlotManagement slotManagement) { + LocalDateTime compared = LocalDateTime.of( + now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0) + .plusHours(slotManagement.getFutureSlotTime()); + if (slotManagement.getEndTime() != null && slotManagement.getEndTime().isBefore(compared)) { + return slotManagement.getEndTime(); + } + return compared; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/NotiController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/NotiController.java new file mode 100644 index 000000000..f964c11c6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/NotiController.java @@ -0,0 +1,42 @@ +package gg.pingpong.api.user.noti.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.noti.controller.response.NotiListResponseDto; +import gg.pingpong.api.user.noti.controller.response.NotiResponseDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import lombok.AllArgsConstructor; + +@RestController +@AllArgsConstructor +@RequestMapping(value = "/pingpong/notifications") +public class NotiController { + private final NotiService notiService; + + @GetMapping + public NotiListResponseDto notiFindByUser(@Login UserDto user) { + List notiResponseDtoList = notiService.findNotiByUser(user); + return new NotiListResponseDto(notiResponseDtoList); + } + + @PutMapping(value = "/check") + public ResponseEntity checkNotiByUser(@Login UserDto user) { + notiService.modifyNotiCheckedByUser(user); + return ResponseEntity.status(204).build(); + } + + @DeleteMapping + public ResponseEntity notiRemoveAll(@Login UserDto user) { + notiService.removeAllNotisByUser(user); + return ResponseEntity.status(204).build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/request/NotiFindByUserRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/request/NotiFindByUserRequestDto.java new file mode 100644 index 000000000..f63c6e490 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/request/NotiFindByUserRequestDto.java @@ -0,0 +1,4 @@ +package gg.pingpong.api.user.noti.controller.request; + +public class NotiFindByUserRequestDto { +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiFindByUserResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiFindByUserResponseDto.java new file mode 100644 index 000000000..143f7f6e9 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiFindByUserResponseDto.java @@ -0,0 +1,4 @@ +package gg.pingpong.api.user.noti.controller.response; + +public class NotiFindByUserResponseDto { +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiListResponseDto.java new file mode 100644 index 000000000..a0e76bc58 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiListResponseDto.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.user.noti.controller.response; + +import java.util.List; +import java.util.Objects; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class NotiListResponseDto { + private List notifications; + + @Override + public String toString() { + return "NotiResponseDto{" + + "notifications=" + notifications + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + NotiListResponseDto other = (NotiListResponseDto)obj; + return Objects.equals(notifications, other.notifications); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiResponseDto.java new file mode 100644 index 000000000..2f4a2efa6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/controller/response/NotiResponseDto.java @@ -0,0 +1,66 @@ +package gg.pingpong.api.user.noti.controller.response; + +import java.time.LocalDateTime; +import java.util.Objects; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class NotiResponseDto { + private Long id; + private NotiType type; + private Boolean isChecked; + private String message; + private LocalDateTime createdAt; + + public static NotiResponseDto from(Noti noti) { + NotiResponseDto notiResponseDto; + if (noti == null) { + notiResponseDto = null; + } else { + notiResponseDto = NotiResponseDto.builder() + .id(noti.getId()) + .type(noti.getType()) + .isChecked(noti.getIsChecked()) + .message(noti.getMessage()) + .createdAt(noti.getCreatedAt()) + .build(); + } + return notiResponseDto; + } + + @Override + public String toString() { + return "NotiDto{" + + "id=" + id + + ", type=" + type + + ", isChecked=" + isChecked + + ", message='" + message + '\'' + + ", createdDate=" + createdAt + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof NotiResponseDto)) { + return false; + } + NotiResponseDto other = (NotiResponseDto)obj; + return Objects.equals(id, other.id) + && Objects.equals(type, other.type) + && Objects.equals(isChecked, other.isChecked) + && Objects.equals(message, other.message) + && Objects.equals(createdAt, other.createdAt); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/NotiDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/NotiDto.java new file mode 100644 index 000000000..9d38ca674 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/NotiDto.java @@ -0,0 +1,67 @@ +package gg.pingpong.api.user.noti.dto; + +import java.time.LocalDateTime; +import java.util.Objects; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.pingpong.api.user.user.dto.UserDto; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class NotiDto { + private Long id; + private UserDto user; + private NotiType type; + private Boolean isChecked; + private String message; + private LocalDateTime createdAt; + + public static NotiDto from(Noti noti) { + NotiDto notiDto; + if (noti == null) { + notiDto = null; + } else { + notiDto = NotiDto.builder() + .id(noti.getId()) + .user(UserDto.from(noti.getUser())) + .type(noti.getType()) + .isChecked(noti.getIsChecked()) + .message(noti.getMessage()) + .createdAt(noti.getCreatedAt()) + .build(); + } + return notiDto; + } + + @Override + public String toString() { + return "NotiDto{" + + "id=" + id + + ", user=" + user + + ", type=" + type + + ", isChecked=" + isChecked + + ", message='" + message + '\'' + + ", createdDate=" + createdAt + + '}'; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof NotiDto)) { + return false; + } + NotiDto other = (NotiDto)obj; + return Objects.equals(id, other.id) + && Objects.equals(user, other.user) + && Objects.equals(type, other.type) + && Objects.equals(isChecked, other.isChecked) + && Objects.equals(message, other.message) + && Objects.equals(createdAt, other.createdAt); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/UserNotiDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/UserNotiDto.java new file mode 100644 index 000000000..bddb971de --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/dto/UserNotiDto.java @@ -0,0 +1,22 @@ +package gg.pingpong.api.user.noti.dto; + +import gg.data.user.type.SnsType; +import gg.repo.game.out.GameUser; +import lombok.Getter; + +@Getter +public class UserNotiDto { + private Long userId; + private Long gameId; + private String intraId; + private SnsType snsNotiOpt; + private String email; + + public UserNotiDto(GameUser gameUser) { + this.gameId = gameUser.getGameId(); + this.userId = gameUser.getUserId(); + this.intraId = gameUser.getIntraId(); + this.email = gameUser.getEmail(); + this.snsNotiOpt = gameUser.getSnsNotiOpt(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java new file mode 100644 index 000000000..94dce8928 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/NotiService.java @@ -0,0 +1,169 @@ +package gg.pingpong.api.user.noti.service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.pingpong.api.user.noti.controller.response.NotiResponseDto; +import gg.pingpong.api.user.noti.dto.NotiDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.noti.NotiRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.AllArgsConstructor; + +@Service +@AllArgsConstructor +public class NotiService { + private final NotiRepository notiRepository; + private final UserRepository userRepository; + private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); + + /** + * UserDto๋ฅผ ์ด์šฉํ•˜์—ฌ User์˜ ์•Œ๋ฆผ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. + * @param userDto ์œ ์ € Dto + * @exception UserNotFoundException ์œ ์ €๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + * @return ์•Œ๋ฆผ ๋ชฉ๋ก + */ + @Transactional(readOnly = true) + public List findNotiByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + List notiList = notiRepository.findAllByUserOrderByIdDesc(user); + List notiResponseDtoList = notiList.stream() + .map(NotiResponseDto::from) + .collect(Collectors.toList()); + return notiResponseDtoList; + } + + /** + * UserDto์™€ notiId๋ฅผ ์ด์šฉํ•˜์—ฌ User์˜ ์•Œ๋ฆผ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. + * @param userDto ์œ ์ € Dto + * @param notiId ์•Œ๋ฆผ Id + * @exception UserNotFoundException ์œ ์ €๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + * @return ์•Œ๋ฆผ ๋ชฉ๋ก + */ + @Transactional + public NotiDto findNotiByIdAndUser(UserDto userDto, Long notiId) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + Noti noti = notiRepository.findByIdAndUser(notiId, user) + .orElseThrow(() -> new NotExistException("์š”์ฒญํ•œ ์•Œ๋ฆผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.NOT_FOUND)); + return NotiDto.from(noti); + } + + /** + * ์•Œ๋ฆผ์„ ์ฝ์Œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + * @param userDto ์œ ์ € Dto + * @exception UserNotFoundException ์œ ์ €๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public void modifyNotiCheckedByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + List notis = notiRepository.findAllByUser(user); + notis.forEach(noti -> { + noti.modifyIsChecked(true); + }); + } + + /** + * ์•Œ๋ฆผ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. + * @param notiId ์•Œ๋ฆผ Id + */ + @Transactional + public void removeNotiById(Long notiId) { + notiRepository.deleteById(notiId); + } + + /** + * ์•Œ๋ฆผ ๋ชฉ๋ก ์ „์ฒด๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. + * @param userDto ์œ ์ € Dto + * @exception UserNotFoundException ์œ ์ €๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ + */ + @Transactional + public void removeAllNotisByUser(UserDto userDto) { + User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); + notiRepository.deleteAllByUser(user); + } + + /** + * ๋งค์นญ ์„ฑ์‚ฌ ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + * @param user ์œ ์ € + * @param startTime ๊ฒฝ๊ธฐ ์‹œ์ž‘ ์‹œ๊ฐ„ + * @return ๋งค์นญ ์„ฑ์‚ฌ ์•Œ๋ฆผ + */ + @Transactional + public Noti createMatched(User user, LocalDateTime startTime) { + String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; + Noti noti = new Noti(user, NotiType.MATCHED, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + /** + * ๋งค์นญ ์ทจ์†Œ ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + * @param user ์œ ์ € + * @param startTime ๊ฒฝ๊ธฐ ์‹œ์ž‘ ์‹œ๊ฐ„ + * @return ๋งค์นญ ์ทจ์†Œ ์•Œ๋ฆผ + */ + @Transactional + public Noti createMatchCancel(User user, LocalDateTime startTime) { + String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์ƒ๋Œ€์— ์˜ํ•ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; + Noti noti = new Noti(user, NotiType.CANCELEDBYMAN, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + /** + * ์•„์ดํ…œ ์„ ๋ฌผ ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + * @param ownerUser ์„ ๋ฌผ ๋ฐ›์€ ์œ ์ € + * @param payUser ์„ ๋ฌผํ•œ ์œ ์ € + * @param itemName ์•„์ดํ…œ ์ด๋ฆ„ + * @return ์•„์ดํ…œ ์„ ๋ฌผ ์•Œ๋ฆผ + */ + @Transactional + public Noti createGiftNoti(User ownerUser, User payUser, String itemName) { + String notiMessage = "เฌ˜(เฉญหŠแต•ห‹)เฉญ* เฉˆโœฉ " + payUser.getIntraId() + "๋‹˜์—๊ฒŒ " + itemName + " ์•„์ดํ…œ์„ ์„ ๋ฌผ๋ฐ›์•˜์–ด์š”!"; + Noti noti = new Noti(ownerUser, NotiType.GIFT, notiMessage, false); + notiRepository.save(noti); + return noti; + } + + /** + * ๊ฒฝ๊ธฐ ์ž„๋ฐ• ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + * @param user ์œ ์ € + * @param enemyIntra ์ƒ๋Œ€ํŒ€ ์ธํŠธ๋ผ ์•„์ด๋”” + * @param notiType ์•Œ๋ฆผ ํƒ€์ž… + * @param gameOpenMinute ๊ฒŒ์ž„ ์‹œ๊ฐ„ + * @return ๊ฒฝ๊ธฐ ์ž„๋ฐ• ์•Œ๋ฆผ + */ + public Noti createImminentNoti(User user, String enemyIntra, NotiType notiType, Integer gameOpenMinute) { + String msg = "๋‹˜๊ณผ ๊ฒฝ๊ธฐ " + gameOpenMinute + "๋ถ„ ์ „ ์ž…๋‹ˆ๋‹ค. ์„œ๋‘๋ฅด์„ธ์š”!"; + return notiRepository.save(new Noti(user, notiType, msg, false)); + } + + /** + * ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. + * @param noti ์•Œ๋ฆผ + * @return ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€ + */ + public String getMessage(Noti noti) { + String message; + if (noti.getType() != NotiType.ANNOUNCE) { + message = + "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; + } else { + message = "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n๊ณต์ง€์‚ฌํ•ญ: " + + noti.getMessage() + "\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; + } + return message; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/SnsNotiService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/SnsNotiService.java new file mode 100644 index 000000000..656a9958f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/SnsNotiService.java @@ -0,0 +1,70 @@ +package gg.pingpong.api.user.noti.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.noti.Noti; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.sns.NotiMailSender; +import gg.pingpong.api.user.noti.service.sns.SlackbotService; +import gg.pingpong.api.user.user.dto.UserDto; +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class SnsNotiService { + private final NotiMailSender notiMailSender; + private final SlackbotService slackbotService; + + public SnsNotiService(NotiMailSender notiMailSender, SlackbotService slackbotService) { + this.notiMailSender = notiMailSender; + this.slackbotService = slackbotService; + } + + /** + * ์œ ์ €๊ฐ€ ์„ค์ •ํ•ด๋‘” ์•Œ๋ฆผ ์˜ต์…˜(email, slack, both, none)์— ๋”ฐ๋ผ ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + * UserNotiDto ์ด์šฉ + * @param noti ์•Œ๋ฆผ + * @param user ์œ ์ € + */ + @Transactional(readOnly = true) + public void sendSnsNotification(Noti noti, UserNotiDto user) { + log.info("Send Sns Noti"); + SnsType userSnsNotiOpt = user.getSnsNotiOpt(); + if (userSnsNotiOpt == SnsType.NONE) { + return; + } + if (userSnsNotiOpt == SnsType.EMAIL) { + notiMailSender.send(user, noti); + } else if (userSnsNotiOpt == SnsType.SLACK) { + slackbotService.send(user, noti); + } else if (userSnsNotiOpt == SnsType.BOTH) { + notiMailSender.send(user, noti); + slackbotService.send(user, noti); + } + } + + /** + * ์œ ์ €๊ฐ€ ์„ค์ •ํ•ด๋‘” ์•Œ๋ฆผ ์˜ต์…˜(email, slack, both, none)์— ๋”ฐ๋ผ ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + * UserDto ์ด์šฉ + * @param noti ์•Œ๋ฆผ + * @param user ์œ ์ € + */ + @Transactional(readOnly = true) + public void sendSnsNotification(Noti noti, UserDto user) { + log.info("Send Sns Noti"); + SnsType userSnsNotiOpt = user.getSnsNotiOpt(); + if (userSnsNotiOpt == SnsType.NONE) { + return; + } + if (userSnsNotiOpt == SnsType.EMAIL) { + notiMailSender.send(user, noti); + } else if (userSnsNotiOpt == SnsType.SLACK) { + slackbotService.send(user, noti); + } else if (userSnsNotiOpt == SnsType.BOTH) { + notiMailSender.send(user, noti); + slackbotService.send(user, noti); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/NotiMailSender.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/NotiMailSender.java new file mode 100644 index 000000000..970a1cff6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/NotiMailSender.java @@ -0,0 +1,67 @@ +package gg.pingpong.api.user.noti.service.sns; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; + +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import gg.data.noti.Noti; +import gg.pingpong.api.global.utils.AsyncMailSender; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@RequiredArgsConstructor +@Slf4j +public class NotiMailSender { + private final JavaMailSender javaMailSender; + private final AsyncMailSender asyncMailSender; + private final NotiService notiService; + + /** + * ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + * UserNotiDto ์ด์šฉ + * @param user ์œ ์ € + * @param noti ์•Œ๋ฆผ + */ + public void send(UserNotiDto user, Noti noti) { + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message); + try { + helper.setSubject("ํ•‘ํ์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ๋„์ฐฉํ•œ ํŽธ์ง€"); + log.info(user.getEmail()); + helper.setTo(user.getEmail()); + helper.setText(notiService.getMessage(noti)); + } catch (MessagingException e) { + log.error("MessagingException message = {}", e.getMessage()); + } + log.info("Email send {}", user.getUserId()); + asyncMailSender.send(message); + } + + /** + * ์•Œ๋ฆผ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. + * UserDto ์ด์šฉ + * @param user ์œ ์ € + * @param noti ์•Œ๋ฆผ + */ + public void send(UserDto user, Noti noti) { + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message); + try { + helper.setSubject("ํ•‘ํ์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ๋„์ฐฉํ•œ ํŽธ์ง€"); + log.info(user.getEMail()); + helper.setTo(user.getEMail()); + helper.setText(notiService.getMessage(noti)); + } catch (MessagingException e) { + log.error("MessagingException message = {}", e.getMessage()); + } + log.info("Email send {}", user.getId()); + asyncMailSender.send(message); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotService.java new file mode 100644 index 000000000..f645b9d4b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotService.java @@ -0,0 +1,124 @@ +package gg.pingpong.api.user.noti.service.sns; + +import static gg.pingpong.api.user.noti.service.sns.SlackbotUtils.*; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import gg.data.noti.Noti; +import gg.pingpong.api.global.utils.external.ApiUtil; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.exception.noti.SlackSendException; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +@RequiredArgsConstructor +public class SlackbotService { + @Value("${slack.xoxbToken}") + private String authenticationToken; + + private final NotiService notiService; + private final ApiUtil apiUtil; + + private String getSlackUserId(String intraId) { + String userEmail = intraId + intraEmailSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.add(HttpHeaders.AUTHORIZATION, authenticationPrefix + authenticationToken); + + MultiValueMap parameters = new LinkedMultiValueMap<>(); + parameters.add("email", userEmail); + + SlackUserInfoResponse res = apiUtil.apiCall(userIdGetUrl, SlackUserInfoResponse.class, + headers, parameters, HttpMethod.POST); + return res.user.id; + } + + private String getDmChannelId(String slackUserId) { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(HttpHeaders.AUTHORIZATION, + authenticationPrefix + authenticationToken); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + + Map bodyMap = new HashMap<>(); + bodyMap.put("users", slackUserId); + + ConversationResponse res = apiUtil.apiCall(conversationsUrl, ConversationResponse.class, + httpHeaders, bodyMap, HttpMethod.POST); + + return res.channel.id; + } + + @Async("asyncExecutor") + public void send(UserNotiDto user, Noti noti) { + log.info("slack alarm send"); + try { + startSendNoti(user.getIntraId(), noti); + } catch (SlackSendException e) { + log.error("SlackSendException message = {}", e.getMessage()); + } + } + + @Async("asyncExecutor") + public void send(UserDto user, Noti noti) { + log.info("slack alarm send"); + try { + startSendNoti(user.getIntraId(), noti); + } catch (SlackSendException e) { + log.error("SlackSendException message = {}", e.getMessage()); + } + } + + private void startSendNoti(String intraId, Noti noti) { + String slackUserId = getSlackUserId(intraId); + String slackChannelId = getDmChannelId(slackUserId); + String message = notiService.getMessage(noti); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(HttpHeaders.AUTHORIZATION, + authenticationPrefix + authenticationToken); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + + Map map = new HashMap<>(); + map.put("channel", slackChannelId); + map.put("text", message); + apiUtil.apiCall(sendMessageUrl, String.class, httpHeaders, map, HttpMethod.POST); + } + + @Getter + static class ConversationResponse { + private Boolean ok; + private Channel channel; + + @Getter + static class Channel { + private String id; + } + + } + + @Getter + static class SlackUserInfoResponse { + private Boolean ok; + private SlackUser user; + + @Getter + static class SlackUser { + private String id; + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotUtils.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotUtils.java new file mode 100644 index 000000000..2a271eac5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/noti/service/sns/SlackbotUtils.java @@ -0,0 +1,9 @@ +package gg.pingpong.api.user.noti.service.sns; + +public class SlackbotUtils { + public static String conversationsUrl = "https://slack.com/api/conversations.open"; + public static String sendMessageUrl = "https://slack.com/api/chat.postMessage"; + public static String userIdGetUrl = "https://slack.com/api/users.lookupByEmail"; + public static String authenticationPrefix = "Bearer "; + public static String intraEmailSuffix = "@student.42seoul.kr"; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankController.java new file mode 100644 index 000000000..825c3b5e4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankController.java @@ -0,0 +1,51 @@ +package gg.pingpong.api.user.rank.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.rank.service.RankService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong") +public class RankController { + + private final RankService rankService; + + @GetMapping("/exp") + public ExpRankPageResponseDto getExpRankPage(@Valid PageRequestDto pageRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("totalExp").descending().and(Sort.by("intraId"))); + return rankService.getExpRankPageByRedis(pageRequest, user); + } + + /** + * + * @param pageRequestDto + * @param user + * @param season + * @param gameType + * + * gameType๋Š” single๋กœ ๊ณ ์ •๋˜์–ด ์˜ค๊ณ ์žˆ๋Š”๋ฐ ํ˜„์žฌ rank๊ฒŒ์ž„์€ single๋งŒ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด์„œ ์‚ฌ์šฉ ์•ˆํ•˜๊ธฐ๋กœ + */ + @GetMapping("/ranks/{gameType}") + public RankPageResponseDto getRankPage(@Valid PageRequestDto pageRequestDto, + @Parameter(hidden = true) @Login UserDto user, + Long season, String gameType) { + PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize()); + return rankService.getRankPage(pageRequest, user, season); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankV2Controller.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankV2Controller.java new file mode 100644 index 000000000..c625edb4c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/RankV2Controller.java @@ -0,0 +1,52 @@ +package gg.pingpong.api.user.rank.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.rank.service.RankService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/v2") +public class RankV2Controller { + private final RankService rankService; + + @GetMapping("/exp") + public ExpRankPageResponseDto getExpRankPage(@Valid PageRequestDto pageRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), + Sort.by("totalExp").descending().and(Sort.by("intraId"))); + return rankService.getExpRankPage(pageRequest, user); + } + + /** + * + * @param pageRequestDto + * @param user + * @param season + * @param gameType + * + * gameType๋Š” single๋กœ ๊ณ ์ •๋˜์–ด ์˜ค๊ณ ์žˆ๋Š”๋ฐ ํ˜„์žฌ rank๊ฒŒ์ž„์€ single๋งŒ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด์„œ ์‚ฌ์šฉ ์•ˆํ•˜๊ธฐ๋กœ + */ + @GetMapping("/ranks/{gameType}") + public RankPageResponseDto getRankPage(@Valid PageRequestDto pageRequestDto, + @Parameter(hidden = true) @Login UserDto user, + @RequestParam Long season, @PathVariable String gameType) { + PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize()); + return rankService.getRankPageV2(pageRequest, user, season); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/ExpRankPageResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/ExpRankPageResponseDto.java new file mode 100644 index 000000000..8920edb3d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/ExpRankPageResponseDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.rank.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.rank.dto.ExpRankDto; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ExpRankPageResponseDto { + private int myRank; + private int currentPage; + private int totalPage; + private List rankList; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/RankPageResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/RankPageResponseDto.java new file mode 100644 index 000000000..cd5b7956e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/controller/response/RankPageResponseDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.user.rank.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.rank.dto.RankDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class RankPageResponseDto { + private int myRank; + private int currentPage; + private int totalPage; + private List rankList; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/ExpRankDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/ExpRankDto.java new file mode 100644 index 000000000..9d3131860 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/ExpRankDto.java @@ -0,0 +1,49 @@ +package gg.pingpong.api.user.rank.dto; + +import gg.data.user.User; +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import gg.repo.user.ExpRankV2Dto; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ExpRankDto { + private String intraId; + private Integer rank; + private String statusMessage; + private Integer level; + private Integer exp; + private String userImageUri; + private String textColor; + + public static ExpRankDto from(User user, Integer rank, String statusMessage) { + ExpRankDto dto = ExpRankDto.builder() + .intraId(user.getIntraId()) + .rank(user.getTotalExp() == 0 ? -1 : rank) + .statusMessage(statusMessage) + .level(ExpLevelCalculator.getLevel(user.getTotalExp())) + .exp(user.getTotalExp()) + .userImageUri(user.getImageUri()) + .textColor(user.getTextColor()) + .build(); + return dto; + } + + public static ExpRankDto from(ExpRankV2Dto dto) { + return ExpRankDto.builder() + .intraId(dto.getIntraId()) + .rank(dto.getRanking()) + .statusMessage(dto.getStatusMessage()) + .level(ExpLevelCalculator.getLevel(dto.getTotalExp())) + .exp(dto.getTotalExp()) + .userImageUri(dto.getImageUri()) + .textColor(dto.getTextColor()) + .build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/RankDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/RankDto.java new file mode 100644 index 000000000..ca045c620 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/dto/RankDto.java @@ -0,0 +1,45 @@ +package gg.pingpong.api.user.rank.dto; + +import gg.data.rank.redis.RankRedis; +import gg.data.user.User; +import gg.repo.rank.RankV2Dto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class RankDto { + private String intraId; + private int rank; + private int ppp; + private String statusMessage; + private String tierImageUri; + private String textColor; + + public static RankDto from(User user, RankRedis rankRedis, Integer rank) { + RankDto dto = RankDto.builder() + .intraId(user.getIntraId()) + .rank(rank) + .ppp(rankRedis.getPpp()) + .statusMessage(rankRedis.getStatusMessage()) + .tierImageUri(rankRedis.getTierImageUri()) + .textColor(user.getTextColor()) + .build(); + return dto; + } + + public static RankDto from(RankV2Dto dto) { + return RankDto.builder() + .intraId(dto.getIntraId()) + .rank(dto.getRanking()) + .ppp(dto.getPpp()) + .statusMessage(dto.getStatusMessage()) + .tierImageUri(dto.getTierImageUri()) + .textColor(dto.getTextColor()) + .build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RankRedisService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RankRedisService.java new file mode 100644 index 000000000..945a9d3e4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RankRedisService.java @@ -0,0 +1,174 @@ +package gg.pingpong.api.user.rank.redis; + +import java.util.List; + +import javax.persistence.EntityManager; + +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.TeamUser; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.pingpong.api.global.utils.EloRating; +import gg.pingpong.api.user.game.service.PChangeService; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; +import gg.utils.exception.rank.RankNotFoundException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@RequiredArgsConstructor +@Slf4j +public class RankRedisService { + private final RankRedisRepository rankRedisRepository; + private final TierRepository tierRepository; + private final PChangeService pChangeService; + private final RankRepository rankRepository; + private final SeasonFindService seasonFindService; + private final EntityManager entityManager; + + public Integer getUserPpp(Long userId, Long seasonId) { + String hashKey = RedisKeyManager.getHashKey(seasonId); + return rankRedisRepository.findRankByUserId(hashKey, userId).getPpp(); + } + + public void updateAdminRankData(TeamUser myTeamUser, TeamUser enemyTeamUser, Game game, RankRedis myTeam, + RankRedis enemyTeam) { + // ๋‹จ์‹ -> 2๋ช… ๊ธฐ์ค€ + String key = RedisKeyManager.getHashKey(game.getSeason().getId()); + String zsetKey = RedisKeyManager.getZSetKey(game.getSeason().getId()); + Integer myPPP = myTeam.getPpp(); + Integer enemyPPP = enemyTeam.getPpp(); + updatePPP(myTeamUser, myTeam, enemyTeamUser.getTeam().getScore(), myPPP, enemyPPP, game.getSeason().getId()); + updatePPP(enemyTeamUser, enemyTeam, myTeamUser.getTeam().getScore(), enemyPPP, myPPP, game.getSeason().getId()); + updateRankUser(key, zsetKey, myTeamUser.getUser().getId(), myTeam); + updateRankUser(key, zsetKey, enemyTeamUser.getUser().getId(), enemyTeam); + pChangeService.addPChange(game, myTeamUser.getUser(), myTeam.getPpp(), false); + pChangeService.addPChange(game, enemyTeamUser.getUser(), enemyTeam.getPpp(), false); + } + + public void updateRankRedis(TeamUser myTeamUser, TeamUser enemyTeamUser, Game game) { + // ๋‹จ์‹ -> 2๋ช… ๊ธฐ์ค€ + String key = RedisKeyManager.getHashKey(game.getSeason().getId()); + String zsetKey = RedisKeyManager.getZSetKey(game.getSeason().getId()); + RankRedis myTeam = rankRedisRepository.findRankByUserId(key, myTeamUser.getUser().getId()); + RankRedis enemyTeam = rankRedisRepository.findRankByUserId(key, enemyTeamUser.getUser().getId()); + Integer myPPP = myTeam.getPpp(); + Integer enemyPPP = enemyTeam.getPpp(); + updatePPP(myTeamUser, myTeam, enemyTeamUser.getTeam().getScore(), myPPP, enemyPPP, game.getSeason().getId()); + updatePPP(enemyTeamUser, enemyTeam, myTeamUser.getTeam().getScore(), enemyPPP, myPPP, game.getSeason().getId()); + updateRankUser(key, zsetKey, myTeamUser.getUser().getId(), myTeam); + updateRankUser(key, zsetKey, enemyTeamUser.getUser().getId(), enemyTeam); + pChangeService.addPChange(game, myTeamUser.getUser(), myTeam.getPpp(), true); + pChangeService.addPChange(game, enemyTeamUser.getUser(), enemyTeam.getPpp(), false); + } + + private void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { + rankRedisRepository.updateRankData(hashKey, userId, userRank); + rankRedisRepository.deleteFromZSet(zsetKey, userId); + rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); + } + + @Transactional + public void updatePPP(TeamUser teamuser, RankRedis myTeam, int enemyScore, Integer myPPP, Integer enemyPPP, + Long seasonId) { + // rank table ์ˆ˜์ • + Rank rank = rankRepository.findByUserIdAndSeasonId(myTeam.getUserId(), seasonId) + .orElseThrow(() -> new NotExistException("rank ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.NOT_FOUND)); + int win = teamuser.getTeam().getWin() ? rank.getWins() + 1 : rank.getWins(); + int losses = !teamuser.getTeam().getWin() ? rank.getLosses() + 1 : rank.getLosses(); + Integer changedPpp = EloRating.pppChange(myPPP, enemyPPP, + teamuser.getTeam().getWin(), + Math.abs(teamuser.getTeam().getScore() - enemyScore) == 2); + log.info("update before: intraId: " + teamuser.getUser().getIntraId() + ", win: db(" + rank.getWins() + + "), redis(" + myTeam.getWins() + "), losses: db(" + rank.getLosses() + + "), redis(" + myTeam.getLosses() + ")"); + rank.modifyUserRank(rank.getPpp() + changedPpp, win, losses); + myTeam.updateRank(changedPpp, + win, losses); + log.info("update after: intraId: " + teamuser.getUser().getIntraId() + ", win: db(" + rank.getWins() + + "), redis(" + myTeam.getWins() + "), losses: db(" + rank.getLosses() + + "), redis(" + myTeam.getLosses() + ")"); + } + + @Transactional + public void updateAllTier(Long gameId) { + // ์ „์ฒด ๋ ˆ๋””์Šค ๋žญํฌ ํ‹ฐ์–ด ์ƒˆ๋กœ๊ณ ์นจํ•˜๋Š” ๋กœ์ง + Season targetSeason = seasonFindService.findSeasonByGameId(gameId); + String key = RedisKeyManager.getHashKey(targetSeason.getId()); + String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); + List rankRedisList = rankRedisRepository.findAllRanksOrderByPppDesc(key); + Long totalRankPlayers = rankRepository.countRealRankPlayers(targetSeason.getId()); + List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); + + int top30percentPpp = rankRedisList.get((int)(totalRankPlayers * 0.3)).getPpp(); + int top10percentPpp = rankRedisList.get((int)(totalRankPlayers * 0.1)).getPpp(); + + for (int i = 0; i < rankRedisList.size(); i++) { + RankRedis rankRedis = rankRedisList.get(i); + if (rankRedis.getWins() == 0 && rankRedis.getLosses() == 0) { + rankRedis.updateTierImage(tierList.get(0).getImageUri()); + } else { + if (i < 3) { + rankRedis.updateTierImage(tierList.get(6).getImageUri()); + updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); + continue; + } + if (rankRedis.getPpp() < 970) { + // 970 ๋ฏธ๋งŒ + rankRedis.updateTierImage(tierList.get(1).getImageUri()); + } else if (rankRedis.getPpp() < 1010) { + // 970 ~ 1009 + rankRedis.updateTierImage(tierList.get(2).getImageUri()); + } else if (rankRedis.getPpp() < 1050) { + // 1010 ~ 1049 + rankRedis.updateTierImage(tierList.get(3).getImageUri()); + } else { + if ((rankRedis.getPpp() >= top30percentPpp) && (rankRedis.getPpp() < top10percentPpp)) { + // 1050 ์ด์ƒ, 30% ์ด์ƒ, 10% ๋ฏธ๋งŒ + rankRedis.updateTierImage(tierList.get(4).getImageUri()); + } else if (rankRedis.getPpp() >= top10percentPpp) { + // 1050 ์ด์ƒ, 10% ์ด์ƒ + rankRedis.updateTierImage(tierList.get(5).getImageUri()); + } else { + // 1050 ์ด์ƒ, 30% ๋ฏธ๋งŒ + rankRedis.updateTierImage(tierList.get(3).getImageUri()); + } + } + updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); + } + } + } + + @Transactional + public RankRedis rollbackRank(TeamUser teamUser, int ppp, Long seasonId) { + String hashkey = RedisKeyManager.getHashKey(seasonId); + RankRedis myTeam = rankRedisRepository.findRankByUserId(hashkey, teamUser.getUser().getId()); + Rank rank = rankRepository.findByUserIdAndSeasonId(myTeam.getUserId(), seasonId) + .orElseThrow(RankNotFoundException::new); + int win = teamUser.getTeam().getWin() ? rank.getWins() - 1 : rank.getWins(); + int losses = !teamUser.getTeam().getWin() ? rank.getLosses() - 1 : rank.getLosses(); + log.info("Before: userId: " + teamUser.getUser().getIntraId() + ", " + "ppp: rank(" + + rank.getPpp() + "), redis(" + myTeam.getPpp() + "), win: " + myTeam.getWins() + + ", losses: " + myTeam.getLosses()); + rank.modifyUserRank(ppp, win, losses); + myTeam.changedRank(ppp, win, losses); + updateRankUser(hashkey, RedisKeyManager.getZSetKey(seasonId), teamUser.getUser().getId(), myTeam); + entityManager.flush(); + log.info("After: userId: " + teamUser.getUser().getIntraId() + ", " + "ppp: rank(" + + rank.getPpp() + "), redis(" + myTeam.getPpp() + "), win: " + myTeam.getWins() + + ", losses: " + myTeam.getLosses()); + return myTeam; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RedisUploadService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RedisUploadService.java new file mode 100644 index 000000000..e494a6255 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/redis/RedisUploadService.java @@ -0,0 +1,77 @@ +package gg.pingpong.api.user.rank.redis; + +import java.time.LocalDateTime; +import java.util.Objects; + +import javax.annotation.PostConstruct; + +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.redis.RankRedis; +import gg.repo.rank.RankRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.utils.RedisKeyManager; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RedisUploadService { + private final RankRedisRepository redisRepository; + private final SeasonRepository seasonRepository; + private final RankRepository rankRepository; + private final RedisTemplate redisTemplate; + + @PostConstruct + @Transactional + public void uploadRedis() { + seasonRepository.findCurrentSeason(LocalDateTime.now()).ifPresent(currentSeason -> { + String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); + if (redisRepository.isEmpty(hashKey)) { + upload(); + } + }); + } + + private void upload() { + + redisTemplate.executePipelined((RedisCallback)connection -> { + seasonRepository.findAll().forEach(season -> { + String hashKey = RedisKeyManager.getHashKey(season.getId()); + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + rankRepository.findAllBySeasonId(season.getId()).forEach(rank -> { + RankRedis rankRedis = RankRedis.from(rank); + connection.hSet(Objects.requireNonNull(keySerializer().serialize(hashKey)), + Objects.requireNonNull(hashKeySerializer().serialize(rank.getUser().getId().toString())), + Objects.requireNonNull(hashValueSerializer().serialize(rankRedis))); + if (rank.getWins() + rankRedis.getLosses() != 0) { + connection.zAdd(Objects.requireNonNull(keySerializer().serialize(zSetKey)), rank.getPpp(), + Objects.requireNonNull(valueSerializer().serialize(rank.getUser().getId().toString()))); + } + }); + }); + return null; + }); + } + + private RedisSerializer valueSerializer() { + return redisTemplate.getValueSerializer(); + } + + private RedisSerializer hashValueSerializer() { + return redisTemplate.getHashValueSerializer(); + } + + private RedisSerializer hashKeySerializer() { + return redisTemplate.getHashKeySerializer(); + } + + private RedisSerializer keySerializer() { + return redisTemplate.getKeySerializer(); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankFindService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankFindService.java new file mode 100644 index 000000000..5ad1053dd --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankFindService.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.user.rank.service; + +import org.springframework.stereotype.Service; + +import gg.data.rank.Rank; +import gg.repo.rank.RankRepository; +import gg.utils.exception.rank.RankNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RankFindService { + private final RankRepository rankRepository; + + public Rank findByUserIdAndSeasonId(Long userId, Long seasonId) { + return rankRepository.findByUserIdAndSeasonId(userId, seasonId).orElseThrow(RankNotFoundException::new); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankService.java new file mode 100644 index 000000000..affb950d5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/RankService.java @@ -0,0 +1,205 @@ +package gg.pingpong.api.user.rank.service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.rank.dto.ExpRankDto; +import gg.pingpong.api.user.rank.dto.RankDto; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.rank.RankRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.ExpRankV2Dto; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.PageNotFoundException; +import gg.utils.exception.rank.RedisDataNotFoundException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RankService { + private final UserRepository userRepository; + private final RankRedisRepository redisRepository; + private final SeasonFindService seasonFindService; + private final RankRepository rankRepository; + + @Transactional(readOnly = true) + public ExpRankPageResponseDto getExpRankPageByRedis(PageRequest pageRequest, UserDto curUser) { + + Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); + Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); + if (pageRequest.getPageNumber() + 1 > users.getTotalPages()) { + throw new PageNotFoundException("ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.PAGE_NOT_FOUND); + } + + List userIds = users.getContent().stream().map(user -> user.getId()).collect(Collectors.toList()); + Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + + String hashKey = RedisKeyManager.getHashKey(curSeason.getId()); + List ranks = redisRepository.findRanksByUserIds(hashKey, userIds); + + Integer startRank = pageRequest.getPageSize() * pageRequest.getPageNumber() + 1; + List expRankDtos = new ArrayList<>(); + for (int i = 0; i < ranks.size(); i++) { + RankRedis rank = ranks.get(i); + User user = users.getContent().get(i); + expRankDtos.add(ExpRankDto.from(user, startRank + i, rank.getStatusMessage())); + } + + return new ExpRankPageResponseDto(myRank.intValue(), pageRequest.getPageNumber() + 1, users.getTotalPages(), + expRankDtos); + } + + /** + * ExpRankPage v2 (redis ์กฐํšŒ ์ œ๊ฑฐ - db ์กฐํšŒ๋กœ๋งŒ ํ•˜๋Š” ๊ธฐ๋Šฅ) + * @param pageRequest + * @param curUser + * @return + */ + @Transactional(readOnly = true) + public ExpRankPageResponseDto getExpRankPage(PageRequest pageRequest, UserDto curUser) { + + Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); + Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); + if (pageRequest.getPageNumber() + 1 > users.getTotalPages()) { + throw new PageNotFoundException(); + } + List expRankDtos = getExpRankList(pageRequest); + + return new ExpRankPageResponseDto(myRank.intValue(), + pageRequest.getPageNumber() + 1, + users.getTotalPages(), + expRankDtos); + } + + @Cacheable(value = "expRanking", cacheManager = "gameCacheManager", + key = "#pageRequest.pageNumber + #pageRequest.pageSize.toString()") + public List getExpRankList(PageRequest pageRequest) { + Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + int pageOffset = pageRequest.getPageNumber() * pageRequest.getPageSize(); + List expRankV2Dtos = userRepository.findExpRank(pageOffset, pageRequest.getPageSize(), + curSeason.getId()); + return expRankV2Dtos.stream().map(ExpRankDto::from).collect(Collectors.toList()); + } + + /** + * rank ํŽ˜์ด์ง€ ์กฐํšŒ v2 + * @param pageRequest + * @param curUser + * @param seasonId + * @return + */ + @Transactional(readOnly = true) + @Cacheable(value = "ranking", cacheManager = "gameCacheManager", + key = "#pageRequest.pageSize.toString() + #pageRequest.pageNumber + #curUser.id + #seasonId") + public RankPageResponseDto getRankPageV2(PageRequest pageRequest, UserDto curUser, Long seasonId) { + Season season; + if (seasonId == null || seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + int totalPage = calcTotalPageV2(season, pageRequest.getPageSize()); + if (totalPage == 0) { + return returnEmptyRankPage(); + } + if (pageRequest.getPageNumber() + 1 > totalPage) { + throw new PageNotFoundException(); + } + + int myRank = rankRepository.findRankByUserIdAndSeasonId(curUser.getId(), season.getId()) + .orElse(-1); + int pageOffset = pageRequest.getPageNumber() * pageRequest.getPageSize(); + List rankList = rankRepository.findPppRankBySeasonId(pageOffset, pageRequest.getPageSize(), + season.getId()) + .stream().map(RankDto::from).collect(Collectors.toList()); + return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); + } + + @Transactional(readOnly = true) + public RankPageResponseDto getRankPage(PageRequest pageRequest, UserDto curUser, Long seasonId) { + Season season; + if (seasonId == null || seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + int totalPage = calcTotalPage(season, pageRequest.getPageSize()); + if (totalPage == 0) { + return returnEmptyRankPage(); + } + if (pageRequest.getPageNumber() + 1 > totalPage) { + throw new PageNotFoundException("ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.PAGE_NOT_FOUND); + } + + int myRank = findMyRank(curUser, season); + int startRank = pageRequest.getPageNumber() * pageRequest.getPageSize(); + int endRank = startRank + pageRequest.getPageSize() - 1; + List rankList = createRankList(startRank, endRank, season); + return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); + } + + private RankPageResponseDto returnEmptyRankPage() { + return new RankPageResponseDto(-1, 1, 1, new ArrayList<>()); + } + + private int findMyRank(UserDto curUser, Season season) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + try { + Long myRank = redisRepository.getRankInZSet(zSetKey, curUser.getId()); + return myRank.intValue() + 1; + } catch (RedisDataNotFoundException e) { + return -1; + } + } + + private int calcTotalPage(Season season, int pageSize) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + try { + Long totalUserCount = redisRepository.countTotalRank(zSetKey); + return (int)Math.ceil((double)totalUserCount / pageSize); + } catch (RedisDataNotFoundException e) { + return 0; + } + } + + private int calcTotalPageV2(Season season, int pageSize) { + try { + Integer totalUserCount = rankRepository.countRankUserBySeasonId(season.getId()); + return (int)Math.ceil((double)totalUserCount / pageSize); + } catch (RedisDataNotFoundException e) { + return 0; + } + } + + private List createRankList(int startRank, int endRank, Season season) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + + List userIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, startRank, endRank); + List userRanks = redisRepository.findRanksByUserIds(hashKey, userIds); + List rankList = new ArrayList<>(); + + for (int i = 0; i < userRanks.size(); i++) { + User user = userRepository.findById(userIds.get(i)).orElseThrow(UserNotFoundException::new); + rankList.add(RankDto.from(user, userRanks.get(i), ++startRank)); + } + return rankList; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/TierService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/TierService.java new file mode 100644 index 000000000..f692dd0cb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/rank/service/TierService.java @@ -0,0 +1,64 @@ +package gg.pingpong.api.user.rank.service; + +import java.util.List; + +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.season.Season; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class TierService { + private final TierRepository tierRepository; + private final RankRepository rankRepository; + + /** + * ํ•ด๋‹น ์‹œ์ฆŒ ๋žญํ‚น์˜ ํ‹ฐ์–ด๋ฅผ ๋ชจ๋‘ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. + *

+ * ์ฐธ์—ฌํ•œ์  ์—†์œผ๋ฉด 0๋ฒˆ ํ‹ฐ์–ด.
+ * ppp 970 ๋ฏธ๋งŒ 1๋ฒˆ ํ‹ฐ์–ด.
+ * ppp 1010 ๋ฏธ๋งŒ 2๋ฒˆ ํ‹ฐ์–ด.
+ * ppp 1050 ๋ฏธ๋งŒ || ์ƒ์œ„ 30ํ”„๋กœ ๋ฏธ๋งŒ 3๋ฒˆ ํ‹ฐ์–ด.
+ * ppp 1050 ์ด์ƒ && ์ƒ์œ„ 10ํ”„๋กœ ๋ฏธ๋งŒ 4๋ฒˆ ํ‹ฐ์–ด.
+ * ppp 1050 ์ด์ƒ && ์ƒ์œ„ 10ํ”„๋กœ ์ด์ƒ 5๋ฒˆ ํ‹ฐ์–ด.
+ * ์ตœ์ƒ์œ„ 3๋ช… 6๋ฒˆํ‹ฐ์–ด. + *

+ * + * @param season + */ + @Transactional + public void updateAllTier(Season season) { + List rankList = rankRepository.findAllBySeasonIdOrderByPppDesc(season.getId()); + Long totalRankPlayers = rankRepository.countRealRankPlayers(season.getId()); + List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); + + int top30percentPpp = rankList.get((int)(totalRankPlayers * 0.3)).getPpp(); + int top10percentPpp = rankList.get((int)(totalRankPlayers * 0.1)).getPpp(); + + for (int i = 0; i < rankList.size(); i++) { + Rank rank = rankList.get(i); + if (!rank.isParticipated()) { + rank.updateTier(tierList.get(0)); + } else if (i < 3) { + rank.updateTier(tierList.get(6)); + } else if (rank.getPpp() < 970) { + rank.updateTier(tierList.get(1)); + } else if (rank.getPpp() < 1010) { + rank.updateTier(tierList.get(2)); + } else if (rank.getPpp() < 1050 || rank.getPpp() < top30percentPpp) { + rank.updateTier(tierList.get(3)); + } else if (rank.getPpp() < top10percentPpp) { + rank.updateTier(tierList.get(4)); + } else { + rank.updateTier(tierList.get(5)); + } + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/SeasonController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/SeasonController.java new file mode 100644 index 000000000..083c154a4 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/SeasonController.java @@ -0,0 +1,22 @@ +package gg.pingpong.api.user.season.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.user.season.controller.response.SeasonListResDto; +import gg.pingpong.api.user.season.service.SeasonService; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/pingpong/") +public class SeasonController { + + private final SeasonService seasonService; + + @GetMapping("seasons") + public SeasonListResDto seasonList() { + return new SeasonListResDto(seasonService.seasonList()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonListResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonListResDto.java new file mode 100644 index 000000000..6a7a84cb2 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonListResDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.user.season.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class SeasonListResDto { + List seasonList; + + public SeasonListResDto(List seasonList) { + this.seasonList = seasonList; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonResDto.java new file mode 100644 index 000000000..9b86af272 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/controller/response/SeasonResDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.season.controller.response; + +import gg.data.season.Season; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class SeasonResDto { + private Long id; + private String name; + + public SeasonResDto(Season season) { + this.id = season.getId(); + this.name = season.getSeasonName(); + } + + @Override + public String toString() { + return "SeasonResDto{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/dto/CurSeason.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/dto/CurSeason.java new file mode 100644 index 000000000..e171e925b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/dto/CurSeason.java @@ -0,0 +1,25 @@ +package gg.pingpong.api.user.season.dto; + +import java.time.LocalDateTime; + +import gg.data.season.Season; +import lombok.Getter; + +@Getter +public class CurSeason { + private Long id; + private String seasonName; + private LocalDateTime startTime; + private LocalDateTime endTime; + private Integer startPpp; + private Integer pppGap; + + public CurSeason(Season season) { + this.id = season.getId(); + this.seasonName = season.getSeasonName(); + this.startTime = season.getStartTime(); + this.endTime = season.getEndTime(); + this.startPpp = season.getStartPpp(); + this.pppGap = season.getPppGap(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonFindService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonFindService.java new file mode 100644 index 000000000..766376a37 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonFindService.java @@ -0,0 +1,38 @@ +package gg.pingpong.api.user.season.service; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.season.Season; +import gg.repo.game.GameRepository; +import gg.repo.season.SeasonRepository; +import gg.utils.exception.game.GameNotExistException; +import gg.utils.exception.season.SeasonNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor + +public class SeasonFindService { + private final SeasonRepository seasonRepository; + private final GameRepository gameRepository; + + @Transactional(readOnly = true) + public Season findCurrentSeason(LocalDateTime now) { + return seasonRepository.findCurrentSeason(now).orElseThrow(SeasonNotFoundException::new); + } + + @Transactional(readOnly = true) + public Season findSeasonById(Long seasonId) { + return seasonRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); + } + + @Transactional(readOnly = true) + public Season findSeasonByGameId(Long gameId) { + Game game = gameRepository.findById(gameId).orElseThrow(GameNotExistException::new); + return game.getSeason(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonService.java new file mode 100644 index 000000000..0ebddfbdb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/season/service/SeasonService.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.user.season.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +import gg.pingpong.api.user.season.controller.response.SeasonResDto; +import gg.pingpong.api.user.season.dto.CurSeason; +import gg.repo.season.SeasonRepository; +import gg.utils.exception.season.SeasonNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SeasonService { + private final SeasonRepository seasonRepository; + + public List seasonList() { + return seasonRepository.findActiveSeasonsDesc(LocalDateTime.now()) + .stream().map(SeasonResDto::new).collect(Collectors.toList()); + } + + public CurSeason getCurSeason() { + return new CurSeason(seasonRepository.findCurrentSeason(LocalDateTime.now()) + .orElseThrow(() -> new SeasonNotFoundException("ํ˜„์žฌ ์‹œ์ฆŒ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."))); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/ItemController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/ItemController.java new file mode 100644 index 000000000..194b4cbaa --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/ItemController.java @@ -0,0 +1,63 @@ +package gg.pingpong.api.user.store.controller; + +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.store.controller.request.ItemGiftRequestDto; +import gg.pingpong.api.user.store.controller.response.ItemStoreListResponseDto; +import gg.pingpong.api.user.store.controller.response.UserItemListResponseDto; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/items") +public class ItemController { + + private final ItemService itemService; + + @GetMapping("/store") + public ItemStoreListResponseDto getAllItems() { + return itemService.getAllItems(); + } + + @PostMapping("/purchases/{itemId}") + public ResponseEntity purchaseItem(@PathVariable Long itemId, + @Parameter(hidden = true) @Login UserDto userDto) { + itemService.purchaseItem(itemId, userDto); + return new ResponseEntity(HttpStatus.CREATED); + } + + @PostMapping("/gift/{itemId}") + public ResponseEntity giftItem(@PathVariable Long itemId, + @RequestBody ItemGiftRequestDto recipient, + @Parameter(hidden = true) @Login UserDto userDto) { + itemService.giftItem(itemId, recipient.getOwnerId(), userDto); + return new ResponseEntity(HttpStatus.CREATED); + } + + @GetMapping + public UserItemListResponseDto getItemByUser(@ModelAttribute @Valid PageRequestDto req, + @Parameter(hidden = true) @Login UserDto userDto) { + Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), + Sort.by("createdAt").descending()); + return itemService.getItemByUser(userDto, pageable); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/MegaphoneController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/MegaphoneController.java new file mode 100644 index 000000000..b7ac85a83 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/MegaphoneController.java @@ -0,0 +1,58 @@ +package gg.pingpong.api.user.store.controller; + +import java.time.LocalTime; +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.store.controller.request.MegaphoneUseRequestDto; +import gg.pingpong.api.user.store.controller.response.MegaphoneDetailResponseDto; +import gg.pingpong.api.user.store.controller.response.MegaphoneTodayListResponseDto; +import gg.pingpong.api.user.store.service.MegaphoneService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/megaphones") +public class MegaphoneController { + private final MegaphoneService megaphoneService; + + @PostMapping() + public ResponseEntity useMegaphone(@RequestBody @Valid MegaphoneUseRequestDto megaphoneUseRequestDto, + @Parameter(hidden = true) @Login UserDto user) { + megaphoneService.useMegaphone(megaphoneUseRequestDto, user, LocalTime.now()); + return ResponseEntity.status(HttpStatus.CREATED).build(); + } + + @DeleteMapping("/{megaphoneId}") + public ResponseEntity deleteMegaphone(@PathVariable Long megaphoneId, + @Parameter(hidden = true) @Login UserDto user) { + megaphoneService.deleteMegaphone(megaphoneId, user); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + + @GetMapping("/receipt/{receiptId}") + public ResponseEntity getMegaphoneDetail(@PathVariable Long receiptId, + @Parameter(hidden = true) @Login UserDto user) { + return ResponseEntity.ok(megaphoneService.getMegaphoneDetail(receiptId, user)); + } + + @GetMapping() + public ResponseEntity> getMegaphoneTodayList( + @Parameter(hidden = true) @Login UserDto user) { + return ResponseEntity.ok(megaphoneService.getMegaphoneTodayList()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/ItemGiftRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/ItemGiftRequestDto.java new file mode 100644 index 000000000..a2f093691 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/ItemGiftRequestDto.java @@ -0,0 +1,12 @@ +package gg.pingpong.api.user.store.controller.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ItemGiftRequestDto { + private String ownerId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/MegaphoneUseRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/MegaphoneUseRequestDto.java new file mode 100644 index 000000000..2a0839acd --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/request/MegaphoneUseRequestDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.store.controller.request; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MegaphoneUseRequestDto { + @NotNull(message = "receiptId๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + private Long receiptId; + @NotNull(message = "content๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + @Size(max = 30) + private String content; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreListResponseDto.java new file mode 100644 index 000000000..048a11f51 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreListResponseDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.user.store.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class ItemStoreListResponseDto { + private List itemList; + + public ItemStoreListResponseDto(List itemList) { + this.itemList = itemList; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreResponseDto.java new file mode 100644 index 000000000..619125bc3 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/ItemStoreResponseDto.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.user.store.controller.response; + +import gg.data.store.Item; +import gg.data.store.type.ItemType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ItemStoreResponseDto { + private Long itemId; + private String itemName; + private String mainContent; + private String subContent; + private ItemType itemType; + private String imageUri; + private Integer originalPrice; + private Integer discount; + private Integer salePrice; + + public ItemStoreResponseDto(Item item) { + this.itemId = item.getId(); + this.itemName = item.getName(); + this.mainContent = item.getMainContent(); + this.subContent = item.getSubContent(); + this.itemType = item.getType(); + this.imageUri = item.getImageUri(); + this.originalPrice = item.getPrice(); + this.discount = item.getDiscount(); + this.salePrice = this.originalPrice - (this.originalPrice * this.discount / 100); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneDetailResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneDetailResponseDto.java new file mode 100644 index 000000000..4b9d4b0b9 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneDetailResponseDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.store.controller.response; + +import gg.data.store.Megaphone; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneDetailResponseDto { + private Long megaphoneId; + private String content; + private String usedAt; + + public MegaphoneDetailResponseDto(Megaphone megaphone) { + this.megaphoneId = megaphone.getId(); + this.content = megaphone.getContent(); + this.usedAt = megaphone.getUsedAt().toString(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneTodayListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneTodayListResponseDto.java new file mode 100644 index 000000000..6cc63351a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/MegaphoneTodayListResponseDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.store.controller.response; + +import gg.data.store.redis.MegaphoneRedis; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class MegaphoneTodayListResponseDto { + private Long megaphoneId; + private String content; + private String intraId; + + public MegaphoneTodayListResponseDto(MegaphoneRedis megaphoneRedis) { + this.megaphoneId = megaphoneRedis.getId(); + this.content = megaphoneRedis.getContent(); + this.intraId = megaphoneRedis.getIntraId(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemListResponseDto.java new file mode 100644 index 000000000..c3d66e055 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemListResponseDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.store.controller.response; + +import java.util.List; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserItemListResponseDto { + private List storageItemList; + private Integer totalPage; + + public UserItemListResponseDto(List storageItemList, Integer totalPage) { + this.storageItemList = storageItemList; + this.totalPage = totalPage; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemResponseDto.java new file mode 100644 index 000000000..43a4a31ca --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/controller/response/UserItemResponseDto.java @@ -0,0 +1,32 @@ +package gg.pingpong.api.user.store.controller.response; + +import gg.data.store.Item; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserItemResponseDto { + private Long receiptId; + private String itemName; + private String imageUri; + private String purchaserIntra; + private ItemStatus itemStatus; + private ItemType itemType; + + public UserItemResponseDto(Receipt receipt) { + Item item = receipt.getItem(); + this.receiptId = receipt.getId(); + this.itemName = item.getName(); + this.imageUri = item.getImageUri(); + this.purchaserIntra = receipt.getPurchaserIntraId(); + this.itemStatus = receipt.getStatus(); + this.itemType = item.getType(); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/dto/UserGameCoinResultDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/dto/UserGameCoinResultDto.java new file mode 100644 index 000000000..49a0a9281 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/dto/UserGameCoinResultDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.user.store.dto; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserGameCoinResultDto { + private int beforeCoin; + private int afterCoin; + private int coinIncrement; + + public UserGameCoinResultDto(int afterCoin, int coinIncrement) { + this.beforeCoin = afterCoin - coinIncrement; + this.afterCoin = afterCoin; + this.coinIncrement = coinIncrement; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/redis/MegaphoneRedisRepository.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/redis/MegaphoneRedisRepository.java new file mode 100644 index 000000000..564cd7848 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/redis/MegaphoneRedisRepository.java @@ -0,0 +1,34 @@ +package gg.pingpong.api.user.store.redis; + +import java.time.Duration; +import java.util.List; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import gg.data.store.redis.MegaphoneRedis; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class MegaphoneRedisRepository { + private final RedisTemplate redisTemplate; + + public void addMegaphone(MegaphoneRedis megaphoneRedis) { + Duration duration = Duration.between(megaphoneRedis.getUsedAt(), megaphoneRedis.getUsedAt().plusDays(1)); + redisTemplate.opsForValue().set("megaphone" + megaphoneRedis.getId(), megaphoneRedis, duration); + } + + public List getAllMegaphone() { + return redisTemplate.opsForValue().multiGet(redisTemplate.keys("megaphone*")); + } + + public void deleteAllMegaphone() { + redisTemplate.delete(redisTemplate.keys("megaphone*")); + } + + public void deleteMegaphoneById(Long id) { + redisTemplate.delete("megaphone" + id); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/CoinHistoryService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/CoinHistoryService.java new file mode 100644 index 000000000..530ad372c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/CoinHistoryService.java @@ -0,0 +1,78 @@ +package gg.pingpong.api.user.store.service; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.CoinHistory; +import gg.data.store.Item; +import gg.data.store.type.HistoryType; +import gg.data.user.User; +import gg.repo.store.CoinHistoryRepository; +import gg.repo.store.CoinPolicyRepository; +import gg.utils.exception.coin.CoinPolicyNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class CoinHistoryService { + private final CoinHistoryRepository coinHistoryRepository; + private final CoinPolicyRepository coinPolicyRepository; + + @Transactional + public void addAttendanceCoinHistory(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getAttendance(); + addCoinHistory(new CoinHistory(user, HistoryType.ATTENDANCECOIN.getHistory(), amount)); + } + + @Transactional + public void addPurchaseItemCoinHistory(User user, Item item, Integer price) { + addCoinHistory(new CoinHistory(user, item.getName() + " ๊ตฌ๋งค", price * (-1))); + } + + @Transactional + public void addGiftItemCoinHistory(User user, User giftTarget, Item item, Integer price) { + addCoinHistory(new CoinHistory(user, giftTarget.getIntraId() + "์—๊ฒŒ " + item.getName() + " ์„ ๋ฌผ", price * (-1))); + } + + @Transactional + public void addNormalCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal(); + addCoinHistory(new CoinHistory(user, HistoryType.NORMAL.getHistory(), amount)); + } + + @Transactional + public int addRankWinCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankWin(); + addCoinHistory(new CoinHistory(user, HistoryType.RANKWIN.getHistory(), amount)); + return amount; + } + + @Transactional + public int addRankLoseCoin(User user) { + int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankLose(); + if (amount == 0) { + return amount; + } + addCoinHistory(new CoinHistory(user, HistoryType.RANKLOSE.getHistory(), amount)); + return amount; + } + + @Transactional(readOnly = true) + public boolean hasAttendedToday(User user) { + LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); + LocalDateTime endOfDay = startOfDay.plusDays(1); + return coinHistoryRepository.existsUserAttendedCheckToday( + user, HistoryType.ATTENDANCECOIN.getHistory(), startOfDay, endOfDay); + } + + public void addCoinHistory(CoinHistory coinHistory) { + coinHistoryRepository.save(coinHistory); + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/ItemService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/ItemService.java new file mode 100644 index 000000000..6df2287e1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/ItemService.java @@ -0,0 +1,196 @@ +package gg.pingpong.api.user.store.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.Item; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.RoleType; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.store.controller.response.ItemStoreListResponseDto; +import gg.pingpong.api.user.store.controller.response.ItemStoreResponseDto; +import gg.pingpong.api.user.store.controller.response.UserItemListResponseDto; +import gg.pingpong.api.user.store.controller.response.UserItemResponseDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.store.ItemRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.store.UserItemRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.item.ItemNotFoundException; +import gg.utils.exception.item.ItemNotPurchasableException; +import gg.utils.exception.item.ItemTypeException; +import gg.utils.exception.item.KakaoGiftException; +import gg.utils.exception.item.KakaoPurchaseException; +import gg.utils.exception.receipt.ItemStatusException; +import gg.utils.exception.receipt.ReceiptNotOwnerException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ItemService { + + private final ItemRepository itemRepository; + private final ReceiptRepository receiptRepository; + private final UserRepository userRepository; + private final UserItemRepository userItemRepository; + private final NotiService notiService; + private final UserCoinChangeService userCoinChangeService; + + /** + *

๋ชจ๋“  ์•„์ดํ…œ์„ ๊ฐ€์ ธ์˜จ๋‹ค.

+ * @return + */ + @Transactional(readOnly = true) + public ItemStoreListResponseDto getAllItems() { + List itemStoreListResponseDto = itemRepository.findAllByCreatedAtDesc() + .stream().map(ItemStoreResponseDto::new).collect(Collectors.toList()); + return new ItemStoreListResponseDto(itemStoreListResponseDto); + } + + /** + *

๊ฒŒ์ŠคํŠธ ์œ ์ €๊ฐ€ ์•„๋‹Œ ์œ ์ €๊ฐ€ ์•„์ดํ…œ์„ ๊ตฌ๋งคํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ด๋‹ค

+ *

ํ• ์ธ ์ค‘ ์ด๋ผ๋ฉด ํ• ์ธ๊ฐ€๋ฅผ ์ ์šฉํ•˜๊ณ , ๊ตฌ๋งค ํ›„ ์˜์ˆ˜์ฆ์„ db์— ์ €์žฅํ•œ๋‹ค.

+ * @param itemId ํƒ€๊ฒŸ ์•„์ดํ…œ Id + * @param userDto ๊ตฌ๋งค ์œ ์ € ์ •๋ณด + * @throws ItemNotFoundException ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•„์ดํ…œ + * @throws ItemNotPurchasableException ๊ตฌ๋งคํ•  ์ˆ˜ ์—†๋Š” ์•„์ดํ…œ + * @throws UserNotFoundException ํƒ€๊ฒŸ ์œ ์ € ์—†์Œ + * @throws KakaoPurchaseException ๊ฒŒ์ŠคํŠธ(์นด์นด์˜ค) ์œ ์ €๊ฐ€ ์•„์ดํ…œ์„ ๊ตฌ๋งคํ•˜๋ ค ํ• ๋•Œ + * @throws + */ + @Transactional + public void purchaseItem(Long itemId, UserDto userDto) { + Item item = itemRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotPurchasableException(); + } + + //์„ธ์ผ๊ฐ€๊ฒฉ ์กด์žฌํ• ๋•Œ ์„ธ์ผ๊ฐ€๋กœ ๊ฒฐ์ • + Integer finalPrice = item.getPrice(); + if (item.getDiscount() != null && item.getDiscount() > 0) { + finalPrice -= (item.getPrice() * item.getDiscount() / 100); + } + + User payUser = userRepository.findById(userDto.getId()) + .orElseThrow(UserNotFoundException::new); + + if (payUser.getRoleType() == RoleType.GUEST) { + throw new KakaoPurchaseException(); + } + + userCoinChangeService.purchaseItemCoin(item, finalPrice, userDto.getId()); + + Receipt receipt = new Receipt(item, userDto.getIntraId(), userDto.getIntraId(), + ItemStatus.BEFORE, LocalDateTime.now()); + receiptRepository.save(receipt); + } + + /** + *

๊ฒŒ์ŠคํŠธ ์œ ์ €๊ฐ€ ์•„๋‹Œ ์œ ์ €๋“ค ๋ผ๋ฆฌ ์„ ๋ฌผ์„ ์ฃผ๋Š” ๋ฉ”์„œ๋“œ ์ด๋‹ค

+ *

ํ• ์ธ ์ค‘ ์ด๋ผ๋ฉด ํ• ์ธ๊ฐ€๋ฅผ ์ ์šฉํ•˜๊ณ , ๊ตฌ๋งค ํ›„ ์˜์ˆ˜์ฆ์„ db์— ์ €์žฅํ•œ๋‹ค.

+ * @param itemId ํƒ€๊ฒŸ ์•„์ดํ…œ id + * @param ownerId ์„ ๋ฌผ ๋ฐ›๋Š” owner intraId + * @param userDto ๊ตฌ๋งค์ž id + * @throws ItemNotFoundException ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์•„์ดํ…œ + * @throws ItemNotPurchasableException ๊ตฌ๋งคํ•  ์ˆ˜ ์—†๋Š” ์•„์ดํ…œ + * @throws UserNotFoundException ํƒ€๊ฒŸ ์œ ์ € ์—†์Œ + * @throws KakaoPurchaseException ๊ฒŒ์ŠคํŠธ(์นด์นด์˜ค) ์œ ์ €๊ฐ€ ์•„์ดํ…œ์„ ๊ตฌ๋งคํ•˜๋ ค ํ• ๋•Œ + * @throws KakaoGiftException ๊ฒŒ์ŠคํŠธ(์นด์นด์˜ค) ์œ ์ €์—๊ฒŒ ์„ ๋ฌผํ•˜๋ ค ํ• ๋•Œ + */ + @Transactional + public void giftItem(Long itemId, String ownerId, UserDto userDto) { + Item item = itemRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); + if (!item.getIsVisible()) { + throw new ItemNotPurchasableException(); + } + + //์„ธ์ผ๊ฐ€๊ฒฉ ์กด์žฌํ• ๋•Œ ์„ธ์ผ๊ฐ€๋กœ ๊ฒฐ์ • + Integer finalPrice = item.getPrice(); + if (item.getDiscount() != null && item.getDiscount() > 0) { + finalPrice -= (item.getPrice() * item.getDiscount() / 100); + } + + User payUser = userRepository.findById(userDto.getId()) + .orElseThrow(UserNotFoundException::new); + + if (payUser.getRoleType() == RoleType.GUEST) { + throw new KakaoPurchaseException(); + } + + User owner = userRepository.findByIntraId(ownerId) + .orElseThrow(UserNotFoundException::new); + + if (owner.getRoleType() == RoleType.GUEST) { + throw new KakaoGiftException(); + } + + userCoinChangeService.giftItemCoin(item, finalPrice, payUser, owner); + + Receipt receipt = new Receipt(item, userDto.getIntraId(), ownerId, + ItemStatus.BEFORE, LocalDateTime.now()); + receiptRepository.save(receipt); + notiService.createGiftNoti(owner, payUser, item.getName()); + } + + /** + *

์œ ์ €๊ฐ€ ๊ตฌ๋งคํ•œ ์•„์ดํ…œ ์ค‘ ์ƒํƒœ๊ฐ€ BEFORE, USING, WAITING ์ธ ๊ฒƒ๋“ค์„ ์ฐพ๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

+ * @param userDto ์œ ์ € ์ •๋ณด + * @param pageable ํŽ˜์ด์ง€ + * @return + */ + @Transactional(readOnly = true) + public UserItemListResponseDto getItemByUser(UserDto userDto, Pageable pageable) { + Page receipts = userItemRepository.findByOwnerIntraId(userDto.getIntraId(), pageable); + Page responseDto = receipts.map(UserItemResponseDto::new); + return new UserItemListResponseDto(responseDto.getContent(), responseDto.getTotalPages()); + } + + /** + *

ํ•ด๋‹น ์•„์ดํ…œ์˜ ์ฃผ์ธ์ด ๋งž๋Š”์ง€ ์ฒดํฌํ•œ๋‹ค.

+ * @param loginUser ๋กœ๊ทธ์ธ ์œ ์ € + * @param receipt ์˜์ˆ˜์ฆ + */ + public void checkItemOwner(User loginUser, Receipt receipt) { + if (!receipt.getOwnerIntraId().equals(loginUser.getIntraId())) { + throw new ReceiptNotOwnerException(); + } + } + + /** + *

ํ•ด๋‹น ์•„์ดํ…œ์˜ ํƒ€์ž…์ด ์˜์ˆ˜์ฆ๊ณผ ๋งž๋Š”์ง€ ์ฒดํฌํ•œ๋‹ค.

+ * @param receipt ์˜์ˆ˜์ฆ + * @param itemType ์•„์ดํ…œ ํƒ€์ž… + */ + public void checkItemType(Receipt receipt, ItemType itemType) { + if (!receipt.getItem().getType().equals(itemType)) { + throw new ItemTypeException(); + } + } + + /** + *

์•„์ดํ…œ์˜ ์ƒํƒœ๋ฅผ ์ฒดํฌํ•œ๋‹ค.

+ *

๋ฉ”๊ฐ€ํฐ์ธ๋ฐ ItemStatus.WAITING ๊ฐ€ ์•„๋‹ˆ๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ค‘์ด๋ผ๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ

+ *

๋ฉ”๊ฐ€ํฐ์ด ์•„๋‹Œ ์•„์ดํ…œ์ธ๋ฐ ItemStatus.BEFORE ์ธ๊ฒฝ์šฐ ์˜ˆ์™ธ ๋ฐœ์ƒ

+ * @param receipt + */ + public void checkItemStatus(Receipt receipt) { + if (receipt.getItem().getType().equals(ItemType.MEGAPHONE)) { + if (!(receipt.getStatus().equals(ItemStatus.WAITING) + || receipt.getStatus().equals(ItemStatus.USING))) { + throw new ItemStatusException(); + } + } else if (!receipt.getStatus().equals(ItemStatus.BEFORE)) { + throw new ItemStatusException(); + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/MegaphoneService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/MegaphoneService.java new file mode 100644 index 000000000..b478ed9dd --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/MegaphoneService.java @@ -0,0 +1,155 @@ +package gg.pingpong.api.user.store.service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.Megaphone; +import gg.data.store.Receipt; +import gg.data.store.redis.MegaphoneRedis; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.RoleType; +import gg.pingpong.api.user.store.controller.request.MegaphoneUseRequestDto; +import gg.pingpong.api.user.store.controller.response.MegaphoneDetailResponseDto; +import gg.pingpong.api.user.store.controller.response.MegaphoneTodayListResponseDto; +import gg.pingpong.api.user.store.redis.MegaphoneRedisRepository; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.store.MegaphoneRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.item.ItemTypeException; +import gg.utils.exception.megaphone.MegaphoneContentException; +import gg.utils.exception.megaphone.MegaphoneNotFoundException; +import gg.utils.exception.megaphone.MegaphoneTimeException; +import gg.utils.exception.receipt.ItemStatusException; +import gg.utils.exception.receipt.ReceiptNotFoundException; +import gg.utils.exception.receipt.ReceiptNotOwnerException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MegaphoneService { + private final UserRepository userRepository; + private final ReceiptRepository receiptRepository; + private final MegaphoneRepository megaphoneRepository; + private final MegaphoneRedisRepository megaphoneRedisRepository; + private final ItemService itemService; + + /** + *

๋ฉ”๊ฐ€ํฐ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

+ *

00:06 ~ 23:54 ๋ถ„ ์‚ฌ์ด์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ ํ•ฉ๋‹ˆ๋‹ค.

+ * @param megaphoneUseRequestDto ์š”์ฒญ dto + * @param user ์ ‘์† ์œ ์ € + * @param localTime ํ˜„์žฌ ๋‚ ์งœ + * @throws UserNotFoundException ์œ ์ € ์—†์„ ๋•Œ + * @throws MegaphoneTimeException ๋ฉ”๊ฐ€ํฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ๊ธฐ๊ฐ„ ์•„๋‹๋•Œ + * @throws ReceiptNotFoundException ์˜์ˆ˜์ฆ ์—†์„ ๋•Œ + * @throws ItemTypeException ๋ฉ”๊ฐ€ํฐ ์•„๋‹ ๋•Œ + * @throws ReceiptNotOwnerException ์˜์ˆ˜์ฆ์— ์ ํžŒ ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋‹ ๋•Œ + * @throws ItemStatusException ์‚ฌ์šฉ์ „์ธ ์•„์ดํ…œ์ด ์•„๋‹๋•Œ + * @throws MegaphoneContentException ๋ฉ”๊ฐ€ํฐ ๋‚ด์šฉ์ด ์—†์„ ๋•Œ + + */ + @Transactional + public void useMegaphone(MegaphoneUseRequestDto megaphoneUseRequestDto, UserDto user, LocalTime localTime) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + if (localTime.isAfter(LocalTime.of(23, 55)) || localTime.isBefore(LocalTime.of(0, 5))) { + throw new MegaphoneTimeException(); + } + Receipt receipt = receiptRepository.findById(megaphoneUseRequestDto.getReceiptId()) + .orElseThrow(ReceiptNotFoundException::new); + itemService.checkItemType(receipt, ItemType.MEGAPHONE); + itemService.checkItemOwner(loginUser, receipt); + if (!receipt.getStatus().equals(ItemStatus.BEFORE)) { + throw new ItemStatusException(); + } + if (megaphoneUseRequestDto.getContent().isEmpty()) { + throw new MegaphoneContentException(); + } + receipt.updateStatus(ItemStatus.WAITING); + Megaphone megaphone = new Megaphone(loginUser, receipt, megaphoneUseRequestDto.getContent(), + LocalDate.now().plusDays(1)); + megaphoneRepository.save(megaphone); + } + + /** + *

ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ ๋ฉ”๊ฐ€ํฐ์€ ์‚ญ์ œํ•˜๊ณ , ๋‹ค์Œ๋‚  ๋ฉ”๊ฐ€ํฐ๋“ค์„ ๋“ฑ๋ก ์‹œ์ผœ์ค€๋‹ค.

+ * @param today ํ˜„์žฌ ๋‚ ์งœ. + */ + @Transactional + public void setMegaphoneList(LocalDate today) { + megaphoneRepository.findAllByUsedAtAndReceiptStatus(today, ItemStatus.USING) + .forEach(megaphone -> megaphone.getReceipt().updateStatus(ItemStatus.USED)); + megaphoneRedisRepository.deleteAllMegaphone(); + List megaphones = megaphoneRepository + .findAllByUsedAtAndReceiptStatus(today.plusDays(1), ItemStatus.WAITING); + for (Megaphone megaphone : megaphones) { + megaphone.getReceipt().updateStatus(ItemStatus.USING); + megaphoneRedisRepository.addMegaphone(new MegaphoneRedis(megaphone.getId(), + megaphone.getUser().getIntraId(), megaphone.getContent(), + LocalDateTime.of(megaphone.getUsedAt(), LocalTime.of(0, 0)))); + } + } + + /** + *

๋ฉ”๊ฐ€ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž์™€ ์ผ๋ฐ˜์œ ์ €๊ฐ€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

+ * @param megaphoneId ํƒ€๊ฒŸ id + * @param user ์ ‘์† ์œ ์ € + * @throws UserNotFoundException ์œ ์ €๊ฐ€ ์—†์„ ๋•Œ + * @throws MegaphoneNotFoundException ํƒ€๊ฒŸ ๋ฉ”๊ฐ€ํฐ ์—†์„ ๋•Œ + * @throws ReceiptNotOwnerException ์ฃผ์ธ์ด ์•„๋‹ ๋•Œ + * @throws ItemStatusException ์•„์ดํ…œ ์ƒํƒœ ์—๋Ÿฌ + */ + @Transactional + public void deleteMegaphone(Long megaphoneId, UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Megaphone megaphone = megaphoneRepository.findById(megaphoneId).orElseThrow(MegaphoneNotFoundException::new); + Receipt receipt = megaphone.getReceipt(); + if (!user.getRoleType().equals(RoleType.ADMIN)) { + itemService.checkItemOwner(loginUser, receipt); + } + itemService.checkItemStatus(receipt); + if (receipt.getStatus().equals(ItemStatus.USING)) { + megaphoneRedisRepository.deleteMegaphoneById(megaphone.getId()); + } + receipt.updateStatus(ItemStatus.DELETED); + } + + /** + *

๋ฉ”๊ฐ€ํฐ ์„ธ๋ถ€์‚ฌํ•ญ์„ ๋ฐ˜ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.

+ * @param receiptId ํƒ€๊ฒŸ id + * @param user ์ ‘์† ์œ ์ € + * @throws UserNotFoundException ์œ ์ € ์—†์„ ๋•Œ + * @throws ReceiptNotFoundException ์˜์ˆ˜์ฆ์ด ์—†์„ ๋•Œ + * @throws ItemTypeException ๋ฉ”๊ฐ€ํฐ์ด ์•„๋‹ ๋•Œ + * @throws ReceiptNotOwnerException ์ฃผ์ธ์ด ์•„๋‹๋•Œ + * @throws ItemStatusException ์•„์ดํ…œ์˜ ์ƒํƒœ ์—๋Ÿฌ + * @throws MegaphoneNotFoundException ์—†๋Š” ๋ฉ”๊ฐ€ํฐ ์ผ๋•Œ + */ + public MegaphoneDetailResponseDto getMegaphoneDetail(Long receiptId, UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Receipt receipt = receiptRepository.findById(receiptId).orElseThrow(ReceiptNotFoundException::new); + itemService.checkItemType(receipt, ItemType.MEGAPHONE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + Megaphone megaphone = megaphoneRepository.findByReceipt(receipt).orElseThrow(MegaphoneNotFoundException::new); + return new MegaphoneDetailResponseDto(megaphone); + } + + /** + *

์˜ค๋Š˜ ๋„์›Œ์ง€๋Š” ๋ฉ”๊ฐ€ํฐ๋“ค์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

+ * @return + */ + public List getMegaphoneTodayList() { + return megaphoneRedisRepository.getAllMegaphone().stream() + .map(MegaphoneTodayListResponseDto::new).collect(Collectors.toList()); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/UserCoinChangeService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/UserCoinChangeService.java new file mode 100644 index 000000000..e0bbe3ad6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/store/service/UserCoinChangeService.java @@ -0,0 +1,100 @@ +package gg.pingpong.api.user.store.service; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.store.Item; +import gg.data.user.User; +import gg.pingpong.api.user.game.service.GameFindService; +import gg.pingpong.api.user.store.dto.UserGameCoinResultDto; +import gg.repo.store.CoinPolicyRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.coin.CoinPolicyNotFoundException; +import gg.utils.exception.user.UserAlreadyAttendanceException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserCoinChangeService { + private final CoinPolicyRepository coinPolicyRepository; + private final CoinHistoryService coinHistoryService; + private final UserRepository userRepository; + private final GameFindService gameFindService; + + @Transactional + public int addAttendanceCoin(User user) { + if (coinHistoryService.hasAttendedToday(user)) { + throw new UserAlreadyAttendanceException(); + } + int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getAttendance(); + user.addGgCoin(coinIncrement); + coinHistoryService.addAttendanceCoinHistory(user); + return coinIncrement; + } + + @Transactional + public void purchaseItemCoin(Item item, Integer price, Long userId) { + + User user = userRepository.findById(userId) + .orElseThrow(UserNotFoundException::new); + + user.payGgCoin(price); + + coinHistoryService.addPurchaseItemCoinHistory(user, item, price); + } + + @Transactional + public void giftItemCoin(Item item, Integer price, User user, User giftTarget) { + user.payGgCoin(price); + + coinHistoryService.addGiftItemCoinHistory(user, giftTarget, item, price); + } + + @Transactional + public UserGameCoinResultDto addNormalGameCoin(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getNormal(); + + user.addGgCoin(coinIncrement); + coinHistoryService.addNormalCoin(user); + return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); + } + + @Transactional + public UserGameCoinResultDto addRankGameCoin(Long gameId, Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + int coinIncrement; + + if (userIsWinner(gameId, user)) { + coinIncrement = coinHistoryService.addRankWinCoin(user); + } else { + coinIncrement = coinHistoryService.addRankLoseCoin(user); + } + + user.addGgCoin(coinIncrement); + return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); + } + + private boolean userIsWinner(Long gameId, User user) { + List teams = gameFindService.findByGameId(gameId).getTeams(); + + for (Team team : teams) { + for (TeamUser teamUser : team.getTeamUsers()) { + if (teamUser.getUser().getId() == user.getId() && team.getWin()) { + return true; + } else if (teamUser.getUser().getId() == user.getId() && !team.getWin()) { + return false; + } + } + } + + return false; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/TournamentController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/TournamentController.java new file mode 100644 index 000000000..c2294aa7c --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/TournamentController.java @@ -0,0 +1,111 @@ +package gg.pingpong.api.user.tournament.controller; + +import javax.validation.Valid; +import javax.validation.constraints.Positive; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.tournament.controller.request.TournamentFilterRequestDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserRegistrationResponseDto; +import gg.pingpong.api.user.tournament.service.TournamentService; +import gg.pingpong.api.user.user.dto.UserDto; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/tournaments") +@Validated +public class TournamentController { + + private final TournamentService tournamentService; + + /** + * ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ + * @param tournamentFilterRequestDto Enum ํ•„ํ„ฐ ์ •๋ณด (page, size, type, status) + * @return ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ + */ + @GetMapping + public ResponseEntity getAllTournamentList( + @ModelAttribute @Valid TournamentFilterRequestDto tournamentFilterRequestDto) { + Pageable pageRequest = PageRequest.of(tournamentFilterRequestDto.getPage() - 1, + tournamentFilterRequestDto.getSize(), Sort.by("startTime").ascending()); + return ResponseEntity.status(HttpStatus.OK) + .body(tournamentService.getAllTournamentList(pageRequest, tournamentFilterRequestDto.getType(), + tournamentFilterRequestDto.getStatus())); + } + + /** + *

์œ ์ € ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ์—ฌ ์—ฌ๋ถ€ ํ™•์ธ ๋งค์„œ๋“œ

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ + * @param user ํ™•์ธํ•˜๊ณ ์ž ํ•˜๋Š” ์œ ์ €(๋กœ๊ทธ์ธํ•œ ์œ ์ € ๋ณธ์ธ) + * @return + */ + @GetMapping("/{tournamentId}/users") + ResponseEntity getUserStatusInTournament(@PathVariable Long tournamentId, + @Parameter(hidden = true) @Login UserDto user) { + + return ResponseEntity.status(HttpStatus.OK) + .body(tournamentService.getUserStatusInTournament(tournamentId, user)); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๋‹จ์ผ ์กฐํšŒ + * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id + * @return ํ† ๋„ˆ๋จผํŠธ + */ + @GetMapping("/{tournamentId}") + public ResponseEntity getTournnament(@PathVariable @Positive Long tournamentId) { + TournamentResponseDto tournamentResponseDto = tournamentService.getTournament(tournamentId); + return ResponseEntity.status(HttpStatus.OK).body(tournamentResponseDto); + } + + @DeleteMapping("/{tournamentId}/users") + ResponseEntity cancelTournamentUserRegistration( + @PathVariable Long tournamentId, @Parameter(hidden = true) @Login UserDto user) { + + return ResponseEntity.status(HttpStatus.OK) + .body(tournamentService.cancelTournamentUserRegistration(tournamentId, user)); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ + * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id + * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ + */ + @GetMapping("/{tournamentId}/games") + public ResponseEntity getTournamentGames(@PathVariable @Positive Long tournamentId) { + return ResponseEntity.status(HttpStatus.OK).body(tournamentService.getTournamentGames(tournamentId)); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ

+ *

ํ† ๋„ˆ๋จผํŠธ ์ตœ๋Œ€ ์ธ์›๋ณด๋‹ค ์ด๋ฏธ ๋งŽ์ด ์‹ ์ฒญํ–ˆ๋‹ค๋ฉด ๋Œ€๊ธฐ์ž๋กœ ๋“ค์–ด๊ฐ„๋‹ค

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id + * @param user ์‹ ์ฒญ ์œ ์ €(๋ณธ์ธ) + * @return + */ + @PostMapping("/{tournamentId}/users") + ResponseEntity registerTournamentUser(@PathVariable Long tournamentId, + @Parameter(hidden = true) @Login UserDto user) { + + return ResponseEntity.status(HttpStatus.CREATED) + .body(tournamentService.registerTournamentUser(tournamentId, user)); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/request/TournamentFilterRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/request/TournamentFilterRequestDto.java new file mode 100644 index 000000000..a0f1d7621 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/request/TournamentFilterRequestDto.java @@ -0,0 +1,20 @@ +package gg.pingpong.api.user.tournament.controller.request; + +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.pingpong.api.global.dto.PageRequestDto; +import lombok.Getter; + +@Getter +public class TournamentFilterRequestDto extends PageRequestDto { + + private TournamentType type; + + private TournamentStatus status; + + public TournamentFilterRequestDto(Integer page, Integer size, TournamentType type, TournamentStatus status) { + super(page, size); + this.type = type; + this.status = status; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameListResponseDto.java new file mode 100644 index 000000000..f8b13428e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameListResponseDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import java.util.List; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TournamentGameListResponseDto { + private Long tournamentId; + private List games; + + public TournamentGameListResponseDto(Long tournamentId, List games) { + this.tournamentId = tournamentId; + this.games = games; + } + + @Override + public String toString() { + return "TournamentGameListResponseDto{" + + "tournamentId=" + tournamentId + + ", games=" + games.toString() + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameResDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameResDto.java new file mode 100644 index 000000000..246488cc0 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentGameResDto.java @@ -0,0 +1,37 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentRound; +import gg.pingpong.api.user.game.controller.response.GameResultResDto; +import gg.repo.game.out.GameTeamUser; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TournamentGameResDto { + + private Long tournamentGameId; + private Long nextTournamentGameId; + private TournamentRound tournamentRound; + private GameResultResDto game; + + public TournamentGameResDto(TournamentGame tournamentGame, GameTeamUser game, TournamentRound tournamentRound, + TournamentGame nextTournamentGame) { + this.tournamentGameId = tournamentGame.getId(); + this.game = game == null ? null : new GameResultResDto(game); + this.tournamentRound = tournamentRound; + this.nextTournamentGameId = nextTournamentGame == null ? null : nextTournamentGame.getId(); + } + + @Override + public String toString() { + return "TournamentGameResDto{" + + "tournamentGameId=" + tournamentGameId + + ", NextTournamentGameId=" + nextTournamentGameId + + ", tournamentRound='" + tournamentRound + '\'' + + ", gameId=" + game.getGameId() + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentListResponseDto.java new file mode 100644 index 000000000..85a616dda --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentListResponseDto.java @@ -0,0 +1,23 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import java.util.List; + +import org.springframework.data.domain.Page; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@Getter +public class TournamentListResponseDto { + + private List tournaments; + private int totalPage; + + public TournamentListResponseDto(Page tournamentsDto) { + tournaments = tournamentsDto.getContent(); + totalPage = tournamentsDto.getTotalPages(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentResponseDto.java new file mode 100644 index 000000000..2a10b819e --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentResponseDto.java @@ -0,0 +1,62 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import java.time.LocalDateTime; + +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.pingpong.api.user.user.dto.UserImageDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@Getter +public class TournamentResponseDto { + + private Long tournamentId; + private String title; + private String contents; + private LocalDateTime startTime; + private LocalDateTime endTime; + private TournamentType type; + private TournamentStatus status; + private String winnerIntraId; + private String winnerImageUrl; + private long playerCnt; + + public TournamentResponseDto(Tournament tournament, UserImageDto winner, int playerCnt) { + this.tournamentId = tournament.getId(); + this.title = tournament.getTitle(); + this.contents = tournament.getContents(); + this.startTime = tournament.getStartTime(); + this.endTime = tournament.getEndTime(); + this.type = tournament.getType(); + this.status = tournament.getStatus(); + this.winnerIntraId = winner.getIntraId(); + this.winnerImageUrl = winner.getImageUri(); + this.playerCnt = playerCnt; + } + + public TournamentResponseDto(Tournament tournament) { + this.tournamentId = tournament.getId(); + this.title = tournament.getTitle(); + this.contents = tournament.getContents(); + this.startTime = tournament.getStartTime(); + this.endTime = tournament.getEndTime(); + this.type = tournament.getType(); + this.status = tournament.getStatus(); + this.playerCnt = tournament.getTournamentUsers().stream() + .filter(TournamentUser::getIsJoined).count(); + if (tournament.getWinner() != null) { + this.winnerIntraId = tournament.getWinner().getIntraId(); + this.winnerImageUrl = tournament.getWinner().getImageUri(); + } + } + + public void update_player_cnt(int playerCnt) { + this.playerCnt = playerCnt; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserListResponseDto.java new file mode 100644 index 000000000..818afd763 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserListResponseDto.java @@ -0,0 +1,24 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import gg.data.tournament.TournamentUser; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@Getter +public class TournamentUserListResponseDto { + private List users; + + public TournamentUserListResponseDto(List tournamentUsers) { + users = new ArrayList<>(); + for (TournamentUser tournamentUser : tournamentUsers) { + users.add(new TournamentUserResponseDto(tournamentUser)); + } + users.sort(Comparator.comparing(TournamentUserResponseDto::getIsJoined).reversed() + .thenComparing(TournamentUserResponseDto::getRegisteredDate)); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserRegistrationResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserRegistrationResponseDto.java new file mode 100644 index 000000000..5858017cb --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserRegistrationResponseDto.java @@ -0,0 +1,13 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import gg.data.tournament.type.TournamentUserStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@Getter +public class TournamentUserRegistrationResponseDto { + private TournamentUserStatus status; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserResponseDto.java new file mode 100644 index 000000000..acb5f83ae --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/controller/response/TournamentUserResponseDto.java @@ -0,0 +1,25 @@ +package gg.pingpong.api.user.tournament.controller.response; + +import java.time.LocalDateTime; + +import gg.data.tournament.TournamentUser; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@Getter +public class TournamentUserResponseDto { + private Long userId; + private String intraId; + private Boolean isJoined; + private LocalDateTime registeredDate; + + public TournamentUserResponseDto(TournamentUser tournamentUser) { + this.userId = tournamentUser.getUser().getId(); + this.intraId = tournamentUser.getUser().getIntraId(); + this.isJoined = tournamentUser.getIsJoined(); + this.registeredDate = tournamentUser.getRegisterTime(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/service/TournamentService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/service/TournamentService.java new file mode 100644 index 000000000..854e3b995 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/tournament/service/TournamentService.java @@ -0,0 +1,280 @@ +package gg.pingpong.api.user.tournament.service; + +import static java.util.Comparator.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.noti.type.NotiType; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.RoundNumber; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.tournament.type.TournamentUserStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.match.service.MatchTournamentService; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameResDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserRegistrationResponseDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameTeamUser; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; +import gg.utils.exception.tournament.TournamentConflictException; +import gg.utils.exception.tournament.TournamentNotFoundException; +import gg.utils.exception.tournament.TournamentUpdateException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class TournamentService { + private final TournamentRepository tournamentRepository; + private final TournamentUserRepository tournamentUserRepository; + private final UserRepository userRepository; + private final TournamentGameRepository tournamentGameRepository; + private final GameRepository gameRepository; + private final MatchTournamentService matchTournamentService; + private final NotiAdminService notiAdminService; + + /** + * ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ + * @param pageRequest ํŽ˜์ด์ง€ ์ •๋ณด + * @param type ํ† ๋„ˆ๋จผํŠธ ํƒ€์ž… + * @param status ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ + * @return ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ + */ + public TournamentListResponseDto getAllTournamentList(Pageable pageRequest, TournamentType type, + TournamentStatus status) { + Page tournaments; + if (type == null && status == null) { + tournaments = tournamentRepository.findAll(pageRequest); + } else if (type == null) { + tournaments = tournamentRepository.findAllByStatus(status, pageRequest); + } else if (status == null) { + tournaments = tournamentRepository.findAllByType(type, pageRequest); + } else { + tournaments = tournamentRepository.findAllByTypeAndStatus(type, status, pageRequest); + } + Page tournamentsDto = tournaments.map(TournamentResponseDto::new); + return new TournamentListResponseDto(tournamentsDto); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๋‹จ์ผ ์กฐํšŒ + * @param tournamentId + * @return ํ† ๋„ˆ๋จผํŠธ + */ + public TournamentResponseDto getTournament(long tournamentId) { + Tournament tournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + return (new TournamentResponseDto(tournament)); + } + + /** + *

์œ ์ € ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ์—ฌ ์—ฌ๋ถ€ ํ™•์ธ ๋งค์„œ๋“œ

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ + * @param user ํ•ด๋‹น ์œ ์ € + * @return TournamentUserRegistrationResponseDto [ BEFORE || WAIT || PLAYER ] + * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ + */ + public TournamentUserRegistrationResponseDto getUserStatusInTournament(Long tournamentId, UserDto user) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + + TournamentUserStatus tournamentUserStatus = TournamentUserStatus.BEFORE; + Optional tournamentUser = targetTournament.findTournamentUserByUserId(user.getId()); + + if (tournamentUser.isPresent()) { + tournamentUserStatus = + tournamentUser.get().getIsJoined() ? TournamentUserStatus.PLAYER : TournamentUserStatus.WAIT; + } + return new TournamentUserRegistrationResponseDto(tournamentUserStatus); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ๋งค์„œ๋“œ

+ *

์ด๋ฏธ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ ์ค‘ BEFORE || LIVE์ธ ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด ์‹ ์ฒญ ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค.

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ Id + * @param user ์‹ ์ฒญ ์œ ์ €(๋กœ๊ทธ์ธํ•œ ๋ณธ์ธ) + * @return TournamentUserRegistrationResponseDto [ WAIT || PLAYER ] + * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ + * @throws UserNotFoundException ์œ ์ € ์—†์Œ + * @throws TournamentConflictException ์ด๋ฏธ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ ์กด์žฌ(BEFORE || LIVE์ธ ํ† ๋„ˆ๋จผํŠธ) + */ + @Transactional + public TournamentUserRegistrationResponseDto registerTournamentUser(Long tournamentId, UserDto user) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + + List tournamentUserList = targetTournament.getTournamentUsers(); + tournamentUserRepository.findAllByUser(loginUser).stream() + .filter(tu -> tu.getTournament().getStatus().equals(TournamentStatus.BEFORE) || tu.getTournament() + .getStatus() + .equals(TournamentStatus.LIVE)) + .findAny() + .ifPresent(a -> { + throw new TournamentConflictException(ErrorCode.TOURNAMENT_ALREADY_PARTICIPANT); + }); + TournamentUser tournamentUser = new TournamentUser(loginUser, targetTournament, + tournamentUserList.size() < Tournament.ALLOWED_JOINED_NUMBER, LocalDateTime.now()); + TournamentUserStatus tournamentUserStatus = + tournamentUser.getIsJoined() ? TournamentUserStatus.PLAYER : TournamentUserStatus.WAIT; + return new TournamentUserRegistrationResponseDto(tournamentUserStatus); + } + + /** + *

์œ ์ € ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ์ทจ์†Œ ๋งค์„œ๋“œ

+ *

์ฐธ๊ฐ€์ž๊ฐ€ WAIT ์ด๊ฑฐ๋‚˜ PLAYER ๋กœ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์‹ ์ฒญ์„ ํ•œ ์ƒํƒœ์ผ๋•Œ๋งŒ ์ทจ์†Œํ•ด ์ค€๋‹ค.

+ * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ + * @param user ํƒ€๊ฒŸ ์œ ์ €(์‚ฌ์šฉ์ž ๋ณธ์ธ) + * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ || ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹˜ + * @return + */ + @Transactional + public TournamentUserRegistrationResponseDto cancelTournamentUserRegistration(Long tournamentId, UserDto user) { + Tournament targetTournament = tournamentRepository.findById(tournamentId) + .orElseThrow(TournamentNotFoundException::new); + if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { + throw new TournamentUpdateException(); + } + + List tournamentUserList = targetTournament.getTournamentUsers(); + TournamentUser targetTournamentUser = tournamentUserList.stream() + .filter(tu -> (tu.getUser().getId().equals(user.getId()))) + .findAny() + .orElseThrow(() -> new TournamentNotFoundException(ErrorCode.TOURNAMENT_NOT_PARTICIPANT)); + tournamentUserList.remove(targetTournamentUser); + if (targetTournamentUser.getIsJoined() && tournamentUserList.size() >= Tournament.ALLOWED_JOINED_NUMBER) { + tournamentUserList.get(Tournament.ALLOWED_JOINED_NUMBER - 1).updateIsJoined(true); + } + tournamentUserRepository.delete(targetTournamentUser); + return new TournamentUserRegistrationResponseDto(TournamentUserStatus.BEFORE); + } + + /** + * ์˜ค๋Š˜ ์‹œ์ž‘ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ status๋ฅผ LIVE๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + * ์ฐธ๊ฐ€์ž๊ฐ€ ALLOWED_JOINED_NUMBER๋ณด๋‹ค ์ ์œผ๋ฉด ํ† ๋„ˆ๋จผํŠธ ์ทจ์†Œ + */ + @Transactional + public void startTournament() { + LocalDate date = LocalDate.now(); + List imminentTournaments = findImminentTournament(date); + + for (Tournament imminentTournament : imminentTournaments) { + List tournamentUsers = imminentTournament.getTournamentUsers(); + if (tournamentUsers.size() < Tournament.ALLOWED_JOINED_NUMBER) { + sendNotification(tournamentUsers, NotiType.TOURNAMENT_CANCELED); + tournamentRepository.delete(imminentTournament); + continue; + } + imminentTournament.updateStatus(TournamentStatus.LIVE); + matchTournamentService.matchGames(imminentTournament, RoundNumber.QUARTER_FINAL); + } + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ค‘์ธ ์œ ์ €์—๊ฒŒ ์•Œ๋ฆผ ์ „์†ก. + */ + private void sendNotification(List tournamentUsers, NotiType type) { + for (TournamentUser tournamentUser : tournamentUsers) { + String message = type.getMessage(); + + if (tournamentUser.getIsJoined().equals(true)) { + String intraId = tournamentUser.getUser().getIntraId(); + SendNotiAdminRequestDto dto = new SendNotiAdminRequestDto(intraId, message); + notiAdminService.sendAnnounceNotiToUser(dto); + } + } + } + + /** + * ์‹œ์ž‘ ์ž„๋ฐ•ํ•œ(์˜ค๋Š˜ ์‹œ์ž‘ํ•˜๋Š”) ํ† ๋„ˆ๋จผํŠธ ์กฐํšŒ + * @param date ์กฐํšŒํ•˜๋ ค๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ์ž‘ ๋‚ ์งœ + * @return date ๋‚ ์งœ์— ์‹œ์ž‘ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ + */ + private List findImminentTournament(LocalDate date) { + List tournaments = tournamentRepository.findAllByStatus(TournamentStatus.BEFORE); + return tournaments.stream() + .filter(tournament -> tournament.getStartTime().toLocalDate().isEqual(date)) + .collect(Collectors.toList()); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ + * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id + * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ชฉ๋ก + */ + public TournamentGameListResponseDto getTournamentGames(Long tournamentId) { + List tournamentGameResDtoList = getTournamentGameResDtoList(tournamentId); + return new TournamentGameListResponseDto(tournamentId, tournamentGameResDtoList); + } + + /** + * TournamentGameResDto list ๋ฐ˜ํ™˜ + * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id + * @return List + * - tournamentGameId: ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ id + * - NextTournamentGameId: ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ id + * - tournamentRound: ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ + * - game: ๊ฒŒ์ž„ ์ •๋ณด + */ + private List getTournamentGameResDtoList(Long tournamentId) { + List tournamentGames = tournamentGameRepository.findAllByTournamentId(tournamentId); + List tournamentGameResDtoList = new ArrayList<>(); + for (TournamentGame tournamentGame : tournamentGames) { + TournamentGame nextTournamentGame = findNextTournamentGame(tournamentGames, tournamentGame); + GameTeamUser gameTeamUser = null; + if (tournamentGame.getGame() != null) { + gameTeamUser = gameRepository.findTeamsByGameId(tournamentGame.getGame().getId()) + .orElseThrow(() -> new BusinessException(ErrorCode.TEAM_USER_NOT_FOUND)); + } + tournamentGameResDtoList.add( + new TournamentGameResDto(tournamentGame, gameTeamUser, tournamentGame.getTournamentRound(), + nextTournamentGame)); + } + tournamentGameResDtoList.sort(comparing(TournamentGameResDto::getTournamentRound, + comparing(TournamentRound::getRoundNumber).reversed().thenComparing(TournamentRound::getRoundOrder))); + + return tournamentGameResDtoList; + } + + /** + * ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์กฐํšŒ + * @param tournamentGames tournamentGames ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ + * @param tournamentGame ํ˜„์žฌ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + * @return ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + */ + private TournamentGame findNextTournamentGame(List tournamentGames, TournamentGame tournamentGame) { + TournamentRound tournamentRound = tournamentGame.getTournamentRound(); + return tournamentGames.stream() + .filter(tournamentGame1 -> tournamentGame1.getTournamentRound().equals(tournamentRound.getNextRound())) + .findFirst() + .orElse(null); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/UserController.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/UserController.java new file mode 100644 index 000000000..3afc31df1 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/UserController.java @@ -0,0 +1,196 @@ +package gg.pingpong.api.user.user.controller; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +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.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import gg.data.game.type.Mode; +import gg.data.user.type.OauthType; +import gg.data.user.type.RoleType; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.pingpong.api.global.security.cookie.CookieUtil; +import gg.pingpong.api.global.security.jwt.utils.TokenHeaders; +import gg.pingpong.api.global.utils.argumentresolver.Login; +import gg.pingpong.api.user.user.controller.request.UserModifyRequestDto; +import gg.pingpong.api.user.user.controller.request.UserProfileImageRequestDto; +import gg.pingpong.api.user.user.controller.response.UserAttendanceResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinHistoryListResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinResponseDto; +import gg.pingpong.api.user.user.controller.response.UserDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserHistoryResponseDto; +import gg.pingpong.api.user.user.controller.response.UserImageResponseDto; +import gg.pingpong.api.user.user.controller.response.UserLiveResponseDto; +import gg.pingpong.api.user.user.controller.response.UserNormalDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserRankResponseDto; +import gg.pingpong.api.user.user.controller.response.UserSearchResponseDto; +import gg.pingpong.api.user.user.dto.UserAccessTokenDto; +import gg.pingpong.api.user.user.dto.UserBackgroundDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.pingpong.api.user.user.dto.UserEdgeDto; +import gg.pingpong.api.user.user.dto.UserOauthDto; +import gg.pingpong.api.user.user.dto.UserTextColorDto; +import gg.pingpong.api.user.user.service.UserAuthenticationService; +import gg.pingpong.api.user.user.service.UserCoinService; +import gg.pingpong.api.user.user.service.UserService; +import gg.utils.exception.user.KakaoOauth2AlreadyExistException; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/pingpong/users") +public class UserController { + private final UserService userService; + private final UserAuthenticationService userAuthenticationService; + private final CookieUtil cookieUtil; + private final UserCoinService userCoinService; + + @PostMapping("/accesstoken") + public ResponseEntity generateAccessToken(@RequestParam String refreshToken) { + String accessToken = userAuthenticationService.regenerate(refreshToken); + return new ResponseEntity<>(new UserAccessTokenDto(accessToken), HttpStatus.CREATED); + } + + @GetMapping + UserNormalDetailResponseDto getUserNormalDetail(@Parameter(hidden = true) @Login UserDto user) { + return userService.getUserNormalDetail(user); + } + + @GetMapping("/live") + UserLiveResponseDto getUserLiveDetail(@Parameter(hidden = true) @Login UserDto user) { + return userService.getUserLiveDetail(user); + } + + @GetMapping("/searches") + UserSearchResponseDto searchUsers(@RequestParam String intraId) { + List intraIds = userService.findByPartOfIntraId(intraId); + return new UserSearchResponseDto(intraIds); + } + + @GetMapping("/{intraId}") + public UserDetailResponseDto getUserDetail(@PathVariable String intraId) { + return userService.getUserDetail(intraId); + } + + @GetMapping("/{intraId}/rank") + public UserRankResponseDto getUserRank(@PathVariable String intraId, @RequestParam Long season) { + return userService.getUserRankDetail(intraId, season); + } + + @GetMapping("/{intraId}/historics") + public UserHistoryResponseDto getUserHistory(@PathVariable String intraId, @RequestParam Long season) { + return userService.getUserHistory(intraId, season); + } + + @PutMapping("{intraId}") + public ResponseEntity doModifyUser(@Valid @RequestBody UserModifyRequestDto userModifyRequestDto, + @PathVariable String intraId, @Parameter(hidden = true) @Login UserDto loginUser) { + if (!loginUser.getIntraId().equals(intraId)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + userService.updateUser(userModifyRequestDto.getRacketType(), userModifyRequestDto.getStatusMessage(), + userModifyRequestDto.getSnsNotiOpt(), intraId); + return ResponseEntity.noContent().build(); + } + + @PostMapping("/logout") + public void logout(HttpServletResponse response) { + cookieUtil.deleteCookie(response, TokenHeaders.REFRESH_TOKEN); + } + + /** + * 42user ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์—ฐ๋™ ํ•ด์ œ + */ + @DeleteMapping("/oauth/kakao") + public void deleteOauthKakao(@Parameter(hidden = true) @Login UserDto user) { + if (user.getRoleType().equals(RoleType.GUEST) || user.getKakaoId() == null) { + throw new KakaoOauth2AlreadyExistException(); + } + userService.deleteKakaoId(user.getId()); + } + + @GetMapping("/oauth") + public UserOauthDto getUserOauth2Information(@Parameter(hidden = true) @Login UserDto user) { + return new UserOauthDto(OauthType.of(user.getRoleType(), user.getKakaoId()).getCode()); + } + + @GetMapping("/top3") + public UserImageResponseDto getUserImage(@RequestParam(required = false) Long seasonId, Mode mode) { + if (mode == Mode.RANK) { + return userService.getRankedUserImagesByPPP(seasonId); + } else { + PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "totalExp")); + return userService.getRankedUserImagesByExp(pageRequest); + } + } + + @PatchMapping("/text-color") + public ResponseEntity updateTextColor(@RequestBody @Valid UserTextColorDto textColorDto, + @Parameter(hidden = true) @Login UserDto user) { + userService.updateTextColor(user.getId(), textColorDto); + return ResponseEntity.noContent().build(); + } + + @PostMapping("/attendance") + public UserAttendanceResponseDto attendUser(@Parameter(hidden = true) @Login UserDto user) { + return userService.attendUser(user.getId()); + } + + @PatchMapping("/edge") + public String updateEdge(@RequestBody @Valid UserEdgeDto userEdgeDto, + @Parameter(hidden = true) @Login UserDto user) { + String edge = userService.updateEdge(user, userEdgeDto); + return "{\"edge\": " + "\"" + edge + "\"" + "}"; + } + + @GetMapping("/coin") + public UserCoinResponseDto getUserCoin(@Parameter(hidden = true) @Login UserDto user) { + return userCoinService.getUserCoin(user.getIntraId()); + } + + @PatchMapping("/background") + public String updateBackground(@RequestBody @Valid UserBackgroundDto userBackgroundDto, + @Parameter(hidden = true) @Login UserDto user) { + String background = userService.updateBackground(user, userBackgroundDto); + return "{\"background\": " + "\"" + background + "\"" + "}"; + } + + @GetMapping("/coinhistory") + public UserCoinHistoryListResponseDto getUserCoinHistory(@ModelAttribute @Valid PageRequestDto coReq, + @Parameter(hidden = true) @Login UserDto user) { + Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); + + return userCoinService.getUserCoinHistory(pageable, user.getIntraId()); + } + + @PostMapping(path = "/profile-image", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, + MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity updateUserProfileImage(@RequestPart(required = false) MultipartFile profileImage, + @RequestPart @Valid UserProfileImageRequestDto userProfileImageRequestDto, + @Parameter(hidden = true) @Login UserDto user) throws IOException { + userService.updateUserProfileImage(user, userProfileImageRequestDto, profileImage); + return ResponseEntity.noContent().build(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserModifyRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserModifyRequestDto.java new file mode 100644 index 000000000..97df4e0bc --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserModifyRequestDto.java @@ -0,0 +1,18 @@ +package gg.pingpong.api.user.user.controller.request; + +import gg.data.user.type.RacketType; +import gg.data.user.type.SnsType; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserModifyRequestDto { + + private RacketType racketType; + private String statusMessage; + private SnsType snsNotiOpt; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserProfileImageRequestDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserProfileImageRequestDto.java new file mode 100644 index 000000000..ea25afffe --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/request/UserProfileImageRequestDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.user.user.controller.request; + +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserProfileImageRequestDto { + @NotNull + private Long receiptId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/CoinHistoryResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/CoinHistoryResponseDto.java new file mode 100644 index 000000000..8fc5badb6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/CoinHistoryResponseDto.java @@ -0,0 +1,21 @@ +package gg.pingpong.api.user.user.controller.response; + +import java.time.LocalDateTime; + +import gg.data.store.CoinHistory; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CoinHistoryResponseDto { + private String history; + private int amount; + private LocalDateTime createdAt; + + public CoinHistoryResponseDto(CoinHistory coinHistory) { + this.history = coinHistory.getHistory(); + this.amount = coinHistory.getAmount(); + this.createdAt = coinHistory.getCreatedAt(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserAttendanceResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserAttendanceResponseDto.java new file mode 100644 index 000000000..88f6cdec6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserAttendanceResponseDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.user.user.controller.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserAttendanceResponseDto { + private int beforeCoin; + private int afterCoin; + private int coinIncrement; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinHistoryListResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinHistoryListResponseDto.java new file mode 100644 index 000000000..cd0229e0f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinHistoryListResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.user.user.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class UserCoinHistoryListResponseDto { + private List useCoinList; + private int totalPage; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinResponseDto.java new file mode 100644 index 000000000..51190a42f --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserCoinResponseDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.user.user.controller.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class UserCoinResponseDto { + private int coin; + + public UserCoinResponseDto(int userCoin) { + this.coin = userCoin; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserDetailResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserDetailResponseDto.java new file mode 100644 index 000000000..9ed2874b5 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserDetailResponseDto.java @@ -0,0 +1,52 @@ +package gg.pingpong.api.user.user.controller.response; + +import gg.data.rank.Tier; +import gg.data.user.User; +import gg.data.user.type.BackgroundType; +import gg.data.user.type.EdgeType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserDetailResponseDto { + private String intraId; + private String userImageUri; + private String racketType; + private String statusMessage; + private Integer level; + private Integer currentExp; + private Integer maxExp; + private Double expRate; + private SnsType snsNotiOpt; + private BackgroundType background; + private String textColor; + private EdgeType edge; + private String tierName; + private String tierImageUri; + + public UserDetailResponseDto(User user, String statusMessage, Tier tier) { + this.intraId = user.getIntraId(); + this.racketType = user.getRacketType().getCode(); + this.userImageUri = user.getImageUri(); + this.statusMessage = statusMessage; + this.snsNotiOpt = user.getSnsNotiOpt(); + this.background = user.getBackground(); + this.textColor = user.getTextColor(); + this.edge = user.getEdge(); + this.tierName = tier.getName(); + this.tierImageUri = tier.getImageUri(); + calculateExpAndLevel(user); + } + + private void calculateExpAndLevel(User user) { + this.currentExp = ExpLevelCalculator.getCurrentLevelMyExp(user.getTotalExp()); + this.maxExp = ExpLevelCalculator.getLevelMaxExp(ExpLevelCalculator.getLevel(user.getTotalExp())); + this.level = ExpLevelCalculator.getLevel(user.getTotalExp()); + this.expRate = (double)(currentExp * 10000 / maxExp) / 100; + } + +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserHistoryResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserHistoryResponseDto.java new file mode 100644 index 000000000..17e0bf3dd --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserHistoryResponseDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.user.user.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.user.dto.UserHistoryData; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class UserHistoryResponseDto { + private List historics; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserImageResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserImageResponseDto.java new file mode 100644 index 000000000..151d19cac --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserImageResponseDto.java @@ -0,0 +1,16 @@ +package gg.pingpong.api.user.user.controller.response; + +import java.util.List; + +import gg.pingpong.api.user.user.dto.UserImageDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserImageResponseDto { + + List userImages; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserLiveResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserLiveResponseDto.java new file mode 100644 index 000000000..780d552f6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserLiveResponseDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.user.user.controller.response; + +import gg.data.game.type.Mode; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UserLiveResponseDto { + private int notiCount; + private String event; + private Mode currentMatchMode; + private Long gameId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserNormalDetailResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserNormalDetailResponseDto.java new file mode 100644 index 000000000..95cdb41ff --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserNormalDetailResponseDto.java @@ -0,0 +1,20 @@ +package gg.pingpong.api.user.user.controller.response; + +import gg.data.user.type.EdgeType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserNormalDetailResponseDto { + private String intraId; + private String userImageUri; + private Boolean isAdmin; + private Boolean isAttended; + private EdgeType edgeType; + private String tierName; + private String tierImageUri; + private Integer level; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserRankResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserRankResponseDto.java new file mode 100644 index 000000000..4418123de --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserRankResponseDto.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.user.controller.response; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@ToString +public class UserRankResponseDto { + private int rank; + private int ppp; + private int wins; + private int losses; + private double winRate; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserSearchResponseDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserSearchResponseDto.java new file mode 100644 index 000000000..71837c14b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/controller/response/UserSearchResponseDto.java @@ -0,0 +1,14 @@ +package gg.pingpong.api.user.user.controller.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserSearchResponseDto { + private List users; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserAccessTokenDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserAccessTokenDto.java new file mode 100644 index 000000000..9774f80b8 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserAccessTokenDto.java @@ -0,0 +1,10 @@ +package gg.pingpong.api.user.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class UserAccessTokenDto { + private String accessToken; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserBackgroundDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserBackgroundDto.java new file mode 100644 index 000000000..a2aec636a --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserBackgroundDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.user.user.dto; + +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserBackgroundDto { + @NotNull + private Long receiptId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserDto.java new file mode 100644 index 000000000..1d95daf26 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserDto.java @@ -0,0 +1,57 @@ +package gg.pingpong.api.user.user.dto; + +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class UserDto { + private Long id; + private String intraId; + private String eMail; + private RacketType racketType; + private RoleType roleType; + private Integer totalExp; + private SnsType snsNotiOpt; + private Long kakaoId; + private String textColor; + private Integer ggCoin; + + public static UserDto from(User user) { + UserDto userDto; + if (user == null) { + userDto = null; + } else { + userDto = UserDto.builder() + .id(user.getId()) + .intraId(user.getIntraId()) + .eMail(user.getEMail()) + .racketType(user.getRacketType()) + .roleType(user.getRoleType()) + .totalExp(user.getTotalExp()) + .snsNotiOpt(user.getSnsNotiOpt()) + .kakaoId(user.getKakaoId()) + .ggCoin(user.getGgCoin()) + .build(); + } + return userDto; + } + + @Override + public String toString() { + return "UserDto{" + + "id=" + id + + ", intraId='" + intraId + '\'' + + ", eMail='" + eMail + '\'' + + ", racketType=" + racketType + + ", roleType=" + roleType + + ", totalExp=" + totalExp + + ", snsNotiOpt=" + snsNotiOpt + + ", kakaoId=" + kakaoId + + '}'; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserEdgeDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserEdgeDto.java new file mode 100644 index 000000000..c4c96e4af --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserEdgeDto.java @@ -0,0 +1,15 @@ +package gg.pingpong.api.user.user.dto; + +import javax.validation.constraints.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserEdgeDto { + @NotNull + private Long receiptId; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserHistoryData.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserHistoryData.java new file mode 100644 index 000000000..6648c9f6b --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserHistoryData.java @@ -0,0 +1,19 @@ +package gg.pingpong.api.user.user.dto; + +import java.time.LocalDateTime; + +import gg.data.game.PChange; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserHistoryData { + private int ppp; + private LocalDateTime date; + + public UserHistoryData(PChange pChange) { + this.ppp = pChange.getPppResult(); + this.date = pChange.getCreatedAt(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserImageDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserImageDto.java new file mode 100644 index 000000000..02fbe549d --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserImageDto.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.user.dto; + +import gg.data.user.User; +import gg.data.user.type.EdgeType; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UserImageDto { + private String intraId; + private String imageUri; + private EdgeType edge; + private String tierImage; + + public UserImageDto(String intraId, String imageUri, EdgeType edge, String tierImage) { + this.intraId = intraId; + this.imageUri = imageUri; + this.edge = edge; + this.tierImage = tierImage; + } + + public UserImageDto(User user) { + this.intraId = (user == null) ? null : user.getIntraId(); + this.imageUri = (user == null) ? null : user.getImageUri(); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserOauthDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserOauthDto.java new file mode 100644 index 000000000..0a595b409 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserOauthDto.java @@ -0,0 +1,10 @@ +package gg.pingpong.api.user.user.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class UserOauthDto { + private String oauthType; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserTextColorDto.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserTextColorDto.java new file mode 100644 index 000000000..4228807ad --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/dto/UserTextColorDto.java @@ -0,0 +1,17 @@ +package gg.pingpong.api.user.user.dto; + +import com.sun.istack.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class UserTextColorDto { + @NotNull + private Long receiptId; + @NotNull + private String textColor; +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserAuthenticationService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserAuthenticationService.java new file mode 100644 index 000000000..cc79e0045 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserAuthenticationService.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.user.user.service; + +import org.springframework.stereotype.Service; + +import gg.pingpong.api.global.security.jwt.repository.JwtRedisRepository; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.exception.user.TokenNotValidException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserAuthenticationService { + private final JwtRedisRepository jwtRedisRepository; + private final AuthTokenProvider tokenProvider; + + /** + * Refresh ํ† ํฐ์œผ๋กœ Access ํ† ํฐ์„ ์žฌ๋ฐœ๊ธ‰. + * @throws TokenNotValidException ์ผ์น˜ํ•˜๋Š” Refresh ํ† ํฐ ์—†๋Š” ๊ฒฝ์šฐ + * @param refreshToken Refresh ํ† ํฐ + * @return String Access ํ† ํฐ + */ + public String regenerate(String refreshToken) { + Long userId = jwtRedisRepository.getUserIdFromRefToken(refreshToken); + if (userId == null) { + throw new TokenNotValidException(); + } + return tokenProvider.createToken(userId); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserCoinService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserCoinService.java new file mode 100644 index 000000000..afa6c7408 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserCoinService.java @@ -0,0 +1,43 @@ +package gg.pingpong.api.user.user.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.CoinHistory; +import gg.data.user.User; +import gg.pingpong.api.user.user.controller.response.CoinHistoryResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinHistoryListResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinResponseDto; +import gg.repo.store.CoinHistoryRepository; +import gg.repo.user.UserRepository; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Service +public class UserCoinService { + private final UserRepository userRepository; + private final CoinHistoryRepository coinHistoryRepository; + + @Transactional(readOnly = true) + public UserCoinResponseDto getUserCoin(String intraId) { + int userCoin = userRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()).getGgCoin(); + + return new UserCoinResponseDto(userCoin); + } + + @Transactional(readOnly = true) + public UserCoinHistoryListResponseDto getUserCoinHistory(Pageable pageable, String intraId) { + User user = userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + + Page coinHistories = coinHistoryRepository.findAllByUserOrderByIdDesc(user, pageable); + Page coinHistoryResponseDtos = coinHistories.map(CoinHistoryResponseDto::new); + UserCoinHistoryListResponseDto responseDto = new UserCoinHistoryListResponseDto( + coinHistoryResponseDtos.getContent(), + coinHistoryResponseDtos.getTotalPages()); + + return responseDto; + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserFindService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserFindService.java new file mode 100644 index 000000000..0f6f6a7d6 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserFindService.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.user.user.service; + +import java.time.LocalDateTime; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.rank.RedisDataNotFoundException; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserFindService { + private final UserRepository userRepository; + private final SeasonFindService seasonFindService; + private final RankRedisRepository rankRedisRepository; + + @Transactional(readOnly = true) + public User findUserById(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + } + + @Transactional(readOnly = true) + public User findByIntraId(String intraId) { + return userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); + } + + @Transactional(readOnly = true) + public String getUserStatusMessage(User targetUser) { + Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); + try { + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, targetUser.getId()); + return userRank.getStatusMessage(); + } catch (RedisDataNotFoundException e) { + return ""; + } + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserService.java new file mode 100644 index 000000000..eeae4bcdc --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserService.java @@ -0,0 +1,400 @@ +package gg.pingpong.api.user.user.service; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.game.type.StatusType; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.data.user.type.BackgroundType; +import gg.data.user.type.EdgeType; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.utils.ExpLevelCalculator; +import gg.pingpong.api.global.utils.aws.AsyncNewUserImageUploader; +import gg.pingpong.api.user.rank.service.RankFindService; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.store.service.UserCoinChangeService; +import gg.pingpong.api.user.user.controller.request.UserProfileImageRequestDto; +import gg.pingpong.api.user.user.controller.response.UserAttendanceResponseDto; +import gg.pingpong.api.user.user.controller.response.UserDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserHistoryResponseDto; +import gg.pingpong.api.user.user.controller.response.UserImageResponseDto; +import gg.pingpong.api.user.user.controller.response.UserLiveResponseDto; +import gg.pingpong.api.user.user.controller.response.UserNormalDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserRankResponseDto; +import gg.pingpong.api.user.user.dto.UserBackgroundDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.pingpong.api.user.user.dto.UserEdgeDto; +import gg.pingpong.api.user.user.dto.UserHistoryData; +import gg.pingpong.api.user.user.dto.UserImageDto; +import gg.pingpong.api.user.user.dto.UserTextColorDto; +import gg.repo.game.GameRepository; +import gg.repo.game.PChangeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.noti.NotiRepository; +import gg.repo.rank.RankRepository; +import gg.repo.rank.RankV2Dto; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.user.UserImageRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.exception.pchange.PChangeNotExistException; +import gg.utils.exception.rank.RankNotFoundException; +import gg.utils.exception.rank.RedisDataNotFoundException; +import gg.utils.exception.receipt.ReceiptNotFoundException; +import gg.utils.exception.tier.TierNotFoundException; +import gg.utils.exception.user.UserImageLargeException; +import gg.utils.exception.user.UserImageNullException; +import gg.utils.exception.user.UserImageTypeException; +import gg.utils.exception.user.UserNotFoundException; +import gg.utils.exception.user.UserTextColorException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserFindService userFindService; + private final UserRepository userRepository; + private final NotiRepository notiRepository; + private final GameRepository gameRepository; + private final RankRedisRepository rankRedisRepository; + private final SeasonFindService seasonFindService; + private final PChangeRepository pChangeRepository; + private final RankFindService rankFindService; + private final RedisMatchUserRepository redisMatchUserRepository; + private final UserCoinChangeService userCoinChangeService; + private final CoinHistoryService coinHistoryService; + private final ReceiptRepository receiptRepository; + private final AsyncNewUserImageUploader asyncNewUserImageUploader; + private final UserImageRepository userImageRepository; + private final ItemService itemService; + private final TierRepository tierRepository; + private final RankRepository rankRepository; + + /** + * @param intraId + * @return intraId๊ฐ€ ํฌํ•จ๋œ ์œ ์ €๋“ค์˜ intraId๋ฅผ ํŽ˜์ด์ง• ๊ด€๊ณ„์—†์ด ์ตœ๋Œ€ 5๊ฐœ๊นŒ์ง€ ๊ฒ€์ƒ‰ํ•˜์—ฌ List๋กœ return + */ + @Transactional(readOnly = true) + public List findByPartOfIntraId(String intraId) { + Pageable pageable = PageRequest.of(0, 5, Sort.by("intraId").ascending()); + Page pageUsers = userRepository.findByIntraIdContains(pageable, intraId); + return pageUsers.getContent().stream().map(User::getIntraId) + .collect(Collectors.toList()); + } + + /** + * @param user - event: + * - null โ†’ ๋กœ๊ทธ์ธ ์œ ์ €๊ฐ€ ์žกํžŒ ๋งค์นญ์ด ํ•˜๋‚˜๋„ ์—†์„ ๋•Œ + * - match โ†’ ๋งค์นญ์€ ๋˜์—ˆ์œผ๋‚˜ ๊ฒŒ์ž„์‹œ์ž‘ ์ „์ผ ๋•Œ or ๋งค์นญ์ค‘์ธ ๊ฒฝ์šฐ + * - game โ†’ ์œ ์ €๊ฐ€ ๊ฒŒ์ž„์ด ์žกํ˜”๊ณ  ํ˜„์žฌ ๊ฒŒ์ž„์ค‘์ธ ๊ฒฝ์šฐ + *

+ * - currentMatchMode + * - normal + * - rank + * - null -> ๋งค์นญ์ด ์•ˆ์žกํ˜”์„ ๋•Œ or ๊ฒŒ์ž„ ์ „ + */ + @Transactional() + public UserLiveResponseDto getUserLiveDetail(UserDto user) { + int notiCnt = notiRepository.countNotCheckedNotiByUser(user.getId()); + Optional optionalGame = gameRepository.getLatestGameByUser(user.getId()); + int userMatchCnt = redisMatchUserRepository.countMatchTime(user.getId()); + if (optionalGame.isPresent()) { + Game game = optionalGame.get(); + if (game.getStatus() == StatusType.LIVE || game.getStatus() == StatusType.WAIT) { + return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); + } else if (game.getStatus() == StatusType.END) { + PChange userPChange = pChangeRepository.findPChangeByUserIdAndGameId(user.getId(), game.getId()) + .orElseThrow(() -> new PChangeNotExistException()); + if (!userPChange.getIsChecked()) { + userPChange.checkPChange(); + return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); + } + } + + if (game.getStatus() == StatusType.BEFORE) { + return new UserLiveResponseDto(notiCnt, "match", null, null); + } + } + if (userMatchCnt > 0) { + return new UserLiveResponseDto(notiCnt, "match", null, null); + } + return new UserLiveResponseDto(notiCnt, null, null, null); + } + + @Transactional(readOnly = true) + public UserDetailResponseDto getUserDetail(String targetUserIntraId) { + User targetUser = userFindService.findByIntraId(targetUserIntraId); + String statusMessage = userFindService.getUserStatusMessage(targetUser); + Tier tier; + try { + tier = rankFindService.findByUserIdAndSeasonId(targetUser.getId(), + seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + } catch (RankNotFoundException e) { + tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + } + return new UserDetailResponseDto(targetUser, statusMessage, tier); + } + + @Transactional + public void updateUser(RacketType racketType, String statusMessage, SnsType snsNotiOpt, String intraId) { + User user = userFindService.findByIntraId(intraId); + Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + updateRedisRankStatusMessage(statusMessage, user, currentSeason); + updateRankTableStatusMessage(user.getId(), statusMessage, currentSeason.getId()); + user.updateTypes(racketType, snsNotiOpt); + } + + private void updateRankTableStatusMessage(Long userId, String statusMessage, Long seasonId) { + Rank rank = rankFindService.findByUserIdAndSeasonId(userId, seasonId); + rank.setStatusMessage(statusMessage); + } + + private void updateRedisRankStatusMessage(String statusMessage, User user, Season currentSeason) { + String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); + + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); + userRank.setStatusMessage(statusMessage); + rankRedisRepository.updateRankData(hashKey, user.getId(), userRank); + } + + /** + * @param intraId + * @param seasonId seasonId == 0 -> current season, else -> ํ•ด๋‹น Id๋ฅผ ๊ฐ€์ง„ season์˜ ๋ฐ์ดํ„ฐ + *

+ * ๊ธฐ์กด ์ฟผ๋ฆฌ + * @return ์œ ์ €์˜ ์ตœ๊ทผ 10๊ฐœ์˜ ๋žญํฌ ๊ฒฝ๊ธฐ ๊ธฐ๋ก + * @Query(nativeQuery = true, value = "SELECT * FROM pchange " + + * "where game_id in (SELECT id FROM game where season = :season and mode = :mode ) " + + * "AND user_id = :intraId ORDER BY id Desc limit :limit") + * -> Limit์—๋Š” 10์ด ๊ธฐ๋ณธ์œผ๋กœ ๋“ค์–ด๊ฐ + */ + @Transactional(readOnly = true) + public UserHistoryResponseDto getUserHistory(String intraId, Long seasonId) { + Season season; + if (seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + List pChanges = pChangeRepository.findPChangesHistory(intraId, season.getId()); + List historyData = pChanges.stream().map(UserHistoryData::new).collect(Collectors.toList()); + Collections.reverse(historyData); + return new UserHistoryResponseDto(historyData); + } + + /** + * @param targetUserIntraId + * @param seasonId seasonId == 0 -> current season, else -> ํ•ด๋‹น Id๋ฅผ ๊ฐ€์ง„ season์˜ ๋ฐ์ดํ„ฐ + * @return + */ + @Transactional(readOnly = true) + public UserRankResponseDto getUserRankDetail(String targetUserIntraId, Long seasonId) { + Season season; + if (seasonId == 0) { + season = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + season = seasonFindService.findSeasonById(seasonId); + } + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + User user = userFindService.findByIntraId(targetUserIntraId); + try { + Long userRanking = rankRedisRepository.getRankInZSet(zSetKey, user.getId()); + userRanking += 1; + RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); + double winRate = (double)(userRank.getWins() * 10000 / (userRank.getWins() + userRank.getLosses())) / 100; + return new UserRankResponseDto(userRanking.intValue(), userRank.getPpp(), userRank.getWins(), + userRank.getLosses(), winRate); + } catch (RedisDataNotFoundException ex) { + return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); + } catch (ArithmeticException ex2) { + return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); + } + } + + public User getUser(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + } + + @Transactional + public void deleteKakaoId(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + user.updateKakaoId(null); + } + + @Transactional(readOnly = true) + public UserImageResponseDto getRankedUserImagesByPPP(Long seasonId) { + Season targetSeason; + + if (seasonId == 0) { + targetSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); + } else { + targetSeason = seasonFindService.findSeasonById(seasonId); + } + try { + List userImages = new ArrayList<>(); + List dtos = rankRepository.findPppRankBySeasonId(0, 3, targetSeason.getId()); + List users = userRepository.findByIntraIdIn( + dtos.stream().map(RankV2Dto::getIntraId).collect(Collectors.toList())); + for (RankV2Dto dto : dtos) { + User user = users.stream() + .filter(u -> u.getIntraId().equals(dto.getIntraId())) + .findFirst() + .orElseThrow(UserNotFoundException::new); + userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), + user.getEdge(), dto.getTierImageUri())); + } + return new UserImageResponseDto(userImages); + } catch (RedisDataNotFoundException ex) { + return new UserImageResponseDto(new ArrayList<>()); + } + } + + public UserImageResponseDto getRankedUserImagesByExp(PageRequest pageRequest) { + List users = userRepository.findAll(pageRequest).getContent(); + List userImages = new ArrayList<>(); + for (User user : users) { + Tier tier = rankFindService.findByUserIdAndSeasonId(user.getId(), + seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), user.getEdge(), tier.getImageUri())); + } + return new UserImageResponseDto(userImages); + } + + @Transactional + public UserAttendanceResponseDto attendUser(Long userId) { + User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + int plus = userCoinChangeService.addAttendanceCoin(user); + + return new UserAttendanceResponseDto(user.getGgCoin() - plus, user.getGgCoin(), plus); + } + + @Transactional + public UserNormalDetailResponseDto getUserNormalDetail(UserDto user) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Boolean isAdmin = user.getRoleType() == RoleType.ADMIN; + Boolean isAttended = coinHistoryService.hasAttendedToday(loginUser); + Integer level = ExpLevelCalculator.getLevel(user.getTotalExp()); + Tier tier; + try { + tier = rankFindService.findByUserIdAndSeasonId(user.getId(), + seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); + } catch (RankNotFoundException ex) { + // ์นด์นด์˜ค ์œ ์ €๋‚˜ Rank๊ฐ€ ์—†๋Š” ์œ ์ € + tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + } + return new UserNormalDetailResponseDto(user.getIntraId(), loginUser.getImageUri(), isAdmin, isAttended, + loginUser.getEdge(), tier.getName(), tier.getImageUri(), level); + } + + @Transactional() + public void updateTextColor(Long userId, UserTextColorDto textColorDto) { + String textColor = textColorDto.getTextColor(); + Receipt receipt = receiptRepository.findById(textColorDto.getReceiptId()) + .orElseThrow(ReceiptNotFoundException::new); + User loginUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); + + if (!UserTextColorCheckService.check(textColor)) { + throw new UserTextColorException(); + } + + itemService.checkItemType(receipt, ItemType.TEXT_COLOR); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateTextColor(textColor); + receipt.updateStatus(ItemStatus.USED); + } + + @Transactional + public String updateEdge(UserDto user, UserEdgeDto userEdgeDto) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + EdgeType edgeType = EdgeType.getRandomEdgeType(); + Receipt receipt = receiptRepository.findById(userEdgeDto.getReceiptId()) + .orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.EDGE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateEdge(edgeType); + receipt.updateStatus(ItemStatus.USED); + + return edgeType.toString(); + } + + @Transactional + public String updateBackground(UserDto user, UserBackgroundDto userBackgroundDto) { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + BackgroundType backgroundType = BackgroundType.getRandomBackgroundType(); + Receipt receipt = receiptRepository.findById(userBackgroundDto.getReceiptId()) + .orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.BACKGROUND); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + loginUser.updateBackground(backgroundType); + receipt.updateStatus(ItemStatus.USED); + + return backgroundType.toString(); + } + + @Transactional + public void updateUserProfileImage(UserDto user, UserProfileImageRequestDto userProfileImageRequestDto, + MultipartFile userImageFile) throws IOException { + User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); + Receipt receipt = receiptRepository.findById(userProfileImageRequestDto.getReceiptId()) + .orElseThrow(ReceiptNotFoundException::new); + + itemService.checkItemType(receipt, ItemType.PROFILE_IMAGE); + itemService.checkItemOwner(loginUser, receipt); + itemService.checkItemStatus(receipt); + + if (userImageFile == null) { + throw new UserImageNullException(); + } + if (userImageFile.getSize() > 50000) { + throw new UserImageLargeException(); + } else if (userImageFile.getContentType() == null || !userImageFile.getContentType().equals("image/jpeg")) { + throw new UserImageTypeException(); + } + + UserImage userImage = userImageRepository.findTopByUserAndIsCurrentIsTrueOrderByIdDesc(loginUser) + .orElseThrow(UserImageNullException::new); + userImage.updateIsCurrent(); + asyncNewUserImageUploader.update(user.getIntraId(), userImageFile); + receipt.updateStatus(ItemStatus.USED); + } +} diff --git a/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserTextColorCheckService.java b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserTextColorCheckService.java new file mode 100644 index 000000000..34614ca41 --- /dev/null +++ b/gg-pingpong-api/src/main/java/gg/pingpong/api/user/user/service/UserTextColorCheckService.java @@ -0,0 +1,29 @@ +package gg.pingpong.api.user.user.service; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class UserTextColorCheckService { + public static boolean check(String textColor) { + if (textColor == null) { + return false; + } + if (textColor.length() != 7) { + return false; + } + if (textColor.charAt(0) != '#') { + return false; + } + for (int i = 1; i < 7; i++) { + char charTestColor = textColor.charAt(i); + if (!((charTestColor >= '0' && charTestColor <= '9') || (charTestColor >= 'a' && charTestColor <= 'f') || ( + charTestColor >= 'A' && charTestColor <= 'F'))) { + return false; + } + } + return true; + } +} diff --git a/src/main/resources/db/migration/V1.1__migration_42gg_5th.sql b/gg-pingpong-api/src/main/resources/db/migration/V1.1__migration_42gg_5th.sql similarity index 100% rename from src/main/resources/db/migration/V1.1__migration_42gg_5th.sql rename to gg-pingpong-api/src/main/resources/db/migration/V1.1__migration_42gg_5th.sql diff --git a/src/main/resources/db/migration/V1.2__update_tournament_content_column.sql b/gg-pingpong-api/src/main/resources/db/migration/V1.2__update_tournament_content_column.sql similarity index 100% rename from src/main/resources/db/migration/V1.2__update_tournament_content_column.sql rename to gg-pingpong-api/src/main/resources/db/migration/V1.2__update_tournament_content_column.sql diff --git a/src/main/resources/db/migration/V1__init.sql b/gg-pingpong-api/src/main/resources/db/migration/V1__init.sql similarity index 100% rename from src/main/resources/db/migration/V1__init.sql rename to gg-pingpong-api/src/main/resources/db/migration/V1__init.sql diff --git a/src/main/resources/logback-spring.xml b/gg-pingpong-api/src/main/resources/logback-spring.xml similarity index 94% rename from src/main/resources/logback-spring.xml rename to gg-pingpong-api/src/main/resources/logback-spring.xml index 596304b67..9918591b4 100644 --- a/src/main/resources/logback-spring.xml +++ b/gg-pingpong-api/src/main/resources/logback-spring.xml @@ -1,7 +1,7 @@ - + @@ -81,15 +81,15 @@ - - + + - - + + - \ No newline at end of file + diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/ServerPingpongApiApplicationTests.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/ServerPingpongApiApplicationTests.java new file mode 100644 index 000000000..d6350dc89 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/ServerPingpongApiApplicationTests.java @@ -0,0 +1,25 @@ +package gg.pingpong.api; + +import java.util.TimeZone; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +class ServerPingpongApiApplicationTests { + + @Test + void contextLoads() { + } + + @Test + @DisplayName("TimeZone Test") + public void timeZoneTest() throws Exception { + TimeZone tz = TimeZone.getDefault(); + + Assertions.assertThat(tz.getID()).isEqualTo("Asia/Seoul"); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerFailTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerFailTest.java new file mode 100644 index 000000000..f16fdb198 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerFailTest.java @@ -0,0 +1,75 @@ +package gg.pingpong.api.admin.announcement.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.AnnouncementAdminRepository; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +public class AnnouncementAdminControllerFailTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + AnnouncementAdminRepository announcementAdminRepository; + + @Test + @DisplayName("fail currentPage[Get]/pingpong/admin/announcement") + void failAnnouncementList1() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 0; + Integer pageSize = 5; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("fail pageSize[Get]/pingpong/admin/announcement") + void failAnnouncementList2() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 2; + Integer pageSize = 0; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerTest.java new file mode 100644 index 000000000..bfa486b51 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerTest.java @@ -0,0 +1,152 @@ +package gg.pingpong.api.admin.announcement.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.AnnouncementAdminRepository; +import gg.data.manage.Announcement; +import gg.pingpong.api.admin.manage.controller.response.AnnouncementAdminListResponseDto; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.announcement.AnnounceNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class AnnouncementAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + AnnouncementAdminRepository announcementAdminRepository; + + @Test + @DisplayName("[Get]/pingpong/admin/announcement") + void getAnnouncementList() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 2; + Integer pageSize = 5; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //ResponseEntity announceListDtoResponse = objectMapper + // .readValue(contentAsString, new TypeReference>() {}); + //AnnouncementAdminListResponseDto announceListDto = announceListDtoResponse.getBody(); + AnnouncementAdminListResponseDto announceListDto = objectMapper.readValue(contentAsString, + AnnouncementAdminListResponseDto.class); + + } + + @Test + @DisplayName("[Post]/pingpong/admin/announcement") + void addAnnouncement() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + testDataUtils.createAnnouncements(testDataUtils.createAdminUser(), 20); + //๊ณต์ง€์‚ฌํ•ญ 1๊ฐœ ์ •์ฑ… ๋•Œ๋ฌธ์— ๊ธฐ์กด ๊ณต์ง€์‚ฌํ•ญ ์ง€์šธ ๊ฒƒ + Announcement delDto = announcementAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new AnnounceNotFoundException()); + announcementAdminRepository.delete(delDto); + + AnnouncementAdminAddDto addDto = new AnnouncementAdminAddDto("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜", "testId"); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/announcement"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + Announcement result = announcementAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new AnnounceNotFoundException()); + + assertThat(result.getContent()).isEqualTo(addDto.getContent()); + assertThat(result.getCreatorIntraId()).isEqualTo(addDto.getCreatorIntraId()); + assertThat(result.getDeletedAt()).isNull(); + } + + @Test + @DisplayName("fail[Post]/pingpong/admin/announcement") + void addAnnouncementFail() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + AnnouncementAdminAddDto addDto = new AnnouncementAdminAddDto("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜", null); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/announcement"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + + } + + @Test + @DisplayName("[Put]/pingpong/admin/announcement") + void putAnnouncement() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + testDataUtils.createAnnouncement(testDataUtils.createAdminUser(), "testContent"); + + //๊ณต์ง€์‚ฌํ•ญ 1๊ฐœ ์ •์ฑ… ๋•Œ๋ฌธ์— ๊ธฐ์กด ๊ณต์ง€์‚ฌํ•ญ ์ง€์šธ ๊ฒƒ + // Announcement delDto = announcementAdminRepository.findFirstByOrderByIdDesc(); + // announcementAdminRepository.delete(delDto); + //๊ณต์ง€์‚ฌํ•ญ ์—†์œผ๋ฉด ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ณผ์ • ๋„ฃ์–ด ์ค„๊ฒƒ + + String url = "/pingpong/admin/announcement/"; + + String contentAsString = mockMvc.perform(delete(url + "deleterTestId") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + Announcement result = announcementAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new AnnounceNotFoundException()); + + assertThat(result.getDeleterIntraId()).isEqualTo("deleterTestId"); + assertThat(result.getDeletedAt()).isNotNull(); + System.out.println(result.getId()); + System.out.println(result.getDeleterIntraId()); + System.out.println(result.getDeletedAt()); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerUnitTest.java new file mode 100644 index 000000000..bea390428 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/controller/AnnouncementAdminControllerUnitTest.java @@ -0,0 +1,62 @@ +package gg.pingpong.api.admin.announcement.controller; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Pageable; + +import gg.pingpong.api.admin.manage.controller.AnnouncementAdminController; +import gg.pingpong.api.admin.manage.controller.response.AnnouncementAdminListResponseDto; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.pingpong.api.admin.manage.service.AnnouncementAdminService; +import gg.pingpong.api.global.dto.PageRequestDto; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("AnnouncementAdminControllerUnitTest") +class AnnouncementAdminControllerUnitTest { + @Mock + AnnouncementAdminService announcementAdminService; + @InjectMocks + AnnouncementAdminController announcementAdminController; + + @Nested + @DisplayName("GetAnnouncementList_๋ฉ”์„œ๋“œ_unitTest") + class GetAnnouncementList { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + given(announcementAdminService.findAllAnnouncement(any(Pageable.class))).willReturn( + new AnnouncementAdminListResponseDto()); + announcementAdminController.getAnnouncementList(new PageRequestDto(1, 5)); + } + } + + @Nested + @DisplayName("AddAnnouncement_๋ฉ”์„œ๋“œ_unitTest") + class AddAnnouncement { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + announcementAdminController.addAnnouncement(mock(AnnouncementAdminAddDto.class)); + } + } + + @Nested + @DisplayName("AnnouncementModify_๋ฉ”์„œ๋“œ_unitTest") + class AnnouncementModify { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + announcementAdminController.announcementModify("deleterIntraId"); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/service/AnnouncementAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/service/AnnouncementAdminServiceUnitTest.java new file mode 100644 index 000000000..c2c7c09de --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/announcement/service/AnnouncementAdminServiceUnitTest.java @@ -0,0 +1,122 @@ +package gg.pingpong.api.admin.announcement.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.admin.repo.manage.AnnouncementAdminRepository; +import gg.data.manage.Announcement; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.pingpong.api.admin.manage.service.AnnouncementAdminService; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.announcement.AnnounceDupException; +import gg.utils.exception.announcement.AnnounceNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("AnnouncementAdminServiceUnitTest") +class AnnouncementAdminServiceUnitTest { + @Mock + AnnouncementAdminRepository announcementAdminRepository; + @InjectMocks + AnnouncementAdminService announcementAdminService; + + @Nested + @DisplayName("findAllAnnouncement_๋ฉ”์„œ๋“œ_unitTest") + class FindAllAnnouncementTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + List announcementList = new ArrayList<>(); + given(announcementAdminRepository.findAll(any(Pageable.class))) + .willReturn(new PageImpl<>(announcementList)); + announcementAdminService.findAllAnnouncement(mock(Pageable.class)); + verify(announcementAdminRepository, times(1)).findAll(any(Pageable.class)); + } + } + + @Nested + @DisplayName("addAnnouncement_๋ฉ”์„œ๋“œ_unitTest") + class AddAnnouncementTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + String intraId = "intraId"; + LocalDateTime curTime = LocalDateTime.now(); + Announcement announcement = new Announcement(); + announcement.update(intraId, curTime); + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + announcementAdminService.addAnnouncement(new AnnouncementAdminAddDto()); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("AnnounceNotFound") + void announceNotFound() { + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.empty()); + assertThatThrownBy(() -> announcementAdminService.addAnnouncement(new AnnouncementAdminAddDto())) + .isInstanceOf(AnnounceNotFoundException.class); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("Announce_์‚ญ์ œ_์•ˆ๋œ_๊ฒฝ์šฐ") + void announceNotDeleted() { + Announcement announcement = new Announcement(); + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + assertThatThrownBy(() -> announcementAdminService.addAnnouncement(new AnnouncementAdminAddDto())) + .isInstanceOf(AnnounceDupException.class); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + } + + @Nested + @DisplayName("modifyAnnouncementIsDel_๋ฉ”์„œ๋“œ_unitTest") + class ModifyAnnouncementIsDelTest { + final String intraId = "intraId"; + + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + Announcement announcement = new Announcement(); + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + announcementAdminService.modifyAnnouncementIsDel(intraId); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("AnnounceNotFound") + void announceNotFound() { + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.empty()); + assertThatThrownBy(() -> announcementAdminService.modifyAnnouncementIsDel(intraId)) + .isInstanceOf(AnnounceNotFoundException.class); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("์‚ญ์ œ๋œ_Announce_์‚ญ์ œ") + void deleteFail() { + Announcement announcement = new Announcement(); + announcement.update(intraId, LocalDateTime.now()); + given(announcementAdminRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + assertThatThrownBy(() -> announcementAdminService.modifyAnnouncementIsDel(intraId)) + .isInstanceOf(AnnounceNotFoundException.class); + verify(announcementAdminRepository, times(1)).findFirstByOrderByIdDesc(); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinAdminControllerTest.java new file mode 100644 index 000000000..7c793e47c --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinAdminControllerTest.java @@ -0,0 +1,60 @@ +package gg.pingpong.api.admin.coin.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.pingpong.api.admin.store.controller.request.CoinUpdateRequestDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class CoinAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("PUT /pingpong/admin/coin") + public void updateCoinTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String creatorId = userRepository.getById(userId).getIntraId(); + int beforeCoin = userRepository.getById(userId).getGgCoin(); + int changeCoin = 10; + CoinUpdateRequestDto coinUpdateRequestDto = new CoinUpdateRequestDto(creatorId, changeCoin, "๊ด€๋ฆฌ์ž ์ฝ”์ธ ์ง€๊ธ‰ ํ…Œ์ŠคํŠธ"); + mockMvc.perform(put("/pingpong/admin/coin").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(coinUpdateRequestDto))) + .andExpect(status().isNoContent()); + Assertions.assertThat(userRepository.getById(userId).getGgCoin()).isEqualTo(beforeCoin + changeCoin); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerFailTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerFailTest.java new file mode 100644 index 000000000..269e280fc --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerFailTest.java @@ -0,0 +1,62 @@ +package gg.pingpong.api.admin.coin.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.store.CoinPolicyAdminRepository; +import gg.pingpong.api.admin.store.dto.CoinPolicyAdminAddDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +public class CoinPolicyAdminControllerFailTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinPolicyAdminRepository coinPolicyAdminRepository; + + @Test + @DisplayName("[Post FAIL]/pingpong/admin/coinpolicy") + void addAnnouncement() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1, 2, 5, -1); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/coinpolicy"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerTest.java new file mode 100644 index 000000000..b31cc0581 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/controller/CoinPolicyAdminControllerTest.java @@ -0,0 +1,107 @@ +package gg.pingpong.api.admin.coin.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.stream.IntStream; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.store.CoinPolicyAdminRepository; +import gg.data.store.CoinPolicy; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.response.CoinPolicyAdminListResponseDto; +import gg.pingpong.api.admin.store.dto.CoinPolicyAdminAddDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.coin.CoinPolicyNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class CoinPolicyAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinPolicyAdminRepository coinPolicyAdminRepository; + + @Test + @DisplayName("[Get]/pingpong/admin/coinpolicy") + void getCoinPolicy() throws Exception { + User admin = testDataUtils.createAdminUser(); + IntStream.range(0, 3).forEach(i -> testDataUtils + .createCoinPolicy(admin, 1, 2, 3, 4)); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Integer currentPage = 1; + Integer pageSize = 5; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = "/pingpong/admin/coinpolicy?page=" + currentPage + "&size=" + pageSize; + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + CoinPolicyAdminListResponseDto result = objectMapper.readValue(contentAsString, + CoinPolicyAdminListResponseDto.class); + assertThat(result.getCoinPolicyList().size()).isEqualTo(3); + System.out.println(result.getCoinPolicyList().get(0).getCoinPolicyId()); + System.out.println(result.getCoinPolicyList().get(0).getCreateUserId()); + System.out.println(result.getCoinPolicyList().get(0).getAttendance()); + System.out.println(result.getCoinPolicyList().get(0).getNormal()); + System.out.println(result.getCoinPolicyList().get(0).getRankWin()); + System.out.println(result.getCoinPolicyList().get(0).getRankLose()); + + } + + @Test + @DisplayName("[Post]/pingpong/admin/coinpolicy") + void addCoinPolicy() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1, 2, 5, 0); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/admin/coinpolicy"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + CoinPolicy result = coinPolicyAdminRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinPolicyNotFoundException::new); + + assertThat(result.getAttendance()).isEqualTo(addDto.getAttendance()); + assertThat(result.getNormal()).isEqualTo(addDto.getNormal()); + assertThat(result.getRankWin()).isEqualTo(addDto.getRankWin()); + assertThat(result.getRankLose()).isEqualTo(addDto.getRankLose()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/service/CoinAdminServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/service/CoinAdminServiceTest.java new file mode 100644 index 000000000..18e7d0916 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/coin/service/CoinAdminServiceTest.java @@ -0,0 +1,65 @@ +package gg.pingpong.api.admin.coin.service; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.store.CoinHistory; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.request.CoinUpdateRequestDto; +import gg.pingpong.api.admin.store.service.CoinAdminService; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("CoinAdminServiceTest") +class CoinAdminServiceTest { + @Mock + UserRepository userRepository; + @Mock + CoinHistoryService coinHistoryService; + @InjectMocks + CoinAdminService coinAdminService; + + @Nested + @DisplayName("updateUserCoin ๋ฉ”์„œ๋“œ unitTest") + class UpdateUserCoinTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + CoinUpdateRequestDto requestDto = new CoinUpdateRequestDto("testId", 10, "test"); + User user = mock(User.class); + given(userRepository.findByIntraId(any(String.class))).willReturn(Optional.of(user)); + //when + coinAdminService.updateUserCoin(requestDto); + //then + verify(user).addGgCoin(requestDto.getChange()); + verify(coinHistoryService).addCoinHistory(any(CoinHistory.class)); + } + + @Test + @DisplayName("UserNotFound") + void userNotFound() { + //given + CoinUpdateRequestDto requestDto = new CoinUpdateRequestDto("testId", 10, "test"); + given(userRepository.findByIntraId(requestDto.getIntraId())).willReturn(Optional.empty()); + //when, then + Assertions.assertThatThrownBy(() -> coinAdminService.updateUserCoin(requestDto)) + .isInstanceOf(UserNotFoundException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerTest.java new file mode 100644 index 000000000..4f3d7304e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerTest.java @@ -0,0 +1,139 @@ +package gg.pingpong.api.admin.feedback.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.FeedbackAdminRepository; +import gg.data.manage.Feedback; +import gg.data.manage.type.FeedbackType; +import gg.data.user.User; +import gg.pingpong.api.admin.manage.controller.response.FeedbackListAdminResponseDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class FeedbackAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + FeedbackAdminRepository feedbackAdminRepository; + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("[Get]/pingpong/admin/feedback") + void getFeedback() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + for (int i = 0; i < 6; i++) { + Feedback feedback = Feedback.builder() + .category(FeedbackType.ETC) + .content("test" + i) + .user(testDataUtils.createNewUser()) + .build(); + feedbackAdminRepository.save(feedback); + } + + Integer currentPage = 1; + Integer pageSize = 5; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = "/pingpong/admin/feedback?page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, + FeedbackListAdminResponseDto.class); + assertThat(result.getFeedbackList().size()).isEqualTo(5); + System.out.println(result.getFeedbackList().get(0).getId()); + System.out.println(result.getFeedbackList().get(0).getContent()); + + } + + @Test + @DisplayName("[Patch]pingpong/admin/feedback/{id}") + void patchFeedback() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Feedback feedback = Feedback.builder() + .category(FeedbackType.ETC) + .content("test1234") + .user(userRepository.findById(userId).get()) + .build(); + feedbackAdminRepository.save(feedback); + + String url = "/pingpong/admin/feedback/" + feedback.getId().toString(); + Boolean status = feedback.getIsSolved(); + + String contentAsString = mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + } + + @Test + @DisplayName("[get]pingpong/admin/feedback?intraId=${intraId}&page=${pageNumber}&size={size}") + void findFeedbackByIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + User user = userRepository.findById(userId).get(); + + Feedback feedback = Feedback.builder() + .category(FeedbackType.ETC) + .content("test1234") + .user(user) + .build(); + feedbackAdminRepository.save(feedback); + + Integer currentPage = 1; + Integer pageSize = 5; //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ + + String url = + "/pingpong/admin/feedback?intraId=" + user.getIntraId() + "&page=" + currentPage + "&size=" + pageSize; + Boolean status = feedback.getIsSolved(); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, + FeedbackListAdminResponseDto.class); + assertThat(result.getFeedbackList().size()).isBetween(0, 5); + assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); + assertThat(result.getFeedbackList().get(0).getContent()).isEqualTo("test1234"); + assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerUnitTest.java new file mode 100644 index 000000000..be038724f --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/controller/FeedbackAdminControllerUnitTest.java @@ -0,0 +1,67 @@ +package gg.pingpong.api.admin.feedback.controller; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Pageable; + +import gg.pingpong.api.admin.manage.controller.FeedbackAdminController; +import gg.pingpong.api.admin.manage.controller.request.FeedbackAdminPageRequestDto; +import gg.pingpong.api.admin.manage.controller.response.FeedbackListAdminResponseDto; +import gg.pingpong.api.admin.manage.service.FeedbackAdminService; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("FeedbackAdminControllerUnitTest") +class FeedbackAdminControllerUnitTest { + @Mock + FeedbackAdminService feedbackAdminService; + @InjectMocks + FeedbackAdminController feedbackAdminController; + + @Nested + @DisplayName("FeedbackAllUnitTest") + class FeedbackAllUnitTest { + @Test + @DisplayName("successWithIntraId") + public void successWithIntraId() { + //given + FeedbackAdminPageRequestDto requestDto = new FeedbackAdminPageRequestDto("intraId", 2, 2); + given(feedbackAdminService.findByPartsOfIntraId(any(String.class), any(Pageable.class))) + .willReturn(mock(FeedbackListAdminResponseDto.class)); + // when, then + feedbackAdminController.feedbackAll(requestDto); + } + + @Test + @DisplayName("successWithoutIntraId") + public void successWithoutIntraId() { + //given + FeedbackAdminPageRequestDto requestDto = new FeedbackAdminPageRequestDto(null, 2, 2); + given(feedbackAdminService.findAllFeedback(any(Pageable.class))) + .willReturn(mock(FeedbackListAdminResponseDto.class)); + // when, then + feedbackAdminController.feedbackAll(requestDto); + } + } + + @Nested + @DisplayName("FeedbackIsSolvedToggleUnitTest") + class FeedbackIsSolvedToggleUnitTest { + @Test + @DisplayName("success") + public void success() { + // given + // when, then + feedbackAdminController.feedbackIsSolvedToggle(1L); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/service/FeedbackAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/service/FeedbackAdminServiceUnitTest.java new file mode 100644 index 000000000..868de05e8 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/feedback/service/FeedbackAdminServiceUnitTest.java @@ -0,0 +1,92 @@ +package gg.pingpong.api.admin.feedback.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.test.util.ReflectionTestUtils; + +import gg.admin.repo.manage.FeedbackAdminRepository; +import gg.data.manage.Feedback; +import gg.pingpong.api.admin.manage.service.FeedbackAdminService; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.feedback.FeedbackNotFoundException; + +@UnitTest + +@ExtendWith(MockitoExtension.class) +@DisplayName("FeedbackAdminServiceUnitTest") +class FeedbackAdminServiceUnitTest { + @Mock + FeedbackAdminRepository feedbackAdminRepository; + @InjectMocks + FeedbackAdminService feedbackAdminService; + + @Nested + @DisplayName("FindAllFeedbackUnitTest") + class FindAllFeedbackUnitTest { + @Test + @DisplayName("success") + public void success() { + // given + PageImpl feedbackList = new PageImpl<>(new ArrayList<>()); + given(feedbackAdminRepository.findAll(any(Pageable.class))).willReturn(feedbackList); + feedbackAdminService.findAllFeedback(mock(Pageable.class)); + verify(feedbackAdminRepository, times(1)).findAll(any(Pageable.class)); + } + } + + @Nested + @DisplayName("ToggleFeedbackIsSolvedByAdmin") + class ToggleFeedbackIsSolvedByAdmin { + @Test + @DisplayName("success") + public void success() { + // given + Feedback feedback = new Feedback(); + ReflectionTestUtils.setField(feedback, "isSolved", true); + given(feedbackAdminRepository.findById(any(Long.class))).willReturn(Optional.of(feedback)); + // when, then + feedbackAdminService.toggleFeedbackIsSolvedByAdmin(1L); + assertThat(feedback.getIsSolved()).isFalse(); + verify(feedbackAdminRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("feedback_not_found") + public void feedbackNotFound() { + // given + given(feedbackAdminRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> feedbackAdminService.toggleFeedbackIsSolvedByAdmin(1L)) + .isInstanceOf(FeedbackNotFoundException.class); + verify(feedbackAdminRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("FindByPartsOfIntraId") + class FindByPartsOfIntraId { + @Test + @DisplayName("success") + public void success() { + // given + given(feedbackAdminRepository.findFeedbacksByUserIntraId(any(String.class))).willReturn(new ArrayList<>()); + // when, then + feedbackAdminService.findByPartsOfIntraId("intraId", mock(Pageable.class)); + verify(feedbackAdminRepository, times(1)).findFeedbacksByUserIntraId(any(String.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/game/controller/GameAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/game/controller/GameAdminControllerTest.java new file mode 100644 index 000000000..5c7f3b35c --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/game/controller/GameAdminControllerTest.java @@ -0,0 +1,284 @@ +package gg.pingpong.api.admin.game.controller; + +import static java.lang.Thread.*; +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityManager; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.type.Mode; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.admin.game.controller.response.GameLogListAdminResponseDto; +import gg.pingpong.api.admin.game.dto.RankGamePPPModifyReqDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.pingpong.api.user.game.service.GameService; +import gg.pingpong.api.user.match.service.GameUpdateService; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameTeamUser; +import gg.repo.rank.RankRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.dto.GameInfoDto; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@DisplayName("[Admin] Game Admin Controller Integration Test") +class GameAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + GameRepository gameRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + GameUpdateService gameUpdateService; + + @Autowired + GameService gameService; + + @Autowired + RankRepository rankRepository; + + @Autowired + RankRedisRepository rankRedisRepository; + @Autowired + EntityManager entityManager; + + @AfterEach + void redisDown() { + rankRedisRepository.deleteAll(); + } + + @Nested + @DisplayName("[GET] /pingpong/admin/games/users?intraId=${intraId}&page=${pageNumber}&size={sizeNum}") + class GetUserGameList { + String accessToken; + Long userId; + User user; + Season season; + + static final int TOTAL_PAGE_SIZE = 18; + static final int TOURNAMENT_GAME_SIZE = 4; + static final String INTRA_ID = "nheo"; + + @BeforeEach + void setUp() { + accessToken = testDataUtils.getAdminLoginAccessToken(); + userId = tokenProvider.getUserIdFromAccessToken(accessToken); + user = testDataUtils.createNewUser(INTRA_ID); + season = testDataUtils.createSeason(); + testDataUtils.createUserRank(user, "status message", season); + for (int i = 0; i < TOTAL_PAGE_SIZE; i++) { + testDataUtils.createMockMatchWithMockRank(user, season, LocalDateTime.now().minusMinutes(20 + i * 15), + LocalDateTime.now().minusMinutes(5 + i * 15)); + } + for (int i = TOTAL_PAGE_SIZE; i < TOTAL_PAGE_SIZE + TOURNAMENT_GAME_SIZE; i++) { + testDataUtils.createMockMatch(testDataUtils.createNewUser("testUser" + i), season, + LocalDateTime.now().minusMinutes(20 + i * 15), LocalDateTime.now().minusMinutes(5 + i * 15), + Mode.TOURNAMENT); + } + } + + private GameLogListAdminResponseDto getPageResult(int currentPage, int pageSize) + throws Exception { + String url = "/pingpong/admin/games/users?intraId=" + + INTRA_ID + "&page=" + currentPage + "&size=" + pageSize; + + String contentAsString = mockMvc + .perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + return objectMapper.readValue(contentAsString, GameLogListAdminResponseDto.class); + } + + @Test + @Transactional + @DisplayName("First page") + void getUserGameListFirstPage() throws Exception { + //given + int pageSize = 5; + //when + GameLogListAdminResponseDto result = getPageResult(1, pageSize); + //then + assertThat(result.getGameLogList().size()).isEqualTo(pageSize); + } + + @Test + @Transactional + @DisplayName("Middle page") + void getUserGameListMidPage() throws Exception { + //given + int pageSize = 5; + //when + GameLogListAdminResponseDto result = getPageResult(2, pageSize); + //then + assertThat(result.getGameLogList().size()).isEqualTo(pageSize); + } + + @Test + @Transactional + @DisplayName("End page") + void getUserGameListEndPage() throws Exception { + //given + int pageSize = 5; + //when + GameLogListAdminResponseDto result = getPageResult(4, pageSize); + //then + assertThat(result.getGameLogList().size()).isEqualTo(TOTAL_PAGE_SIZE % pageSize); + } + } + + @Test + @DisplayName("[PUT] /pingpong/admin/games ๊ด€๋ฆฌ์ž๊ฒŒ์ž„์ „์ ์ˆ˜์ •ํ…Œ์ŠคํŠธ") + @Transactional + public void admingamestatUpdate() throws Exception { + String url = "/pingpong/admin/games"; + Mode currentMatchMode = Mode.RANK; + Season season = testDataUtils.createSeason(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long adminUserId = tokenProvider.getUserIdFromAccessToken(accessToken); + User adminUser = userRepository.findById(adminUserId).get(); + ArrayList tierList = testDataUtils.createTierSystem("pinpong"); + GameInfoDto game1Info = testDataUtils.createGameWithTierAndRank(adminUser, LocalDateTime.now().minusMinutes(5), + LocalDateTime.now().plusMinutes(5), season, currentMatchMode, tierList.get(0)); + + User enemyUser1 = userRepository.findById(game1Info.getEnemyUserId()).get(); + + RankResultReqDto rankResultReqDto = new RankResultReqDto(game1Info.getGameId(), + game1Info.getMyTeamId(), + 2, + game1Info.getEnemyTeamId(), + 1); + gameService.createRankResult(rankResultReqDto, adminUserId); + + Rank adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + Rank enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), + season.getId()).get(); + // win 1, losses 0, ppp 1020 + // System.out.println("MANGO ADMIN1 before DB PPP : " + adminUserRank.getPpp()); + assertThat(adminUserRank.getLosses()).isEqualTo(0); + assertThat(adminUserRank.getWins()).isEqualTo(1); + // win 0, losses 1, ppp 982 + // System.out.println("MANGO ENEMY1 before DB PPP : " + enemyUser1Rank.getPpp()); + assertThat(enemyUser1Rank.getWins()).isEqualTo(0); + assertThat(enemyUser1Rank.getLosses()).isEqualTo(1); + + RankGamePPPModifyReqDto modifyReqDto = new RankGamePPPModifyReqDto(game1Info.getMyTeamId(), 1, + game1Info.getEnemyTeamId(), 0); + mockMvc.perform(put("/pingpong/admin/games/" + game1Info.getGameId()) + .content(objectMapper.writeValueAsString(modifyReqDto)) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + GameTeamUser historyGame1 = gameRepository.findTeamsByGameIsIn(List.of(game1Info.getGameId())).get(0); + + entityManager.flush(); + entityManager.clear(); + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()) + .get(); + // win 1, losses 0, ppp 1020 + // MANGO ADMIN1 after DB + assertThat(adminUserRank.getPpp()).isEqualTo(1020); + assertThat(adminUserRank.getWins()).isEqualTo(1); + assertThat(adminUserRank.getLosses()).isEqualTo(0); + // win 0, losses 1, ppp 982 + // MANGO ENEMY1 after DB + assertThat(enemyUser1Rank.getWins()).isEqualTo(0); + assertThat(enemyUser1Rank.getLosses()).isEqualTo(1); + assertThat(enemyUser1Rank.getPpp()).isEqualTo(982); + ////////////////////////////// + sleep(1000); + ////////////////////////////// + GameInfoDto game2Info = testDataUtils.createGameWithTierAndRank(adminUser, LocalDateTime.now().minusMinutes(4), + LocalDateTime.now().plusMinutes(6), season, currentMatchMode, tierList.get(0)); + User enemyUser2 = userRepository.findById(game2Info.getEnemyUserId()).get(); + + rankResultReqDto = new RankResultReqDto(game2Info.getGameId(), + game2Info.getMyTeamId(), + 1, + game2Info.getEnemyTeamId(), + 2); + gameService.createRankResult(rankResultReqDto, adminUserId); + + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + Rank enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), + season.getId()).get(); + // win 1, losses 1, ppp 1001 + // MANGO ADMIN2 before DB + assertThat(adminUserRank.getWins()).isEqualTo(1); + assertThat(adminUserRank.getLosses()).isEqualTo(1); + assertThat(adminUserRank.getPpp()).isEqualTo(1001); + // win1, losses 0, ppp 1021 + // MANGO ENEMY2 before DB + assertThat(enemyUser2Rank.getWins()).isEqualTo(1); + assertThat(enemyUser2Rank.getLosses()).isEqualTo(0); + assertThat(enemyUser2Rank.getPpp()).isEqualTo(1021); + + modifyReqDto = new RankGamePPPModifyReqDto(game2Info.getMyTeamId(), 2, game2Info.getEnemyTeamId(), 1); + mockMvc.perform(put("/pingpong/admin/games/" + game2Info.getGameId()) + .content(objectMapper.writeValueAsString(modifyReqDto)) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); + enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); + // win 2, losses 0, ppp 1038 + // System.out.println("MANGO ADMIN2 after DB PPP : " + adminUserRank.getPpp() + ", WIN: " + // + adminUserRank.getWins() + ", LOSSES" + adminUserRank.getLosses()); + assertThat(adminUserRank.getWins()).isEqualTo(2); + assertThat(adminUserRank.getLosses()).isEqualTo(0); + assertThat(adminUserRank.getPpp()).isEqualTo(1038); + // win 0, losses 1, ppp + System.out.println("MANGO ENEMY2 after DB PPP : " + enemyUser2Rank.getPpp() + ", WIN: " + + enemyUser2Rank.getWins() + ", LOSSES" + enemyUser2Rank.getLosses()); + assertThat(enemyUser2Rank.getWins()).isEqualTo(0); + assertThat(enemyUser2Rank.getLosses()).isEqualTo(1); + // assertThat(enemyUser2Rank.getPpp()).isEqualTo() + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/controller/ItemAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/controller/ItemAdminControllerTest.java new file mode 100644 index 000000000..734c16218 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/controller/ItemAdminControllerTest.java @@ -0,0 +1,140 @@ +package gg.pingpong.api.admin.item.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.List; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.store.ItemAdminRepository; +import gg.data.store.Item; +import gg.data.store.type.ItemType; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.admin.store.controller.response.ItemListResponseDto; +import gg.pingpong.api.admin.store.service.ItemAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.utils.ItemImageHandler; +import gg.repo.user.UserRepository; +import gg.utils.ItemTestUtils; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class ItemAdminControllerTest { + @Autowired + ItemAdminService itemAdminService; + @Autowired + UserRepository userRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + ItemAdminRepository itemAdminRepository; + @Autowired + MockMvc mockMvc; + @Autowired + ItemTestUtils itemTestUtils; + @MockBean + ItemImageHandler itemImageHandler; + + Item item; + + @BeforeEach + void setUp() { + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "content", + "subContent", 100, 50, ItemType.EDGE); + item = itemTestUtils.createItem(testDataUtils.createAdminUserForItem(), dto); + } + + @Test + @DisplayName("GET /pingpong/admin/items/history") + public void getAllItemHistoryTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + String url = "/pingpong/admin/items/history?page=" + page + "&size=" + size; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + ItemListResponseDto expect = itemAdminService.getAllItemHistory(pageable); + System.out.println(expect.getHistoryList()); + ItemListResponseDto result = objectMapper.readValue(contentAsString, ItemListResponseDto.class); + System.out.println(expect.getHistoryList().get(0)); + System.out.println(result.getHistoryList().get(0)); + assertThat(result.getHistoryList().get(0).getItemId()); + assertThat(result.getHistoryList().get(0).getName()); + assertThat(result.getHistoryList().get(0).getMainContent()); + assertThat(result.getHistoryList().get(0).getSubContent()); + assertThat(result.getHistoryList().get(0).getPrice()); + } + + @Test + @DisplayName("POST /pingpong/admin/items/history/{itemId}") + public void updateItemTest() throws Exception { + Mockito.when(itemImageHandler.uploadToS3(Mockito.any(), Mockito.anyString())) + .thenAnswer(invocation -> invocation.getArgument(1, String.class)); + + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String creatorId = userRepository.getById(userId).getIntraId(); + MockMultipartFile image = new MockMultipartFile("imgData", "imagefile.jpeg", "image/jpeg", + "<>".getBytes()); + MockMultipartFile jsonFile = new MockMultipartFile("updateItemInfo", "", + "application/json", + ("{\"name\": \"TEST\", " + + "\"mainContent\": \"TESTING\", " + + "\"subContent\": \"TESTING\", " + + "\"price\": 42, " + + "\"discount\": 50, " + + "\"itemType\": \"MEGAPHONE\"}").getBytes()); + String contentAsString = mockMvc.perform(multipart("/pingpong/admin/items/{itemId}", item.getId()) + .file(image) + .file(jsonFile) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("DELETE /pingpong/admin/items/{itemId}") + public void deleteItemTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String deleterId = userRepository.getById(userId).getIntraId(); + + String contentAsString = mockMvc.perform(delete("/pingpong/admin/items/{itemId}", item.getId()) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + List list = itemAdminRepository.findAll(); + assertThat(list.get(0).getDeleterIntraId()).isEqualTo(deleterId); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/service/ItemAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/service/ItemAdminServiceUnitTest.java new file mode 100644 index 000000000..18a30742d --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/item/service/ItemAdminServiceUnitTest.java @@ -0,0 +1,194 @@ +package gg.pingpong.api.admin.item.service; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.web.multipart.MultipartFile; + +import gg.admin.repo.store.ItemAdminRepository; +import gg.data.store.Item; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.admin.store.service.ItemAdminService; +import gg.pingpong.api.global.utils.aws.AsyncNewItemImageUploader; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.item.ItemNotAvailableException; +import gg.utils.exception.item.ItemNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class ItemAdminServiceUnitTest { + @Mock + ItemAdminRepository itemAdminRepository; + @Mock + AsyncNewItemImageUploader asyncNewItemImageUploader; + + @InjectMocks + ItemAdminService itemAdminService; + + User user; + Item item; + + @BeforeEach + void beforeEach() { + item = new Item(); + setFieldWithReflection(item, "isVisible", true); + user = new User("testUser", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + } + + @Nested + @DisplayName("getAllItemHistoryTest") + class GetAllItemHistoryTest { + @Test + @DisplayName("success") + void success() { + // given + given(itemAdminRepository.findAll(any(Pageable.class))).willReturn(new PageImpl<>(new ArrayList<>())); + // when, then + itemAdminService.getAllItemHistory(mock(Pageable.class)); + verify(itemAdminRepository, times(1)).findAll(any(Pageable.class)); + } + } + + @Nested + @DisplayName("updateItemTest ํŒŒ๋ผ๋ฏธํ„ฐ 4๊ฐœ ์งœ๋ฆฌ") + class UpdateItem4ParamsTest { + @Test + @DisplayName("success") + void success() throws Exception { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(itemAdminRepository.save(any(Item.class))).willReturn(mock(Item.class)); + ItemUpdateRequestDto mockRequest = mock(ItemUpdateRequestDto.class); + when(mockRequest.toItem(any(), any())).thenReturn(mock(Item.class)); + + // when, then + itemAdminService.updateItem(1L, mockRequest, + mock(MultipartFile.class), UserDto.from(user)); + setFieldWithReflection(item, "isVisible", true); + + itemAdminService.updateItem(1L, mockRequest, + null, UserDto.from(user)); + verify(itemAdminRepository, times(2)).findById(any(Long.class)); + verify(asyncNewItemImageUploader, times(1)).upload(any(), any()); + verify(itemAdminRepository, times(2)).save(any(Item.class)); + } + + @Test + @DisplayName("ItemNotAvailableTest") + void itemNotAvailableTest() throws Exception { + // given + setFieldWithReflection(item, "isVisible", false); + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + // when, then + assertThatThrownBy( + () -> itemAdminService.updateItem(1L, mock(ItemUpdateRequestDto.class), mock(MultipartFile.class), + UserDto.from(user))) + .isInstanceOf(ItemNotAvailableException.class); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("ItemNotFoundTest") + void itemNotFoundTest() throws Exception { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy( + () -> itemAdminService.updateItem(1L, mock(ItemUpdateRequestDto.class), mock(MultipartFile.class), + UserDto.from(user))) + .isInstanceOf(ItemNotFoundException.class); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("updateItemTest ํŒŒ๋ผ๋ฏธํ„ฐ 3๊ฐœ ์งœ๋ฆฌ") + class UpdateItem3ParamsTest { + @Test + @DisplayName("success") + void success() throws Exception { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(itemAdminRepository.save(any(Item.class))).willReturn(mock(Item.class)); + ItemUpdateRequestDto mockRequest = mock(ItemUpdateRequestDto.class); + when(mockRequest.toItem(any(), any())).thenReturn(mock(Item.class)); + + // when, then + itemAdminService.updateItem(1L, mockRequest, UserDto.from(user)); + assertThat(item.getDeleterIntraId()).isEqualTo(user.getIntraId()); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + verify(itemAdminRepository, times(1)).save(any(Item.class)); + } + + @Test + @DisplayName("ItemNotAvailableTest") + void itemNotAvailableTest() throws Exception { + // given + setFieldWithReflection(item, "isVisible", false); + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + // when, then + assertThatThrownBy( + () -> itemAdminService.updateItem(1L, mock(ItemUpdateRequestDto.class), UserDto.from(user))) + .isInstanceOf(ItemNotAvailableException.class); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("ItemNotFoundTest") + void itemNotFoundTest() throws Exception { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy( + () -> itemAdminService.updateItem(1L, mock(ItemUpdateRequestDto.class), UserDto.from(user))) + .isInstanceOf(ItemNotFoundException.class); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("deleteItemTest") + class DeleteItemTest { + @Test + @DisplayName("success") + void success() { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + // when, then + itemAdminService.deleteItem(1L, UserDto.from(user)); + assertThat(item.getIsVisible()).isFalse(); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("ItemNotFoundTest") + void itemNotFoundTest() { + // given + given(itemAdminRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemAdminService.deleteItem(1L, UserDto.from(user))) + .isInstanceOf(ItemNotFoundException.class); + verify(itemAdminRepository, times(1)).findById(any(Long.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/controller/MegaphoneAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/controller/MegaphoneAdminControllerTest.java new file mode 100644 index 000000000..7a8201a63 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/controller/MegaphoneAdminControllerTest.java @@ -0,0 +1,48 @@ +package gg.pingpong.api.admin.megaphone.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; + +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class MegaphoneAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + AuthTokenProvider tokenProvider; + + @Test + @DisplayName("[GET] /pingpong/admin/megaphones/history?page={page}&size={pageSize}&intraId={intraId}") + void getMegaphoneListTest() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/admin/megaphones/history?page=1&size=30"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/service/MegaphoneAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/service/MegaphoneAdminServiceUnitTest.java new file mode 100644 index 000000000..fcbbe28b0 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/megaphone/service/MegaphoneAdminServiceUnitTest.java @@ -0,0 +1,59 @@ +package gg.pingpong.api.admin.megaphone.service; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.admin.repo.store.MegaphoneAdminRepository; +import gg.pingpong.api.admin.store.service.MegaphoneAdminService; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class MegaphoneAdminServiceUnitTest { + @Mock + MegaphoneAdminRepository megaphoneAdminRepository; + @InjectMocks + MegaphoneAdminService megaphoneAdminService; + + @Nested + @DisplayName("getMegaphoneHistory ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetMegaphoneHistory { + @Test + @DisplayName("success") + void success() { + // given + given(megaphoneAdminRepository.findAll(any(Pageable.class))).willReturn(new PageImpl<>(new ArrayList<>())); + // when, then + megaphoneAdminService.getMegaphoneHistory(mock(Pageable.class)); + verify(megaphoneAdminRepository, times(1)).findAll(any(Pageable.class)); + } + } + + @Nested + @DisplayName("getMegaphoneHistoryByIntraId ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetMegaphoneHistoryByIntraId { + @Test + @DisplayName("success") + void success() { + // given + given(megaphoneAdminRepository.findMegaphonesByUserIntraId(any(String.class), any( + Pageable.class))).willReturn(new PageImpl<>(new ArrayList<>())); + // when, then + megaphoneAdminService.getMegaphoneHistoryByIntraId("testUser", mock(Pageable.class)); + verify(megaphoneAdminRepository, times(1)) + .findMegaphonesByUserIntraId(any(String.class), any(Pageable.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/controller/NotiAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/controller/NotiAdminControllerTest.java new file mode 100644 index 000000000..71343707a --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/controller/NotiAdminControllerTest.java @@ -0,0 +1,150 @@ +package gg.pingpong.api.admin.noti.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.List; +import java.util.UUID; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.noti.NotiAdminRepository; +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.controller.response.NotiListAdminResponseDto; +import gg.pingpong.api.admin.noti.dto.NotiAdminDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.noti.NotiRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +class NotiAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + NotiAdminService notiAdminService; + @Autowired + NotiAdminRepository notiAdminRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + + @Test + @DisplayName("GET /pingpong/admin/notifications") + @Transactional + public void getAllNotiTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + String testMessage = "Test notification"; + notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(user.getIntraId(), testMessage)); + String url = "/pingpong/admin/notifications?page=1&size=20"; + String url2 = "/pingpong/admin/notifications?page=1&q=\"" + user.getIntraId() + "\""; + + //when + //200 ์„ฑ๊ณต(์ „์ฒด์กฐํšŒ) + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, + NotiListAdminResponseDto.class); + //200 ์„ฑ๊ณต(๊ฒ€์ƒ‰์กฐํšŒ) + String contentAsString2 = mockMvc.perform(get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, + NotiListAdminResponseDto.class); + Pageable pageable = PageRequest.of(0, 20); + Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending()); + + //then + List notiList1 = notiAdminRepository.findAll(pageable).getContent(); + List expectedNotiAdminDtoList = actureResponse1.getNotiList(); + for (int i = 0; i < notiList1.size(); i++) { + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIntraId()) + .isEqualTo(expectedNotiAdminDtoList.get(i).getIntraId()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getMessage()) + .isEqualTo(expectedNotiAdminDtoList.get(i).getMessage()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIsChecked()) + .isEqualTo(expectedNotiAdminDtoList.get(i).getIsChecked()); + Assertions.assertThat(expectedNotiAdminDtoList.get(i).getType()) + .isEqualTo(expectedNotiAdminDtoList.get(i).getType()); + } + + List notiList2 = notiRepository.findByUser(user); + Assertions.assertThat(notiList2.size()).isEqualTo(1); + Noti expectedNoti2 = notiList2.get(0); + NotiAdminDto actureNotiResponseDto2 = actureResponse2.getNotiList().get(0); + Assertions.assertThat(expectedNoti2.getUser().getIntraId()).isEqualTo(actureNotiResponseDto2.getIntraId()); + Assertions.assertThat(expectedNoti2.getMessage()).isEqualTo(testMessage); + Assertions.assertThat(expectedNoti2.getIsChecked()).isFalse(); + Assertions.assertThat(expectedNoti2.getType()).isEqualTo(NotiType.ANNOUNCE); + } + + @Test + @DisplayName("POST /pingpong/admin/notifications") + @Transactional + public void sendNotiToUserTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + String url = "/pingpong/admin/notifications"; + String wrongIntraId = UUID.randomUUID().toString().substring(0, 30); + String expectedMessage = "test ์•Œ๋ฆผ message "; + + //when + //201 ์„ฑ๊ณต + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(user.getIntraId(), + expectedMessage)))) + .andExpect(status().isCreated()); + + //404 ์กด์žฌํ•˜์ง€ ์•Š๋Š” intraId + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(wrongIntraId, expectedMessage)))) + .andExpect(status().isNotFound()); + + //then + List notiList = notiRepository.findByUser(user); + Assertions.assertThat(notiList.size()).isEqualTo(1); + Noti actureNoti = notiList.get(0); + Assertions.assertThat(actureNoti.getUser()).isEqualTo(user); + Assertions.assertThat(actureNoti.getMessage()).isEqualTo(expectedMessage); + Assertions.assertThat(actureNoti.getIsChecked()).isFalse(); + Assertions.assertThat(actureNoti.getType()).isEqualTo(NotiType.ANNOUNCE); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/service/NotiAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/service/NotiAdminServiceUnitTest.java new file mode 100644 index 000000000..62a19d4fa --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/noti/service/NotiAdminServiceUnitTest.java @@ -0,0 +1,117 @@ +package gg.pingpong.api.admin.noti.service; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.Collections; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +import gg.admin.repo.noti.NotiAdminRepository; +import gg.admin.repo.user.UserAdminRepository; +import gg.data.noti.Noti; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.user.noti.service.SnsNotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("NotiAdminServiceUnitTest") +class NotiAdminServiceUnitTest { + @Mock + UserAdminRepository userAdminRepository; + @Mock + NotiAdminRepository notiAdminRepository; + @Mock + SnsNotiService snsNotiService; + @Mock + SendNotiAdminRequestDto sendNotiAdminRequestDto; + @InjectMocks + NotiAdminService notiAdminService; + + @Nested + @DisplayName("sendAnnounceNotiToUser_๋ฉ”์„œ๋“œ_unitTest") + class SendAnnounceNotiToUserTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + given(userAdminRepository.findByIntraId(any(String.class))).willReturn(Optional.of(mock(User.class))); + given(notiAdminRepository.save(any(Noti.class))).willReturn(new Noti()); + willDoNothing().given(snsNotiService).sendSnsNotification(any(Noti.class), any(UserDto.class)); + + //when + notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto("TestUser", "Message")); + + //then + verify(userAdminRepository, times(1)).findByIntraId(any(String.class)); + verify(notiAdminRepository, times(1)).save(any(Noti.class)); + verify(snsNotiService, times(1)).sendSnsNotification(any(Noti.class), any(UserDto.class)); + } + + @Test + @DisplayName("user_not_found") + void userNotFound() { + //given + SendNotiAdminRequestDto requestDto = new SendNotiAdminRequestDto("testIntraId", "TestMessage"); + when(userAdminRepository.findByIntraId(any(String.class))).thenThrow(new UserNotFoundException()); + + //when, then + assertThatThrownBy(() -> notiAdminService.sendAnnounceNotiToUser(requestDto)) + .isInstanceOf(UserNotFoundException.class); + verify(notiAdminRepository, never()).save(any(Noti.class)); + verify(snsNotiService, never()).sendSnsNotification(any(Noti.class), any(UserDto.class)); + } + } + + @Nested + @DisplayName("getAllNoti_๋ฉ”์„œ๋“œ_unitTest") + class GetAllNotiTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + given(notiAdminRepository.findAll(any(Pageable.class))).willReturn(new PageImpl<>(Collections.emptyList())); + + //when + notiAdminService.getAllNoti(mock(Pageable.class)); + + //then + verify(notiAdminRepository, times(1)).findAll(any(Pageable.class)); + } + } + + @Nested + @DisplayName("getFilteredNotifications_๋ฉ”์„œ๋“œ_unitTest") + class GetFilteredNotificationsTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + given(notiAdminRepository.findNotisByUserIntraId(any(Pageable.class), + any(String.class))) + .willReturn(new PageImpl<>(Collections.emptyList())); + + //when + notiAdminService.getFilteredNotifications(PageRequest.of(1, 1), "TestUser"); + + //then + verify(notiAdminRepository, times(1)).findNotisByUserIntraId( + any(Pageable.class), any(String.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/penalty/controller/PenaltyAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/penalty/controller/PenaltyAdminControllerTest.java new file mode 100644 index 000000000..c67f02ef6 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/penalty/controller/PenaltyAdminControllerTest.java @@ -0,0 +1,353 @@ +package gg.pingpong.api.admin.penalty.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.PenaltyAdminRepository; +import gg.admin.repo.manage.PenaltyUserAdminRedisRepository; +import gg.data.manage.Penalty; +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.manage.type.PenaltyType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.manage.controller.request.PenaltyRequestDto; +import gg.pingpong.api.admin.manage.controller.response.PenaltyListResponseDto; +import gg.pingpong.api.admin.manage.service.PenaltyAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class PenaltyAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + UserRepository userRepository; + @Autowired + PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; + @Autowired + PenaltyAdminRepository penaltyAdminRepository; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RedisConnectionFactory redisConnectionFactory; + @Autowired + PenaltyAdminService penaltyAdminService; + + private final String headUrl = "/pingpong/admin/"; + + @AfterEach + void clear() { + RedisConnection connection = redisConnectionFactory.getConnection(); + connection.flushDb(); + connection.close(); + } + + @Test + @DisplayName("POST : penalty๋ฅผ ๋ถ€์—ฌ๋ฐ›์ง€ ์•Š์€ ์œ ํšจํ•œ intraId์— penalty ๋ถ€์—ฌ") + public void giveUserPenaltyforFirstTimeWithValidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty"; + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().isCreated()); + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + //redis + Assertions.assertThat(penaltyUser).isPresent(); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(3 * 60); + Assertions.assertThat( + Duration.between(penaltyUser.get().getStartTime(), + penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(3 * 60 * 60); + Assertions.assertThat(penaltyUser.get().getReason()); + //mySQL + List penalties = penaltyAdminRepository.findAll(); + Assertions.assertThat(penalties.stream().anyMatch(ele -> ele.getUser().getIntraId().equals(intraId) + && ele.getPenaltyTime().equals(3 * 60))).isEqualTo(true); + } + + @Test + @DisplayName("POST : penalty๋ฅผ ๋ถ€์—ฌ๋ฐ›์€ ์œ ํšจํ•œ intraId์— penalty ๋ถ€์—ฌ") + public void giveUserPenaltyRepeatablyWithValidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty"; + //ํŒจ๋„ํ‹ฐ ๋‘๋ฒˆ ๋ถ€์—ฌ + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().isCreated()); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 2, "test2")))) + .andExpect(status().isCreated()); + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + //redis ํ™•์ธ + Assertions.assertThat(penaltyUser).isPresent(); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(5 * 60); + Assertions.assertThat( + Duration.between(penaltyUser.get().getStartTime(), + penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(5 * 60 * 60); + Assertions.assertThat(penaltyUser.get().getReason()); + //mySQL ํ™•์ธ + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Assertions.assertThat(userPenalties.size()).isEqualTo(2); + Duration duration = Duration.between(userPenalties.get(0).getStartTime(), userPenalties.get(1).getStartTime()); + Assertions.assertThat(duration.getSeconds()).isEqualTo(3 * 60 * 60); + } + + @Test + @DisplayName("POST ์œ ํšจํ•˜์ง€ ์•Š์€ intraId์— penalty ๋ถ€์—ฌ") + public void giveUserPenaltyWithInvalidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String intraId = "invalid!"; + String url = "/pingpong/admin/penalty"; + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) + .andExpect(status().is4xxClientError()); + } + + @Test + @DisplayName("GET pagination ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") + public void checkPagination() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 20๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ + for (int i = 0; i < 20; i++) { + User newUser = testDataUtils.createNewUser(); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i) + "&size=10¤t=true"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } + + @Test + @DisplayName("GET parameter ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") + public void checkInputException() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/admin/penalty?page=-1&size=10¤t=false"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); + String url2 = "/pingpong/admin/penalty?page=2&size=0¤t=false"; + String contentAsString2 = mockMvc.perform( + get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("GET pagination keyword ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") + public void checkPaginationWithKeyword() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 40๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ + //๊ทธ์ค‘ 20๋ช…๋งŒ intraId์— testํฌํ•จ + for (int i = 0; i < 20; i++) { + String intraId = UUID.randomUUID().toString().substring(0, 4) + "test" + UUID.randomUUID().toString() + .substring(0, 4); + User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, + RoleType.USER); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + for (int i = 0; i < 20; i++) { + String intraId = "dummy" + String.valueOf(i); + User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, + RoleType.USER); + users.add(newUser); + penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); + } + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i) + "&size=10¤t=true&intraId=test"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } + + @Test + @DisplayName("DELETE ํŒจ๋„ํ‹ฐ ์‚ญ์ œ - ์œ ์ € ํŒจ๋„ํ‹ฐ๊ฐ€ 1๋ฒˆ๋งŒ ๋ถ€๊ณผ๋œ ๊ฒฝ์šฐ") + public void deleteExistPenaltyUser() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + penaltyAdminService.givePenalty(intraId, 3, "test!"); + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Long penaltyId = userPenalties.get(0).getId(); + String url = "/pingpong/admin/penalty/" + penaltyId.toString(); + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + //Redis์— penaltyUser ์—†๋Š”์ง€ ํ™•์ธ + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + Assertions.assertThat(penaltyUser).isEmpty(); + //MySQL์— penalty ์—†๋Š”์ง€ ํ™•์ธ + List afterPenalties = penaltyAdminRepository.findAll(); + boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); + Assertions.assertThat(isPresent).isEqualTo(false); + } + + @Test + @DisplayName("DELETE ํŒจ๋„ํ‹ฐ ์‚ญ์ œ - ์œ ์ € ํŒจ๋„ํ‹ฐ๊ฐ€ 2๋ฒˆ ๋ถ€๊ณผ๋œ ๊ฒฝ์šฐ") + public void deleteExistPenaltyUserOfTwicePenalty() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + penaltyAdminService.givePenalty(intraId, 3, "test!"); + penaltyAdminService.givePenalty(intraId, 2, "test2"); + List penalties = penaltyAdminRepository.findAll(); + List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) + .collect(Collectors.toList()); + Long penaltyId = userPenalties.get(0).getId(); + String url = "/pingpong/admin/penalty/" + penaltyId.toString(); + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + //Redis์— penaltyUser ์žˆ๋Š”์ง€ ํ™•์ธ + Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); + Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(2 * 60); + + //MySQL์— penalty ์—†๋Š”์ง€ ํ™•์ธ + List afterPenalties = penaltyAdminRepository.findAll(); + boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); + Assertions.assertThat(isPresent).isEqualTo(false); + } + + @Test + @DisplayName("DELETE ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒจ๋„ํ‹ฐ ์œ ์ € ์‚ญ์ œ") + public void deleteInvalidPenaltyUser() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //user์— ํŒจ๋„ํ‹ฐ๋Š” ๋ถ€์—ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. + User newUser = testDataUtils.createNewUser(); + String intraId = newUser.getIntraId(); + String url = "/pingpong/admin/penalty/users/" + intraId; + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()); + } + + @Test + @DisplayName("DELETE ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒจ๋„ํ‹ฐ ์œ ์ € ์‚ญ์ œ") + public void deleteInvalidIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //30์ž ์ด์ƒ + String intraId = UUID.randomUUID().toString(); + String url = "/pingpong/admin/penalty/users/" + intraId; + mockMvc.perform( + delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()); + } + + @Test + @DisplayName("get pingpong/admin/penalty?page={page}&size={pageSize}¤t=true") + public void getCurrentPenalties() throws Exception { + List users = new ArrayList(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + //penalty user 20๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ + for (int i = 0; i < 20; i++) { + User newUser = testDataUtils.createNewUser(); + users.add(newUser); + } + + //๊ณผ๊ฑฐ penalty๋“ค db์— ์ €์žฅ + for (int i = 0; i < 20; i++) { + Penalty penalty = new Penalty(users.get(i), PenaltyType.NOSHOW, "test", LocalDateTime.now().minusHours(3), + 120); + penaltyAdminRepository.save(penalty); + } + + //ํ˜„์žฌ ํŒจ๋„ํ‹ฐ ๋ถ€์—ฌ + for (int i = 0; i < 20; i++) { + penaltyAdminService.givePenalty(users.get(i).getIntraId(), 3, "test" + String.valueOf(i)); + } + + List sizeCounts = new ArrayList(); + Integer totalPages = -1; + for (int i = 1; i <= 3; i++) { + String url = "/pingpong/admin/penalty?page=" + String.valueOf(i) + "&size=10¤t=true"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, + PenaltyListResponseDto.class); + sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); + totalPages = penaltyListResponseDto.getTotalPage(); + } + Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); + Assertions.assertThat(totalPages).isEqualTo(2); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/controller/ReceiptAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/controller/ReceiptAdminControllerTest.java new file mode 100644 index 000000000..3a157f59e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/controller/ReceiptAdminControllerTest.java @@ -0,0 +1,118 @@ +package gg.pingpong.api.admin.receipt.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.store.ReceiptAdminRepository; +import gg.data.store.Item; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.admin.store.controller.response.ReceiptListResponseDto; +import gg.pingpong.api.admin.store.service.ReceiptAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.ItemTestUtils; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class ReceiptAdminControllerTest { + @Autowired + ReceiptAdminService receiptAdminService; + @Autowired + ReceiptAdminRepository receiptAdminRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + MockMvc mockMvc; + @Autowired + ItemTestUtils itemTestUtils; + Item item; + User user; + + @BeforeEach + void setUp() { + user = testDataUtils.createNewUser(); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", "subContent", + 100, 50, ItemType.EDGE); + item = itemTestUtils.createItem(testDataUtils.createAdminUserForItem(), dto); + } + + @Test + @DisplayName("GET /pingpong/admin/receipt") + public void getAllReceipt() throws Exception { + itemTestUtils.purchaseItem(user, user, item); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + String url = "/pingpong/admin/receipt?page=" + page + "&size=" + size; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + ReceiptListResponseDto expect = receiptAdminService.getAllReceipt(pageable); + ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); + assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo( + expect.getReceiptList().get(0).getReceiptId()); + assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo( + expect.getReceiptList().get(0).getCreatedAt()); + assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo( + expect.getReceiptList().get(0).getItemName()); + assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo( + expect.getReceiptList().get(0).getItemPrice()); + assertThat(result.getReceiptList().size()).isEqualTo(expect.getReceiptList().size()); + assertThat(result.getReceiptList().size()).isEqualTo(1); + } + + @Test + @DisplayName("GET /pingpong/admin/receipt") + public void findByIntraId() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Integer page = 1; + Integer size = 20; + User targetUser = testDataUtils.createNewUser("david"); + itemTestUtils.purchaseItem(user, user, item); + itemTestUtils.purchaseItem(targetUser, targetUser, item); + + String url = "/pingpong/admin/receipt?page=" + page + "&size=" + size + "&intraId=" + targetUser.getIntraId(); + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + ReceiptListResponseDto expect = receiptAdminService.findByIntraId(targetUser.getIntraId(), pageable); + ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); + assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo( + expect.getReceiptList().get(0).getReceiptId()); + assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo( + expect.getReceiptList().get(0).getCreatedAt()); + assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo( + expect.getReceiptList().get(0).getItemName()); + assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo( + expect.getReceiptList().get(0).getItemPrice()); + assertThat(result.getReceiptList().size()).isEqualTo(expect.getReceiptList().size()); + assertThat(result.getReceiptList().size()).isEqualTo(1); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/service/ReceiptAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/service/ReceiptAdminServiceUnitTest.java new file mode 100644 index 000000000..be06a7587 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/receipt/service/ReceiptAdminServiceUnitTest.java @@ -0,0 +1,58 @@ +package gg.pingpong.api.admin.receipt.service; + +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.admin.repo.store.ReceiptAdminRepository; +import gg.data.store.Receipt; +import gg.pingpong.api.admin.store.service.ReceiptAdminService; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class ReceiptAdminServiceUnitTest { + @Mock + ReceiptAdminRepository receiptAdminRepository; + @InjectMocks + ReceiptAdminService receiptAdminService; + + @Nested + @DisplayName("getAllReceipt ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetAllReceipt { + @Test + @DisplayName("success") + void success() { + // given + ArrayList receipts = new ArrayList<>(); + given(receiptAdminRepository.findAll(any(Pageable.class))).willReturn(new PageImpl<>(receipts)); + // when, then + receiptAdminService.getAllReceipt(mock(Pageable.class)); + } + } + + @Nested + @DisplayName("findByIntraId ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class FindByIntraId { + @Test + @DisplayName("success") + void success() { + // given + ArrayList receipts = new ArrayList<>(); + given(receiptAdminRepository.findReceiptByIntraId(any(String.class), any(Pageable.class))) + .willReturn(new PageImpl<>(receipts)); + // when, then + receiptAdminService.findByIntraId("intraId", mock(Pageable.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/controller/SeasonAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/controller/SeasonAdminControllerTest.java new file mode 100644 index 000000000..fdc758d2e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/controller/SeasonAdminControllerTest.java @@ -0,0 +1,242 @@ +package gg.pingpong.api.admin.season.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.net.HttpHeaders; + +import gg.admin.repo.season.SeasonAdminRepository; +import gg.data.rank.Tier; +import gg.data.season.Season; +import gg.pingpong.api.admin.rank.service.RankAdminService; +import gg.pingpong.api.admin.rank.service.RankRedisAdminService; +import gg.pingpong.api.admin.season.controller.request.SeasonCreateRequestDto; +import gg.pingpong.api.admin.season.controller.request.SeasonUpdateRequestDto; +import gg.pingpong.api.admin.season.controller.response.SeasonListAdminResponseDto; +import gg.pingpong.api.admin.season.dto.SeasonAdminDto; +import gg.pingpong.api.admin.season.service.SeasonAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.rank.RankRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.rank.RedisDataNotFoundException; +import gg.utils.exception.season.SeasonForbiddenException; +import gg.utils.exception.season.SeasonNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class SeasonAdminControllerTest { + @Autowired + MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private SeasonAdminRepository seasonAdminRepository; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + RankRepository rankRepository; + + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + SeasonAdminService seasonAdminService; + + @Autowired + RankAdminService rankAdminService; + + @Autowired + RankRedisAdminService rankRedisAdminService; + + SeasonListAdminResponseDto responseDto; + Long dbSeasonId; + + @AfterEach + void tearDown() { + rankRedisRepository.deleteAll(); + } + + @Test + @DisplayName("[GET]pingpong/admin/seasons") + void getAdminSeasons() throws Exception { + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.get("/pingpong/admin/seasons") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + SeasonListAdminResponseDto seasonListAdminResponseDto = objectMapper.readValue(contentAsString, + SeasonListAdminResponseDto.class); + System.out.println(seasonListAdminResponseDto.getSeasonList().size()); + } + + @Test + @DisplayName("[POST]/pingpong/admin/seasons") + void createSeasons() throws Exception { + List pingpong = testDataUtils.createTierSystem("pingpong"); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + SeasonCreateRequestDto seasonCreateReqeustDto = new SeasonCreateRequestDto( + "redis1", + LocalDateTime.now().plusHours(25), + 1000, + 500); + String content = objectMapper.writeValueAsString(seasonCreateReqeustDto); + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.post("/pingpong/admin/seasons") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + dbSeasonId = rankRepository.findFirstByOrderByCreatedAtDesc().get().getSeason().getId(); + String redisHashKey = RedisKeyManager.getHashKey(dbSeasonId); + + if (rankRedisRepository.findRankByUserId(redisHashKey, userId) == null) { + throw new SeasonNotFoundException(); + } + System.out.println(rankRedisRepository.findRankByUserId(redisHashKey, userId).getIntraId()); + } + + @Test + @DisplayName("[Delete]/pingpong/admin/season/{seasonId}") + void deleteSeasons() throws Exception { + testDataUtils.createTierSystem("pingpong"); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Season newSeason = Season.builder() + .seasonName("redis1") + .startTime(LocalDateTime.now().plusDays(1)) + .endTime(LocalDateTime.now().plusDays(10)) + .startPpp(1000) + .pppGap(500) + .build(); + seasonAdminRepository.save(newSeason); + Long seasonId = newSeason.getId(); + + SeasonAdminDto seasonAdminDto = seasonAdminService.findSeasonById(seasonId); + if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { + rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); + rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); + } + dbSeasonId = seasonId; + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.delete("/pingpong/admin/seasons/" + dbSeasonId) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + try { + String redisHashKey = RedisKeyManager.getHashKey(dbSeasonId); + if (rankRedisRepository.findRankByUserId(redisHashKey, userId) != null) { + throw new SeasonForbiddenException(); + } + } catch (RedisDataNotFoundException ex) { + System.out.println("success: ๋ ˆ๋””์Šค๊ฐ€ ์ง€์›Œ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค"); + } + } + + @Test + @DisplayName("[Put]/pingpong/admin/seasons/{seasonId}") + void updateSeasons() throws Exception { + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Season newSeason = Season.builder() + .seasonName("redis1") + .startTime(LocalDateTime.now().plusHours(25)) + .endTime(LocalDateTime.now().plusDays(10)) + .startPpp(1000) + .pppGap(500) + .build(); + seasonAdminRepository.save(newSeason); + Long seasonId = newSeason.getId(); + + SeasonAdminDto seasonAdminDto = seasonAdminService.findSeasonById(seasonId); + if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { + rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); + rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); + } + dbSeasonId = seasonId; + SeasonUpdateRequestDto seasonUpdateRequestDto = new SeasonUpdateRequestDto( + "putSeasonTestName", + LocalDateTime.now().plusHours(25), + 1000, + 500); + + String content = objectMapper.writeValueAsString(seasonUpdateRequestDto); + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/pingpong/admin/seasons/" + dbSeasonId) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + assertThat(seasonAdminRepository.findById(dbSeasonId).get().getSeasonName()) + .isEqualTo(seasonUpdateRequestDto.getSeasonName()); + } + + @Test + @DisplayName("Fail[Put]/pingpong/admin/seasons/{seasonId}") + void failUpdateSeasons() throws Exception { //ํ˜„์žฌ ์‹œ์ฆŒ์„ ๋ณ€๊ฒฝํ•  ๋•Œ 400๋ฒˆ๋Œ€ ์ƒํƒœ์ฝ”๋“œ ๋ฐ˜ํ™˜ + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + Long nowSeasonId = seasonAdminRepository.findCurrentSeason(LocalDateTime.now().plusMinutes(1)).get().getId(); + SeasonUpdateRequestDto seasonUpdateRequestDto = new SeasonUpdateRequestDto( + "putSeasonTestName", + LocalDateTime.now().plusHours(25), + 1000, + 500); + + String content = objectMapper.writeValueAsString(seasonUpdateRequestDto); + + String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/pingpong/admin/seasons/" + nowSeasonId) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError())//403๋ฐ˜ํ™˜ + .andReturn().getResponse().getContentAsString(); + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/service/SeasonAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/service/SeasonAdminServiceUnitTest.java new file mode 100644 index 000000000..1022bcc8f --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/season/service/SeasonAdminServiceUnitTest.java @@ -0,0 +1,381 @@ +package gg.pingpong.api.admin.season.service; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.admin.repo.season.SeasonAdminRepository; +import gg.data.season.Season; +import gg.pingpong.api.admin.rank.service.RankAdminService; +import gg.pingpong.api.admin.rank.service.RankRedisAdminService; +import gg.pingpong.api.admin.season.controller.request.SeasonCreateRequestDto; +import gg.pingpong.api.admin.season.controller.request.SeasonUpdateRequestDto; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.season.SeasonForbiddenException; +import gg.utils.exception.season.SeasonNotFoundException; +import gg.utils.exception.season.SeasonTimeBeforeException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class SeasonAdminServiceUnitTest { + @Mock + SeasonAdminRepository seasonAdminRepository; + @Mock + RankRedisAdminService rankRedisAdminService; + @Mock + RankAdminService rankAdminService; + @InjectMocks + SeasonAdminService seasonAdminService; + + int beforeSeasonCnt = 3; + int afterSeasonCnt = 2; + List beforeSeasons = new ArrayList<>(); + List afterSeasons = new ArrayList<>(); + + @BeforeEach + void beforeEach() { + LocalDateTime time = LocalDateTime.now(); + beforeSeasons.clear(); + afterSeasons.clear(); + for (int i = 0; i < beforeSeasonCnt; i++) { + beforeSeasons.add(new Season("season" + i, + time.minusDays(i + 1).minusSeconds(1), time.minusDays(i).minusSeconds(2), 1000, 200)); + } + for (int i = 0; i < afterSeasonCnt; i++) { + afterSeasons.add(new Season("season" + (i + beforeSeasonCnt), + time.plusDays(i + 3).minusSeconds(1), time.plusDays(i + 4).minusSeconds(2), 1000, 200)); + } + } + + @Nested + @DisplayName("findAllSeasons() ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class FindAllSeasons { + @Test + @DisplayName("success") + void success() { + // given + given(seasonAdminRepository.findAllByOrderByStartTimeDesc()).willReturn(beforeSeasons); + // when, then + seasonAdminService.findAllSeasons(); + verify(seasonAdminRepository, times(1)).findAllByOrderByStartTimeDesc(); + } + } + + @Nested + @DisplayName("createSeason() ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class CreateSeason { + SeasonCreateRequestDto requestDto; + Season season; + ArrayList beforeSeasonsAsc; + + @BeforeEach + void beforeEach() { + requestDto = new SeasonCreateRequestDto("season", LocalDateTime.now().plusDays(1).plusSeconds(1), + 1000, 200); + season = Season.builder() + .seasonName(requestDto.getSeasonName()) + .startTime(requestDto.getStartTime()) + .startPpp(requestDto.getStartPpp()) + .pppGap(requestDto.getPppGap()) + .build(); + + setFieldWithReflection(beforeSeasons.get(0), "id", 2L); + beforeSeasonsAsc = new ArrayList<>(beforeSeasons); + Collections.reverse(beforeSeasonsAsc); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒx&์˜ˆ์•ฝ์‹œ์ฆŒx") + void success1() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(new ArrayList<>()); + // when, then + seasonAdminService.createSeason(requestDto); + verify(seasonAdminRepository, times(1)).findBeforeSeasons(any()); + verify(seasonAdminRepository, times(1)).findAfterSeasons(any()); + verify(seasonAdminRepository, times(1)).save(any()); + verify(seasonAdminRepository, times(1)).findAllByOrderByStartTimeAsc(); + verify(rankAdminService, times(1)).addAllUserRankByNewSeason(any()); + verify(rankRedisAdminService, times(1)).addAllUserRankByNewSeason(any()); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒo&์˜ˆ์•ฝ์‹œ์ฆŒx") + void success2() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(beforeSeasonsAsc); + // when, then + seasonAdminService.createSeason(requestDto); + assertThat(beforeSeasons.get(0).getEndTime()).isEqualTo(requestDto.getStartTime().minusSeconds(1)); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒx&์˜ˆ์•ฝ์‹œ์ฆŒo") + void success3() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(afterSeasons); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(afterSeasons); + // when, then + seasonAdminService.createSeason(requestDto); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒo&์˜ˆ์•ฝ์‹œ์ฆŒo") + void success4() { + // given + ArrayList seasons = new ArrayList<>(beforeSeasonsAsc); + seasons.add(season); + setFieldWithReflection(season, "endTime", afterSeasons.get(0).getStartTime().minusSeconds(1)); + seasons.addAll(afterSeasons); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(afterSeasons); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(seasons); + // when, then + seasonAdminService.createSeason(requestDto); + } + + @Test + @DisplayName("isOverlap ๋งค์„œ๋“œ ๋ชจ๋“ ์กฐ๊ฑด ์ฒดํฌ 1") + void isOverlap1() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(beforeSeasonsAsc); + // when, then + beforeSeasonsAsc.get(1).setEndTime(beforeSeasonsAsc.get(1).getStartTime()); + seasonAdminService.createSeason(requestDto); + } + + @Test + @DisplayName("isOverlap ๋งค์„œ๋“œ ๋ชจ๋“ ์กฐ๊ฑด ์ฒดํฌ 2") + void isOverlap2() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(beforeSeasonsAsc); + // when, then + beforeSeasonsAsc.get(0).setEndTime(beforeSeasonsAsc.get(0).getStartTime()); + seasonAdminService.createSeason(requestDto); + } + + @Test + @DisplayName("isOverlap ๋งค์„œ๋“œ ๋ชจ๋“ ์กฐ๊ฑด ์ฒดํฌ 3") + void isOverlap3() { + // given + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(beforeSeasons); + // when, then 1 + seasonAdminService.createSeason(requestDto); + } + + @Test + @DisplayName("SeasonForbiddenException_1") + void seasonForbiddenException1() { + // given + ArrayList seasons = new ArrayList<>(beforeSeasonsAsc); + seasons.add(season); + setFieldWithReflection(season, "endTime", afterSeasons.get(0).getEndTime()); + seasons.addAll(afterSeasons); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(afterSeasons); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + given(seasonAdminRepository.findAllByOrderByStartTimeAsc()).willReturn(seasons); + // when, then + assertThatThrownBy(() -> seasonAdminService.createSeason(requestDto)) + .isInstanceOf(SeasonForbiddenException.class); + } + + @Test + @DisplayName("SeasonForbiddenException_2") + void seasonForbiddenException2() { + // given + setFieldWithReflection(beforeSeasonsAsc.get(0), "startTime", season.getStartTime().minusHours(23)); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasonsAsc); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + // when, then + assertThatThrownBy(() -> seasonAdminService.createSeason(requestDto)) + .isInstanceOf(SeasonForbiddenException.class); + } + + @Test + @DisplayName("SeasonTimeBeforeException") + void seasonTimeBeforeException() { + // given + setFieldWithReflection(requestDto, "startTime", LocalDateTime.now().plusHours(23).plusMinutes(59)); + // when, then + assertThatThrownBy(() -> seasonAdminService.createSeason(requestDto)) + .isInstanceOf(SeasonTimeBeforeException.class); + } + } + + @Nested + @DisplayName("findSeasonById() ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class FindSeasonById { + @Test + @DisplayName("success") + void success() { + // given + given(seasonAdminRepository.findById(any())).willReturn( + Optional.of(afterSeasons.get(afterSeasons.size() - 1))); + // when, then + seasonAdminService.findSeasonById(1L); + verify(seasonAdminRepository, times(1)).findById(any()); + } + + @Test + @DisplayName("SeasonNotFoundException") + void seasonNotFoundException() { + // given + given(seasonAdminRepository.findById(any())).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> seasonAdminService.findSeasonById(1L)) + .isInstanceOf(SeasonNotFoundException.class); + } + } + + @Nested + @DisplayName("deleteSeason() ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class DeleteSeason { + Season season; + + @BeforeEach + void beforeEach() { + season = new Season(1L, "season", LocalDateTime.now().plusDays(1).plusSeconds(1), + LocalDateTime.of(9999, 12, 31, 23, 59, 59), + 1000, 200); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒx&์˜ˆ์•ฝ์‹œ์ฆŒx") + void success1() { + // given + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + // when, then + seasonAdminService.deleteSeason(1L); + verify(seasonAdminRepository, times(1)).findById(any()); + verify(seasonAdminRepository, times(1)).findBeforeSeasons(any(LocalDateTime.class)); + verify(seasonAdminRepository, times(1)).findAfterSeasons(any(LocalDateTime.class)); + verify(rankAdminService, times(1)).deleteAllUserRankBySeason(any()); + verify(rankRedisAdminService, times(1)).deleteSeasonRankBySeasonId(any()); + verify(seasonAdminRepository, times(1)).delete(any()); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒo&์˜ˆ์•ฝ์‹œ์ฆŒx") + void success2() { + // given + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(new ArrayList<>()); + // when, then + seasonAdminService.deleteSeason(1L); + assertThat(beforeSeasons.get(0).getEndTime()) + .isEqualTo(LocalDateTime.of(9999, 12, 31, 23, 59, 59)); + } + + @Test + @DisplayName("success_์ด์ „์‹œ์ฆŒo&์˜ˆ์•ฝ์‹œ์ฆŒo") + void success3() { + // given + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + given(seasonAdminRepository.findBeforeSeasons(any(LocalDateTime.class))).willReturn(beforeSeasons); + given(seasonAdminRepository.findAfterSeasons(any(LocalDateTime.class))).willReturn(afterSeasons); + // when, then + seasonAdminService.deleteSeason(1L); + assertThat(beforeSeasons.get(0).getEndTime()).isEqualTo(afterSeasons.get(0).getStartTime().minusSeconds(1)); + } + + @Test + @DisplayName("SeasonForbiddenException") + void seasonForbiddenException() { + // given + setFieldWithReflection(season, "startTime", LocalDateTime.now().minusHours(2)); + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + // when, then 1 + assertThatThrownBy(() -> seasonAdminService.deleteSeason(1L)) + .isInstanceOf(SeasonForbiddenException.class); + // when, then 1 + setFieldWithReflection(season, "endTime", LocalDateTime.now().minusHours(1)); + assertThatThrownBy(() -> seasonAdminService.deleteSeason(1L)) + .isInstanceOf(SeasonForbiddenException.class); + } + } + + @Nested + @DisplayName("updateSeason() ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class UpdateSeason { + Season season; + SeasonUpdateRequestDto requestDto; + + @BeforeEach + void beforeEach() { + season = new Season(1L, "season", LocalDateTime.now().plusDays(1).plusSeconds(1), + LocalDateTime.of(9999, 12, 31, 23, 59, 59), + 1000, 200); + requestDto = new SeasonUpdateRequestDto("season", + LocalDateTime.now().plusDays(2), 1000, 500); + } + + @Test + @DisplayName("success") + void success() { + // given + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + given(seasonAdminRepository.findBeforeSeasons(any())).willReturn(new ArrayList<>()); + given(seasonAdminRepository.findAfterSeasons(any())).willReturn(new ArrayList<>()); + given(seasonAdminRepository.save(any())).willReturn(mock(Season.class)); + // when, then + seasonAdminService.updateSeason(1L, requestDto); + + verify(seasonAdminRepository, times(2)).findById(any()); + verify(seasonAdminRepository, times(2)).findBeforeSeasons(any()); + verify(seasonAdminRepository, times(2)).findAfterSeasons(any()); + verify(seasonAdminRepository, times(1)).save(any()); + verify(rankAdminService, times(1)).deleteAllUserRankBySeason(any()); + verify(rankAdminService, times(1)).addAllUserRankByNewSeason(any()); + verify(rankRedisAdminService, times(1)).deleteSeasonRankBySeasonId(any()); + verify(rankRedisAdminService, times(1)).addAllUserRankByNewSeason(any()); + } + + @Test + @DisplayName("SeasonForbiddenException") + void seasonForbiddenException() { + // given + setFieldWithReflection(season, "startTime", LocalDateTime.now().minusHours(1)); + given(seasonAdminRepository.findById(any())).willReturn(Optional.of(season)); + // when, then + assertThatThrownBy(() -> seasonAdminService.updateSeason(1L, requestDto)) + .isInstanceOf(SeasonForbiddenException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerFailTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerFailTest.java new file mode 100644 index 000000000..2d6f207cd --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerFailTest.java @@ -0,0 +1,164 @@ +package gg.pingpong.api.admin.slotmanagement.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.AdminSlotManagementsRepository; +import gg.data.manage.SlotManagement; +import gg.pingpong.api.admin.manage.controller.request.SlotCreateRequestDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.manage.SlotManagementRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +public class SlotAdminControllerFailTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + AdminSlotManagementsRepository adminSlotManagementRepository; + + @Autowired + SlotManagementRepository slotManagementRepository; + + @Test + @DisplayName("fail[Post]/pingpong/admin/slot-management") + void failModifySlotSetting() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 20, null, LocalDateTime.now().plusDays(2)); + String content = objectMapper.writeValueAsString(test); + + String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("fail[Post]/pingpong/admin/slot-management") + void endTimeCloseThenFuture() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 20, 1, LocalDateTime.now().plusHours(1)); + String content = objectMapper.writeValueAsString(test); + + String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("fail[Post]/pingpong/admin/slot-management") + void intervalIsSeven() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 7, 1, LocalDateTime.now().plusHours(1)); + String content = objectMapper.writeValueAsString(test); + + String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ƒ๋Œ€๋ฐฉ๊ณต๊ฐœ์‹œ๊ฐ„์ด๊ฒŒ์ž„์‹œ๊ฐ„๋ณด๋‹คํด๋–„") + void enemyOpenCloseThenGameTime() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 10, 15, + LocalDateTime.now().plusHours(1)); + String content = objectMapper.writeValueAsString(test); + + String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์Šฌ๋กฏ์ •๋ณด๊ฐ€ํ˜„์žฌ์ ์šฉ์ค‘์ธ๊ฒฝ์šฐ") + void slotAlreadyApply() throws Exception { + SlotManagement preSlot = SlotManagement.builder() + .futureSlotTime(12) + .pastSlotTime(0) + .openMinute(5) + .gameInterval(15) + .startTime(LocalDateTime.now().minusDays(1)) + .build(); + slotManagementRepository.save(preSlot); + + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + List slotManagements = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); + for (SlotManagement slot : slotManagements) { + System.out.println("-----------------------"); + System.out.println(slot.getFutureSlotTime()); + System.out.println(slot.getPastSlotTime()); + System.out.println(slot.getOpenMinute()); + System.out.println(slot.getStartTime()); + System.out.println(slot.getEndTime()); + System.out.println(slot.getId()); + } + + String contentAsString = mockMvc.perform(delete("/pingpong/admin/slot-management") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is4xxClientError()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + List slotManagements2 = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); + for (SlotManagement slot : slotManagements2) { + System.out.println("-----------------------"); + System.out.println(slot.getFutureSlotTime()); + System.out.println(slot.getPastSlotTime()); + System.out.println(slot.getOpenMinute()); + System.out.println(slot.getStartTime()); + System.out.println(slot.getEndTime()); + System.out.println(slot.getId()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerTest.java new file mode 100644 index 000000000..f41d37e56 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/controller/SlotAdminControllerTest.java @@ -0,0 +1,191 @@ +package gg.pingpong.api.admin.slotmanagement.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.manage.AdminSlotManagementsRepository; +import gg.data.manage.SlotManagement; +import gg.pingpong.api.admin.manage.controller.request.SlotCreateRequestDto; +import gg.pingpong.api.admin.manage.controller.response.SlotListAdminResponseDto; +import gg.pingpong.api.admin.manage.dto.SlotAdminDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.manage.SlotManagementRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class SlotAdminControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + AdminSlotManagementsRepository adminSlotManagementRepository; + + @Autowired + SlotManagementRepository slotManagementRepository; + + @BeforeEach + void setUp() { + SlotManagement preSlot = SlotManagement.builder() + .futureSlotTime(12) + .pastSlotTime(0) + .openMinute(5) + .gameInterval(15) + .startTime(LocalDateTime.now().minusDays(1)) + .build(); + slotManagementRepository.save(preSlot); + } + + @Test + @DisplayName("[Get]/pingpong/admin/slot-management") + void getSlotSetting1() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 20, 1, LocalDateTime.now().plusHours(13)); + System.out.println(test.getStartTime()); + String content = objectMapper.writeValueAsString(test); + mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + SlotCreateRequestDto test2 = new SlotCreateRequestDto(4, 1, 20, 1, LocalDateTime.now().plusHours(48)); + System.out.println(test.getStartTime()); + String content2 = objectMapper.writeValueAsString(test2); + mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content2) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + String contentAsString = mockMvc.perform( + get("/pingpong/admin/slot-management").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + SlotListAdminResponseDto slotAdminDto = objectMapper.readValue(contentAsString, SlotListAdminResponseDto.class); + + for (SlotAdminDto dto : slotAdminDto.getSlotList()) { + System.out.println(dto.getFutureSlotTime()); + System.out.println(dto.getPastSlotTime()); + System.out.println(dto.getInterval()); + System.out.println(dto.getOpenMinute()); + System.out.println(dto.getStartTime()); + System.out.println(dto.getEndTime()); + System.out.println("----------------------"); + } + } + + @Test + @DisplayName("[Get]/pingpong/admin/slot-management") + void getSlotSetting2() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + String contentAsString = mockMvc.perform( + get("/pingpong/admin/slot-management").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + SlotListAdminResponseDto slotAdminDto = objectMapper.readValue(contentAsString, SlotListAdminResponseDto.class); + + for (SlotAdminDto dto : slotAdminDto.getSlotList()) { + System.out.println(dto.getFutureSlotTime()); + System.out.println(dto.getPastSlotTime()); + System.out.println(dto.getInterval()); + System.out.println(dto.getOpenMinute()); + System.out.println(dto.getStartTime()); + System.out.println(dto.getEndTime()); + System.out.println("----------------------"); + } + } + + @Test + @DisplayName("[Post]/pingpong/admin/slot-management") + void modifySlotSetting() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 20, 1, LocalDateTime.now().plusHours(13)); + System.out.println(test.getStartTime()); + String content = objectMapper.writeValueAsString(test); + + String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + List slotList = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); + for (SlotManagement slot : slotList) { + System.out.println(slot.getFutureSlotTime()); + System.out.println(slot.getPastSlotTime()); + System.out.println(slot.getGameInterval()); + System.out.println(slot.getOpenMinute()); + System.out.println(slot.getStartTime()); + System.out.println(slot.getEndTime()); + System.out.println("----------------------"); + } + } + + @Test + @DisplayName("[Delete]/pingpong/admin/slot-management") + void delSlotSetting() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + SlotCreateRequestDto test = new SlotCreateRequestDto(4, 1, 20, 1, LocalDateTime.now().plusHours(13)); + System.out.println(test.getStartTime()); + String content = objectMapper.writeValueAsString(test); + + mockMvc.perform(post("/pingpong/admin/slot-management") + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + String contentAsString = mockMvc.perform(delete("/pingpong/admin/slot-management") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + List slotList = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); + for (SlotManagement slot : slotList) { + System.out.println(slot.getFutureSlotTime()); + System.out.println(slot.getPastSlotTime()); + System.out.println(slot.getGameInterval()); + System.out.println(slot.getOpenMinute()); + System.out.println(slot.getStartTime()); + System.out.println(slot.getEndTime()); + System.out.println("----------------------"); + } + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/service/SlotAdminServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/service/SlotAdminServiceUnitTest.java new file mode 100644 index 000000000..63fe2d374 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/slotmanagement/service/SlotAdminServiceUnitTest.java @@ -0,0 +1,157 @@ +package gg.pingpong.api.admin.slotmanagement.service; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +import gg.admin.repo.manage.AdminSlotManagementsRepository; +import gg.data.manage.SlotManagement; +import gg.pingpong.api.admin.manage.controller.request.SlotCreateRequestDto; +import gg.pingpong.api.admin.manage.service.SlotAdminService; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.slotmanagement.SlotManagementForbiddenException; + +@UnitTest +class SlotAdminServiceUnitTest { + @Mock + AdminSlotManagementsRepository adminSlotManagementRepository; + @InjectMocks + SlotAdminService slotAdminService; + + List slotManagementList; + List requestDtoList; + + @BeforeEach + void beforeEach() { + slotManagementList = new ArrayList<>(); + slotManagementList.add(new SlotManagement(12, 11, 5, 15, + LocalDateTime.now().plusHours(1), null)); + requestDtoList = new ArrayList<>(); + // success case + requestDtoList.add(new SlotCreateRequestDto(12, 11, 15, 5, + LocalDateTime.now().plusDays(1))); + // Exception case + requestDtoList.add(new SlotCreateRequestDto(24, 11, 15, 5, + LocalDateTime.now().plusHours(1))); + requestDtoList.add(new SlotCreateRequestDto(12, 13, 15, 5, + LocalDateTime.now())); + requestDtoList.add(new SlotCreateRequestDto(12, 11, 13, 5, + LocalDateTime.now())); + requestDtoList.add(new SlotCreateRequestDto(12, 11, 12, 5, + LocalDateTime.now())); + requestDtoList.add(new SlotCreateRequestDto(15, 11, 10, 5, + LocalDateTime.now())); + } + + @Nested + @DisplayName("getSlotSetting ๋งค์„œ๋“œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ") + @MockitoSettings(strictness = Strictness.LENIENT) + class GetSlotSetting { + @Test + @DisplayName("success") + void success() { + // given + given(adminSlotManagementRepository.findAfterNowSlotManagement(any())) + .willReturn(slotManagementList); + // when, then + slotAdminService.getSlotSetting(); + + verify(adminSlotManagementRepository, times(1)).findAfterNowSlotManagement(any()); + } + } + + @Nested + @DisplayName("addSlotSetting ๋งค์„œ๋“œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ") + @MockitoSettings(strictness = Strictness.LENIENT) + class AddSlotSetting { + @BeforeEach + void beforeEach() { + // given + given(adminSlotManagementRepository.findFirstByOrderByIdDesc()) + .willReturn(Optional.of(slotManagementList.get(0))); + given(adminSlotManagementRepository.save(any())).willReturn(mock(SlotManagement.class)); + } + + @Test + @DisplayName("success") + void success() { + // when, then + slotAdminService.addSlotSetting(requestDtoList.get(0)); + verify(adminSlotManagementRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("checkVaildSlotManagement์—์„œ ๋ฐœ์ƒํ•˜๋Š” Exception") + void checkVaildSlotManagement() { + //when, then + for (int i = 1; i < requestDtoList.size(); i++) { + int idx = i; + assertThatThrownBy(() -> slotAdminService.addSlotSetting(requestDtoList.get(idx))) + .isInstanceOf(SlotManagementForbiddenException.class); + } + } + + @Test + @DisplayName("updateNowSlotManagementEndTime์—์„œ ๋ฐœ์ƒํ•˜๋Š” Exception") + void updateNowSlotManagementEndTime() { + //when, then + setFieldWithReflection(slotManagementList.get(0), "endTime", LocalDateTime.now()); + assertThatThrownBy(() -> slotAdminService.addSlotSetting(requestDtoList.get(0))) + .isInstanceOf(SlotManagementForbiddenException.class); + setFieldWithReflection(slotManagementList.get(0), "startTime", LocalDateTime.now()); + setFieldWithReflection(requestDtoList.get(0), "startTime", LocalDateTime.now()); + assertThatThrownBy(() -> slotAdminService.addSlotSetting(requestDtoList.get(0))) + .isInstanceOf(SlotManagementForbiddenException.class); + } + } + + @Nested + @DisplayName("delSlotSetting ๋งค์„œ๋“œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ") + @MockitoSettings(strictness = Strictness.LENIENT) + class DelSlotSetting { + @BeforeEach + void beforeEach() { + // given + slotManagementList.add( + new SlotManagement(12, 11, 5, 15, + LocalDateTime.now(), LocalDateTime.now().plusHours(1))); + given(adminSlotManagementRepository.findAfterNowSlotManagement(any())) + .willReturn(slotManagementList); + } + + @Test + @DisplayName("success") + void success() { + // when, then + slotAdminService.delSlotSetting(); + verify(adminSlotManagementRepository, times(1)).findAfterNowSlotManagement(any()); + verify(adminSlotManagementRepository, times(1)).delete(any()); + } + + @Test + @DisplayName("SlotManagementForbiddenException") + void slotManagementForbiddenException() { + // when, then + setFieldWithReflection(slotManagementList.get(1), "endTime", null); + assertThatThrownBy(() -> slotAdminService.delSlotSetting()) + .isInstanceOf(SlotManagementForbiddenException.class); + setFieldWithReflection(slotManagementList.get(0), "startTime", LocalDateTime.now()); + assertThatThrownBy(() -> slotAdminService.delSlotSetting()) + .isInstanceOf(SlotManagementForbiddenException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminControllerTest.java new file mode 100644 index 000000000..f5aa141e6 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminControllerTest.java @@ -0,0 +1,998 @@ +package gg.pingpong.api.admin.tournament.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Random; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.type.Mode; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminAddUserRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminCreateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminUpdateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentGameUpdateRequestDto; +import gg.pingpong.api.admin.tournament.service.TournamentAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.game.dto.TeamReqDto; +import gg.pingpong.api.user.match.utils.MatchIntegrationTestUtils; +import gg.repo.game.PChangeRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.dto.GameInfoDto; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@AutoConfigureMockMvc +@RequiredArgsConstructor +@Transactional +class TournamentAdminControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + TournamentAdminService tournamentAdminService; + + @Autowired + TournamentRepository tournamentRepository; + + @Autowired + TournamentUserRepository tournamentUserRepository; + + @Autowired + TournamentGameRepository tournamentGameRepository; + + @Autowired + PChangeRepository pChangeRepository; + + @Autowired + private MatchIntegrationTestUtils matchTestUtils; + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์ˆ˜์ •_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") + class TournamentAdminControllerUpdateTest { + @BeforeEach + void beforeEach() { + testDataUtils.createSlot(15); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_์„ฑ๊ณต") + void success() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), + TournamentStatus.BEFORE); + + TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + tournament.getId(); + + String content = objectMapper.writeValueAsString(updateDto); + + // when + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + // then + Tournament result = tournamentRepository.findById(tournament.getId()).get(); + assertThat(result.getTitle()).isEqualTo(tournament.getTitle()); + assertThat(result.getContents()).isEqualTo(tournament.getContents()); + assertThat(result.getStartTime()).isEqualTo(updateDto.getStartTime()); + assertThat(result.getEndTime()).isEqualTo(updateDto.getEndTime()); + assertThat(result.getType()).isEqualTo(updateDto.getType()); + assertThat(result.getStatus()).isEqualTo(tournament.getStatus()); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") + void tournamentNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + 1111; + + String content = objectMapper.writeValueAsString(updateDto); + // when, then + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๊ธฐ๊ฐ„_๊ฒน์น˜๋Š”_๊ฒฝ์šฐ") + void tournamentConflicted() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournamentAlreadyExist = testDataUtils.createTournament( + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), + TournamentStatus.BEFORE); + + Tournament tournamentToChange = testDataUtils.createTournament( + LocalDateTime.now().plusDays(3).withHour(18).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(20).withMinute(0), + TournamentStatus.BEFORE); + + // ๊ฒน์น˜๋Š” ์‹œ๊ฐ„ ์กฐ์ ˆ + TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( + LocalDateTime.now().plusDays(3).withHour(13).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(15).withMinute(0), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); + + String content = objectMapper.writeValueAsString(updateDto); + + // when, then + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("๊ธฐ๊ฐ„๋‚ด_๊ฒŒ์ž„_์กด์žฌ") + void gameAlreadyExist() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + GameInfoDto game = testDataUtils.createGame(testDataUtils.createNewUser("testUser"), + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(14).withMinute(15), + testDataUtils.createSeason(), Mode.NORMAL); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), + TournamentStatus.BEFORE); + + // ๊ฒน์น˜๋Š” ์‹œ๊ฐ„ ์กฐ์ ˆ + TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( + tournament.getStartTime().plusDays(1), + tournament.getEndTime().plusDays(1), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + tournament.getId(); + + String content = objectMapper.writeValueAsString(updateDto); + + // when, then + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") + void canNotUpdate() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament liveTournament = testDataUtils.createTournament( + LocalDateTime.now().minusHours(1).withMinute(0), + LocalDateTime.now().plusHours(2).withMinute(0), + TournamentStatus.LIVE); + + Tournament endedTournament = testDataUtils.createTournament( + LocalDateTime.now().minusHours(3).withMinute(0), + LocalDateTime.now().minusHours(1).withMinute(0), + TournamentStatus.END); + + TournamentAdminUpdateRequestDto updateTournamentDto = testDataUtils.createUpdateRequestDto( + LocalDateTime.now().plusDays(2).plusHours(3).withMinute(0), + LocalDateTime.now().plusDays(2).plusHours(5).withMinute(0), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + liveTournament.getId(); + + String content = objectMapper.writeValueAsString(updateTournamentDto); + + // when live tournament test, then + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + url = "/pingpong/admin/tournaments/" + endedTournament.getId(); + + // when ended tournament test, then + contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์ž˜๋ชป๋œ_๊ธฐ๊ฐ„") + void wrongTournamentTime() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournamentToChange = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), + TournamentStatus.BEFORE); + + TournamentAdminUpdateRequestDto updateDto1 = testDataUtils.createUpdateRequestDto( + tournamentToChange.getStartTime(), + tournamentToChange.getStartTime(), + TournamentType.MASTER); + + TournamentAdminUpdateRequestDto updateDto2 = testDataUtils.createUpdateRequestDto( + tournamentToChange.getEndTime(), + tournamentToChange.getStartTime(), + TournamentType.MASTER); + + TournamentAdminUpdateRequestDto updateDto3 = testDataUtils.createUpdateRequestDto( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(5), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(5), + TournamentType.MASTER); + + String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); + // when startTime == endTime, then + String content = objectMapper.writeValueAsString(updateDto1); + + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + // when startTime > endTime test, then + content = objectMapper.writeValueAsString(updateDto2); + + contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + // when startTime minute invalid test, then + content = objectMapper.writeValueAsString(updateDto3); + + contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ_dto") + void wrongDto() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournamentToChange = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), + TournamentStatus.BEFORE); + + TournamentAdminUpdateRequestDto updateDto1 = testDataUtils.createUpdateRequestDto( + tournamentToChange.getStartTime(), + tournamentToChange.getStartTime(), + null); + + String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); + // when startTime == endTime, then + String content = objectMapper.writeValueAsString(updateDto1); + + String contentAsString = mockMvc.perform(patch(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์‚ญ์ œ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") + class TournamentAdminControllerDeleteTest { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_์„ฑ๊ณต") + void success() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + List tournamentGameList = testDataUtils.createTournamentGameList(tournament, 7); + + String url = "/pingpong/admin/tournaments/" + tournament.getId(); + + // when + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + // then + tournamentRepository.findById(tournament.getId()).ifPresent( + a -> { + throw new CustomRuntimeException("์‚ญ์ œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.", ErrorCode.BAD_REQUEST); + }); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") + void tournamentNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + String url = "/pingpong/admin/tournaments/" + 1111; + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") + void canNotDelete() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament liveTournament = testDataUtils.createTournament( + LocalDateTime.now().minusHours(1), + LocalDateTime.now().plusHours(2), + TournamentStatus.LIVE); + + Tournament endedTournament = testDataUtils.createTournament( + LocalDateTime.now().minusHours(3), + LocalDateTime.now().minusHours(1), + TournamentStatus.END); + + String url = "/pingpong/admin/tournaments/" + liveTournament.getId(); + + // when live tournament test, then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + + url = "/pingpong/admin/tournaments/" + endedTournament.getId(); + + // when ended tournament test, then + contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์ƒ์„ฑ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") + class TournamentAdminControllerCreateTest { + @BeforeEach + void beforeEach() { + testDataUtils.createSlot(15); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„ฑ๊ณต") + void success() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + TournamentAdminCreateRequestDto createDto = testDataUtils.createRequestDto( + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), + TournamentType.ROOKIE); + + String url = "/pingpong/admin/tournaments"; + String content = objectMapper.writeValueAsString(createDto); + + //when, then + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("๊ธฐ๊ฐ„๋‚ด_๊ฒŒ์ž„_์กด์žฌ") + void gameAlreadyExist() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + GameInfoDto game = testDataUtils.createGame(testDataUtils.createNewUser("testUser"), + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(14).withMinute(15), + testDataUtils.createSeason(), Mode.NORMAL); + + TournamentAdminCreateRequestDto createDto = testDataUtils.createRequestDto( + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), + TournamentType.ROOKIE); + + String url = "/pingpong/admin/tournaments"; + String content = objectMapper.writeValueAsString(createDto); + + // when, then + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ DTO - ๊ธธ์ด ์ดˆ๊ณผ") + void invalidLength() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + int leftLimit = 97; // letter 'a' + int rightLimit = 122; // letter 'z' + int targetStringLength = 3100; + Random random = new Random(); + String contents = random.ints(leftLimit, rightLimit + 1) + .limit(targetStringLength) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) + .toString(); + TournamentAdminCreateRequestDto createDto = new TournamentAdminCreateRequestDto( + "1st rookie tournament", + contents, + LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), + LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), + TournamentType.ROOKIE); + + String url = "/pingpong/admin/tournaments"; + String content = objectMapper.writeValueAsString(createDto); + + //when, then + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + } + + @Nested + @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ถ”๊ฐ€_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") + class TournamentAdminControllerAddUserTest { + @Test + @DisplayName("์œ ์ €_์ถ”๊ฐ€_์„ฑ๊ณต") + void success() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament1 = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + Tournament tournament2 = testDataUtils.createTournament( + LocalDateTime.now().plusDays(3).plusHours(1), + LocalDateTime.now().plusDays(3).plusHours(3), + TournamentStatus.BEFORE); + User user = testDataUtils.createNewUser("testUser"); + testDataUtils.createTournamentUser(user, tournament2, true); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + tournament1.getId() + "/users"; + String content = objectMapper.writeValueAsString(requestDto); + + // when + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + // then + System.out.println(contentAsString); + tournament1.getTournamentUsers().stream().filter(tu -> tu.getUser().equals(user)).findAny() + .orElseThrow(() -> new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); + tournamentUserRepository.findAllByTournamentId(tournament1.getId()) + .stream().filter(tu -> tu.getUser().getIntraId().equals(requestDto.getIntraId())) + .findAny().orElseThrow(() -> new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€ ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") + void tournamentNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + User user = testDataUtils.createNewUser("test"); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + 9999 + "/users"; + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + } + + @Test + @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") + void canNotUpdate() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(0).plusHours(-1), + LocalDateTime.now().plusDays(0).plusHours(1), + TournamentStatus.LIVE); + User user = testDataUtils.createNewUser("test"); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") + void userNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("nobody"); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("ํ•ด๋‹น_ํ† ๋„ˆ๋จผํŠธ_์ฐธ๊ฐ€์ž์ธ_๊ฒฝ์šฐ") + void alreadyTournamentParticipant() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + User user = testDataUtils.createNewUser("test"); + TournamentUser participant = testDataUtils.createTournamentUser(user, tournament, false); + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๋Œ€๊ธฐ์ž_์‹ ์ฒญ") + void waitUserTest() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + tokenProvider.getUserIdFromAccessToken(accessToken); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + User user = testDataUtils.createNewUser("testUser0"); + for (int i = 1; i <= 8; i++) { + testDataUtils.createTournamentUser(testDataUtils.createNewUser("testUser" + i), tournament, true); + } + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; + String content = objectMapper.writeValueAsString(requestDto); + + // when + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + // then + tournamentUserRepository.findAllByTournamentId(tournament.getId()) + .stream() + .filter(tu -> tu.getUser().getIntraId().equals(user.getIntraId())) + .findAny() + .filter(tu -> !tu.getIsJoined()) + .orElseThrow(() -> new CustomRuntimeException("waitlist ์ œ๋Œ€๋กœ ๋“ฑ๋ก ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); + } + } + + @Nested + @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‚ญ์ œ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") + class TournamentAdminControllerDeleteUserTest { + @Test + @DisplayName("์œ ์ €_์‚ญ์ œ_์„ฑ๊ณต") + void success() throws Exception { + // given + int maxTournamentUser = 8; + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + for (int i = 0; i < maxTournamentUser; i++) { + TournamentUser tournamentUser = testDataUtils.createTournamentUser( + testDataUtils.createNewUser("testUser" + i), tournament, true); + } + for (int i = maxTournamentUser; i < maxTournamentUser + 4; i++) { + TournamentUser tournamentUser = testDataUtils.createTournamentUser( + testDataUtils.createNewUser("testUser" + i), tournament, false); + } + + User user = tournament.getTournamentUsers().get(6).getUser(); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users/" + user.getId(); + // when + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + + // then + System.out.println(contentAsString); + List tournamentUserList = tournament.getTournamentUsers(); + tournamentUserList.stream().filter(tu -> tu.getUser().equals(user)).findAny() + .ifPresent(a -> { + throw new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ์— ์‚ญ์ œ ์•ˆ๋จ", ErrorCode.BAD_REQUEST); + }); + tournamentUserRepository.findByTournamentIdAndUserId(tournament.getId(), user.getId()) + .ifPresent(a -> { + throw new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ ˆํฌ์—์„œ ์‚ญ์ œ ์•ˆ๋จ", ErrorCode.BAD_REQUEST); + }); + for (int i = 0; i < maxTournamentUser; i++) { + if (!tournamentUserList.get(i).getIsJoined()) { + throw new CustomRuntimeException("๋Œ€๊ธฐ์ž => ์ฐธ์—ฌ์ž ์ „ํ™˜ ์ œ๋Œ€๋กœ ์•ˆ๋จ", ErrorCode.BAD_REQUEST); + } + } + for (int i = maxTournamentUser; i < tournamentUserList.size(); i++) { + if (tournamentUserList.get(i).getIsJoined()) { + throw new CustomRuntimeException("์ •ํ•ด์ง„ ์ฐธ๊ฐ€์ž ์ˆ˜๋ณด๋‹ค ์ฐธ๊ฐ€์ž๊ฐ€ ๋งŽ์Œ", ErrorCode.BAD_REQUEST); + } + } + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") + void tournamentNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + User user = testDataUtils.createNewUser("testUser"); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + 1234 + "/users/" + user.getId(); + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + } + + @Test + @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") + void canNotUpdate() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(0).plusHours(-1), + LocalDateTime.now().plusDays(0).plusHours(1), + TournamentStatus.LIVE); + User user = testDataUtils.createNewUser("testUser"); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users/" + user.getId(); + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") + void userNotFound() throws Exception { + // given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + + Tournament tournament = testDataUtils.createTournament( + LocalDateTime.now().plusDays(2).plusHours(1), + LocalDateTime.now().plusDays(2).plusHours(3), + TournamentStatus.BEFORE); + + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("nobody"); + + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users/" + "4321"; + + String content = objectMapper.writeValueAsString(requestDto); + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + } + } + + @Nested + @DisplayName("[Patch] /pingpong/admin/tournaments/{tournamentId}/games") + class AdminUpdateTournamentGameTest { + private String accessToken; + private Tournament tournament; + private List allTournamentGames; + Season season; + + @BeforeEach + void setUp() { + // ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑํ•˜๊ณ  8๊ฐ• & 4๊ฐ•์€ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ž…๋ ฅํ•˜๊ณ  ์ข…๋ฃŒ๋œ ์ƒํƒœ์ด๊ณ  ๊ฒฐ์Šน์ „ ๋งค์นญ๋œ ์ƒํƒœ๋กœ ์ดˆ๊ธฐํ™” + season = testDataUtils.createSeason(); + testDataUtils.createSlotManagement(15); + tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "test"); + allTournamentGames = testDataUtils.createTournamentGameList(tournament, 7); + tournament.updateStatus(TournamentStatus.LIVE); + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); + + accessToken = testDataUtils.getAdminLoginAccessToken(); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ฒŒ์ž„_์ˆ˜์ •_์„ฑ๊ณต") + void updateTournamentGameSuccess() throws Exception { + // given + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/games"; + + int myTeamScore = 2; + int otherTeamScore = 1; + TournamentGame tournamentGame = allTournamentGames.stream() + .filter(tg -> tg.getTournamentRound() == TournamentRound.SEMI_FINAL_1) + .findAny() + .orElseThrow(); + TournamentGame nextTournamentGame = allTournamentGames.stream() + .filter(tg -> tg.getTournamentRound() == TournamentRound.THE_FINAL) + .findAny() + .orElseThrow(); + User user1 = tournamentGame.getGame().getTeams().get(0).getTeamUsers().get(0).getUser(); + User user2 = tournamentGame.getGame().getTeams().get(1).getTeamUsers().get(0).getUser(); + testDataUtils.createUserRank(user1, "", season); + testDataUtils.createUserRank(user2, "", season); + + TournamentGameUpdateRequestDto requestDto = new TournamentGameUpdateRequestDto(tournamentGame.getId(), + nextTournamentGame.getId(), + new TeamReqDto(tournamentGame.getGame().getTeams().get(0).getId(), myTeamScore), + new TeamReqDto(tournamentGame.getGame().getTeams().get(1).getId(), otherTeamScore)); + + String content = objectMapper.writeValueAsString(requestDto); + // when + mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(content) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentGame resTournamentGame = tournamentGameRepository.findById(tournamentGame.getId()).orElseThrow(); + assertThat(resTournamentGame.getGame().getTeams().get(0).getScore()).isEqualTo(myTeamScore); + assertThat(resTournamentGame.getGame().getTeams().get(1).getScore()).isEqualTo(otherTeamScore); + assertThat( + pChangeRepository.findByUserIdAndGameId(user1.getId(), tournamentGame.getGame().getId())).isNotEmpty(); + assertThat( + pChangeRepository.findByUserIdAndGameId(user2.getId(), tournamentGame.getGame().getId())).isNotEmpty(); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ฒŒ์ž„_์ˆ˜์ •_๋ถˆ๊ฐ€๋Šฅ") + void updateTournamentGameEnable() throws Exception { + // given + String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/games"; + int myTeamScore = 2; + int otherTeamScore = 1; + TournamentGame tournamentGame = allTournamentGames.stream() + .filter(tg -> tg.getTournamentRound() == TournamentRound.QUARTER_FINAL_1) + .findAny() + .orElseThrow(); + TournamentGame nextTournamentGame = allTournamentGames.stream() + .filter(tg -> tg.getTournamentRound() == TournamentRound.SEMI_FINAL_1) + .findAny() + .orElseThrow(); + TournamentGameUpdateRequestDto requestDto = new TournamentGameUpdateRequestDto(tournamentGame.getId(), + nextTournamentGame.getId(), + new TeamReqDto(tournamentGame.getGame().getTeams().get(0).getId(), myTeamScore), + new TeamReqDto(tournamentGame.getGame().getTeams().get(1).getId(), otherTeamScore)); + + String content = objectMapper.writeValueAsString(requestDto); + // when + mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(content) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()) + .andReturn().getResponse().getContentAsString(); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminUserControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminUserControllerTest.java new file mode 100644 index 000000000..3ed665cae --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/controller/TournamentAdminUserControllerTest.java @@ -0,0 +1,109 @@ +package gg.pingpong.api.admin.tournament.controller; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.tournament.Tournament; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserListResponseDto; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@Slf4j +public class TournamentAdminUserControllerTest { + + @Autowired + MockMvc mockMvc; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + + String accessToken; + final int joinUserCnt = 8; + final int notJoinUserCnt = 4; + String testName = "42_gg_tester_"; + Tournament tournament; + String adminUrl = "/pingpong/admin/tournaments/"; + + @BeforeEach + void beforeEach() { + User tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + tournament = testDataUtils.createTournamentWithUser(joinUserCnt, notJoinUserCnt, testName); + } + + @Nested + @DisplayName("/pingpong/admin/tournaments") + class FindTournamentUser { + + @Test + @DisplayName("[Get] /{tournamentId}/users") + void getAllTournamentUser() throws Exception { + // given + + String url = adminUrl + tournament.getId() + "/users"; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentUserListResponseDto resp = objectMapper.readValue(contentAsString, + TournamentUserListResponseDto.class); + + // then + assertThat(resp.getUsers().size()).isEqualTo(joinUserCnt + notJoinUserCnt); + for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { + assertThat(resp.getUsers().get(i).getIntraId()).isEqualTo(testName + i); + } + } + + @Test + @DisplayName("[Get] /{tournamentId}/users?isJoined=true") + void getAllTournamentUserByIsJoined() throws Exception { + + // given + String url = adminUrl + tournament.getId() + "/users" + "?isJoined=true"; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentUserListResponseDto resp = objectMapper.readValue(contentAsString, + TournamentUserListResponseDto.class); + + // then + assertThat(resp.getUsers().size()).isEqualTo(joinUserCnt); + for (int i = 0; i < joinUserCnt; i++) { + assertThat(resp.getUsers().get(i).getIntraId()).isEqualTo(testName + i); + assertThat(resp.getUsers().get(i).getIsJoined()).isEqualTo(true); + } + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/service/TournamentAdminServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/service/TournamentAdminServiceTest.java new file mode 100644 index 000000000..e34413789 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/tournament/service/TournamentAdminServiceTest.java @@ -0,0 +1,603 @@ +package gg.pingpong.api.admin.tournament.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.game.Game; +import gg.data.manage.SlotManagement; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminAddUserRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminCreateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminUpdateRequestDto; +import gg.pingpong.api.global.config.ConstantConfig; +import gg.pingpong.api.utils.ReflectionUtilsForUnitTest; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.tournament.TournamentConflictException; +import gg.utils.exception.tournament.TournamentNotFoundException; +import gg.utils.exception.tournament.TournamentUpdateException; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class TournamentAdminServiceTest { + @Mock + TournamentRepository tournamentRepository; + @Mock + TournamentGameRepository tournamentGameRepository; + @Mock + TournamentUserRepository tournamentUserRepository; + @Mock + SlotManagementRepository slotManagementRepository; + @Mock + UserRepository userRepository; + @Mock + GameRepository gameRepository; + @Mock + ConstantConfig constantConfig; + @InjectMocks + TournamentAdminService tournamentAdminService; + + // ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์ƒ์„ฑ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") + class TournamentAdminServiceCreateTest { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„ฑ๊ณต") + void success() { + // given + TournamentAdminCreateRequestDto requestDto = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 14, 0), getTargetTime(3, 16, 0)); + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentGame tournamentGame = createTournamentGame(tournament, TournamentRound.THE_FINAL); + + given(slotManagementRepository.findCurrent(requestDto.getStartTime())).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findAllBetween(requestDto.getStartTime(), requestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given(gameRepository.findAllBetweenTournament(requestDto.getStartTime(), requestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given(tournamentRepository.save(any(Tournament.class))).willReturn(tournament); + + // when + tournamentAdminService.createTournament(requestDto); + } + + @Test + @DisplayName("์œ ํšจํ•˜์ง€ ์•Š์€ ์‹œ๊ฐ„ ์ž…๋ ฅ") + public void invalidTime() { + when(constantConfig.getAllowedMinimalStartDays()).thenReturn(2); + //given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + getTargetTime(0, 0, 0), getTargetTime(0, 1, 0)); + + TournamentAdminCreateRequestDto requestDto1 = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(1, 1, 0), getTargetTime(1, 3, 0)); + TournamentAdminCreateRequestDto requestDto2 = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 3, 0), getTargetTime(3, 1, 0)); + TournamentAdminCreateRequestDto requestDto3 = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 3, 0), getTargetTime(3, 3, 0)); + TournamentAdminCreateRequestDto requestDto4 = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 1, 10), getTargetTime(3, 2, 10)); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(createSlot(15))); + // when, then + assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto1)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto2)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto3)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto4)) + .isInstanceOf(TournamentUpdateException.class); + } + + @Test + @DisplayName("๊ธฐ์กด์— ์žˆ๋Š” ํ† ๋„ˆ๋จผํŠธ์™€ ๊ฒน์น˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„") + public void tournamentTimeConflict() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(3, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminCreateRequestDto createRequestDto = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 11, 0), getTargetTime(3, 13, 0)); + given(slotManagementRepository.findCurrent(createRequestDto.getStartTime())).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findAllBetween(createRequestDto.getStartTime(), createRequestDto.getEndTime())) + .willReturn(tournamentList); + + // when, then + assertThatThrownBy(() -> tournamentAdminService.createTournament(createRequestDto)) + .isInstanceOf(TournamentConflictException.class); + } + + @Test + @DisplayName("๊ธฐ์กด์— ์žˆ๋Š” ๊ฒŒ์ž„๊ณผ ๊ฒน์น˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„") + void gameAlreadyExist() { + // given + TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto = createTournamentCreateRequestDto( + "1st tournament", + getTargetTime(3, 10, 0), getTargetTime(3, 12, 0)); + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentGame tournamentGame = createTournamentGame(tournament, TournamentRound.THE_FINAL); + List gameList = new ArrayList<>(); + gameList.add(new Game()); + given(slotManagementRepository.findCurrent(tournamentAdminCreateRequestDto.getStartTime())).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findAllBetween(tournamentAdminCreateRequestDto.getStartTime(), + tournamentAdminCreateRequestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given(gameRepository.findAllBetweenTournament(tournamentAdminCreateRequestDto.getStartTime(), + tournamentAdminCreateRequestDto.getEndTime())) + .willReturn(gameList); + + // when + assertThatThrownBy(() -> tournamentAdminService.createTournament(tournamentAdminCreateRequestDto)) + .isInstanceOf(TournamentConflictException.class); + ; + } + } + + // ํ† ๋„ˆ๋จผํŠธ ์ˆ˜์ • ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค ์ˆ˜์ • ํ…Œ์ŠคํŠธ") + class TournamentAdminServiceUpdateTest { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_์„ฑ๊ณต") + public void success() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( + getTargetTime(3, 14, 0), getTargetTime(3, 16, 0)); + given(slotManagementRepository.findCurrent(updateRequestDto.getStartTime())).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given( + gameRepository.findAllBetweenTournament(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given(tournamentRepository.save(any(Tournament.class))).willReturn(tournament); + // when + Tournament changedTournament = tournamentAdminService.updateTournamentInfo(1L, updateRequestDto); + // then + assertThat(changedTournament.getId()).isEqualTo(tournament.getId()); + assertThat(changedTournament.getTitle()).isEqualTo(updateRequestDto.getTitle()); + assertThat(changedTournament.getContents()).isEqualTo(updateRequestDto.getContents()); + assertThat(changedTournament.getStartTime()).isEqualTo(updateRequestDto.getStartTime()); + assertThat(changedTournament.getEndTime()).isEqualTo(updateRequestDto.getEndTime()); + assertThat(changedTournament.getType()).isEqualTo(updateRequestDto.getType()); + assertThat(changedTournament.getStatus()).isEqualTo(tournament.getStatus()); + } + + @Test + @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + public void tournamentNotFound() { + // given + Tournament tournament = createTournament(1234L, TournamentStatus.BEFORE, + getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); + TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( + getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); + + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) + .isInstanceOf(TournamentNotFoundException.class); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๋ถˆ๊ฐ€_์ƒํƒœ") + public void canNotUpdate() { + // given + Tournament tournamentLive = createTournament(1L, TournamentStatus.LIVE, + LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); + Tournament tournamentEnd = createTournament(2L, TournamentStatus.END, + LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); + TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( + getTargetTime(3, 10, 0), getTargetTime(3, 12, 0)); + given(tournamentRepository.findById(tournamentLive.getId())).willReturn(Optional.of(tournamentLive)); + given(tournamentRepository.findById(tournamentEnd.getId())).willReturn(Optional.of(tournamentEnd)); + // when, then + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournamentLive.getId(), updateRequestDto)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournamentEnd.getId(), updateRequestDto)) + .isInstanceOf(TournamentUpdateException.class); + } + + @Test + @DisplayName("์—…๋ฐ์ดํŠธ_ํ† ๋„ˆ๋จผํŠธ_Dto_Invalid_Time") + public void dto_Invalid_Time() { + when(constantConfig.getAllowedMinimalStartDays()).thenReturn(2); + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); + TournamentAdminUpdateRequestDto invalidRequestDto1 = createTournamentAdminUpdateRequestDto( + getTargetTime(2, 3, 0), getTargetTime(2, 1, 0)); + TournamentAdminUpdateRequestDto invalidRequestDto2 = createTournamentAdminUpdateRequestDto( + invalidRequestDto1.getStartTime(), invalidRequestDto1.getStartTime()); + TournamentAdminUpdateRequestDto invalidRequestDto3 = createTournamentAdminUpdateRequestDto( + getTargetTime(1, 23, 0), getTargetTime(2, 1, 0)); + TournamentAdminUpdateRequestDto invalidRequestDto4 = createTournamentAdminUpdateRequestDto( + getTargetTime(2, 20, 1), getTargetTime(2, 23, 0)); + + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + // when then + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto1)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto2)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto3)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy( + () -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto4)) + .isInstanceOf(TournamentUpdateException.class); + } + + @Test + @DisplayName("Dto_๊ธฐ๊ฐ„_ํ† ๋„ˆ๋จผํŠธ_๊ธฐ๊ฐ„_๊ฒน์นจ") + public void tournamentTimeConflict() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(3, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( + getTargetTime(3, 12, 0), getTargetTime(3, 14, 0)); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) + .willReturn(tournamentList); + // when, then + assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) + .isInstanceOf(TournamentConflictException.class); + } + + @Test + @DisplayName("Dto_๊ธฐ๊ฐ„_๊ฒŒ์ž„_๊ฒน์นจ") + public void gameTimeConflict() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( + getTargetTime(3, 1, 0), getTargetTime(3, 3, 0)); + List gameList = new ArrayList<>(); + gameList.add(new Game()); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(createSlot(15))); + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); + given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) + .willReturn(new ArrayList<>()); + given(gameRepository.findAllBetweenTournament(updateRequestDto.getStartTime(), + updateRequestDto.getEndTime())).willReturn(gameList); + // when, then + assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) + .isInstanceOf(TournamentConflictException.class); + } + } + + // ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค ์‚ญ์ œ ํ…Œ์ŠคํŠธ") + class TournamentAdminServiceDeleteTest { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_์„ฑ๊ณต") + void success() { + // given + int tournamentGameCnt = 7; + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); + List tournamentGameList = createTournamentGames(1L, tournament, tournamentGameCnt); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + // when, then + tournamentAdminService.deleteTournament(tournament.getId()); + } + + @Test + @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + public void tournamentNotFound() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); + given(tournamentRepository.findById(1L)).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> tournamentAdminService.deleteTournament(tournament.getId())) + .isInstanceOf(TournamentNotFoundException.class); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_๋ถˆ๊ฐ€_์ƒํƒœ") + public void canNotDelete() { + // given + Tournament liveTournament = createTournament(1L, TournamentStatus.LIVE, + LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); + Tournament endTournament = createTournament(1L, TournamentStatus.END, + LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); + given(tournamentRepository.findById(liveTournament.getId())).willReturn(Optional.of(liveTournament)); + given(tournamentRepository.findById(endTournament.getId())).willReturn(Optional.of(endTournament)); + // when, then + assertThatThrownBy(() -> tournamentAdminService.deleteTournament(liveTournament.getId())) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy(() -> tournamentAdminService.deleteTournament(endTournament.getId())) + .isInstanceOf(TournamentUpdateException.class); + } + + } + + @Nested + @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ถ”๊ฐ€_ํ…Œ์ŠคํŠธ") + class TournamentAdminServiceAddUserTest { + @Test + @DisplayName("์œ ์ €_์ถ”๊ฐ€_์„ฑ๊ณต") + public void success() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("testUser"); + User user = createUser("testUser"); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(userRepository.findByIntraId("testUser")).willReturn(Optional.of(user)); + given(tournamentUserRepository.save(any(TournamentUser.class))).willReturn(null); + // when, then + tournamentAdminService.addTournamentUser(1L, requestDto); + } + + @Test + @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + public void tournamentNotFound() { + // given + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); + + given(tournamentRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(1L, requestDto)) + .isInstanceOf(TournamentNotFoundException.class); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๋ถˆ๊ฐ€_์ƒํƒœ") + public void canNotAdd() { + // given + Tournament tournamentLive = createTournament(1L, TournamentStatus.LIVE, + LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); + Tournament tournamentEnd = createTournament(2L, TournamentStatus.END, + LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); + given(tournamentRepository.findById(tournamentLive.getId())).willReturn(Optional.of(tournamentLive)); + given(tournamentRepository.findById(tournamentEnd.getId())).willReturn(Optional.of(tournamentEnd)); + // when, then + assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournamentLive.getId(), requestDto)) + .isInstanceOf(TournamentUpdateException.class); + assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournamentEnd.getId(), requestDto)) + .isInstanceOf(TournamentUpdateException.class); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") + public void userNotFound() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + getTargetTime(0, 14, 0), getTargetTime(0, 16, 0)); + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(userRepository.findByIntraId("test")).willReturn(Optional.empty()); + + // when then + assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournament.getId(), requestDto)) + .isInstanceOf(UserNotFoundException.class); + } + + @Test + @DisplayName("์ด๋ฏธ_ํ•ด๋‹น_ํ† ๋„ˆ๋จผํŠธ_์ฐธ๊ฐ€์ค‘์ธ_์œ ์ €") + public void alreadyTournamentParticipant() { + // given + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); + Tournament tournament = tournamentList.get(0); + TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("testUser"); + User user = createUser("testUser"); + TournamentUser tournamentUser = new TournamentUser(user, tournament, true, LocalDateTime.now()); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(userRepository.findByIntraId("testUser")).willReturn(Optional.of(user)); + + // when, then + assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournament.getId(), requestDto)) + .isInstanceOf(TournamentConflictException.class); + } + } + + @Nested + @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‚ญ์ œ_ํ…Œ์ŠคํŠธ") + class TournamentAdminServiceDeleteUserTest { + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") + public void userNotFound() { + //given + List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); + Tournament tournament = tournamentList.get(0); + User user = createUser("user"); + given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); + given(userRepository.findById(null)).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy(() -> tournamentAdminService.deleteTournamentUser(tournament.getId(), user.getId())) + .isInstanceOf(UserNotFoundException.class); + } + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ requestDto + * @param startTime ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @return + */ + private TournamentAdminCreateRequestDto createTournamentCreateRequestDto(String title, LocalDateTime startTime, + LocalDateTime endTime) { + return new TournamentAdminCreateRequestDto( + title, + "์ œ 1ํšŒ ๋ฃจํ‚ค์ „ ๋งŽ๊ด€๋ถ€!!", + startTime, + endTime, + TournamentType.ROOKIE + ); + } + + /** + * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” ์ƒ์„ฑ + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param round ๋ช‡ ๋ฒˆ์งธ ๊ฒŒ์ž„์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด + * @return ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + */ + private TournamentGame createTournamentGame(Tournament tournament, TournamentRound round) { + TournamentGame tournamentGame = new TournamentGame(null, tournament, round); + return tournamentGameRepository.save(tournamentGame); + } + + /** + * ํ˜„์žฌ ์‹œ๊ฐ„์—์„œ days hours, ๋งŒํผ ์ฐจ์ด๋‚˜๋Š” ์‹œ๊ฐ„์„ ๊ตฌํ•œ๋‹ค. + * @param days + * @param hours + * @return + */ + private LocalDateTime getTargetTime(int days, int hours, int minutes) { + return LocalDateTime.now().plusDays(days).withHour(hours).withMinute(minutes); + } + + /** + * ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ดˆ๊ธฐํ™” ๋œ ํ† ๋„ˆ๋จผํŠธ๋ฅผ ๋ฐ˜ํ™˜ + * @param id + * @param status + * @param startTime + * @param endTime + * @return + */ + private Tournament createTournament(Long id, TournamentStatus status, LocalDateTime startTime, + LocalDateTime endTime) { + Tournament tournament = Tournament.builder() + .title(id + "st tournament") + .contents("") + .startTime(startTime) + .endTime(endTime) + .type(TournamentType.ROOKIE) + .status(status) + .build(); + ReflectionUtilsForUnitTest.setFieldWithReflection(tournament, "id", id); + return tournament; + } + + /** + *

id ๋ถ€ํ„ฐ cnt๊ฐœ ๋งŒํผ์˜ ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
+ * ๊ฐ ํ† ๋„ˆ๋จผํŠธ๋Š” 1์‹œ๊ฐ„ ๊ธธ์ด์ด๋ฉฐ, ํ† ๋„ˆ๋จผํŠธ๊ฐ„ 1์‹œ๊ฐ„์˜ ๊ฐ„๊ฒฉ์ด ์žˆ๋‹ค. + * @param id + * @param cnt + * @param startTime + * @return + */ + private List createTournaments(Long id, long cnt, LocalDateTime startTime) { + List tournamentList = new ArrayList<>(); + for (long i = 0; i < cnt; i++) { + tournamentList.add(createTournament(id++, TournamentStatus.BEFORE, + startTime.plusHours(i * 2), startTime.plusHours((i * 2 + 2)))); + } + return tournamentList; + } + + /** + * ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ดˆ๊ธฐํ™”๋œ TournamentAdminUpdateRequestDto๋ฅผ ๋ฐ˜ํ™˜ + * @param startTime + * @param endTime + * @return + */ + private TournamentAdminUpdateRequestDto createTournamentAdminUpdateRequestDto(LocalDateTime startTime, + LocalDateTime endTime) { + return new TournamentAdminUpdateRequestDto( + "tournament changed", + "changed", + startTime, + endTime, + TournamentType.ROOKIE + ); + } + + /** + * ์œ ์ € ์ƒ์„ฑ ๋งค์„œ๋“œ - intraId๋กœ๋งŒ ์ดˆ๊ธฐํ™” + * @param intraId + * @return + */ + private User createUser(String intraId) { + return User.builder() + .eMail("email") + .intraId(intraId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + } + + /** + * cnt ์‚ฌ์ด์ฆˆ์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ + * @param id ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ id + * @param tournament ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ + * @param cnt ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ˆ˜ + * @return + */ + private List createTournamentGames(Long id, Tournament tournament, int cnt) { + List tournamentGameList = new ArrayList<>(); + TournamentRound[] values = TournamentRound.values(); + while (--cnt >= 0) { + tournamentGameList.add(new TournamentGame(null, tournament, values[cnt])); + } + return tournamentGameList; + } + + private SlotManagement createSlot(int gameInterval) { + return SlotManagement.builder() + .pastSlotTime(0) + .futureSlotTime(0) + .openMinute(0) + .gameInterval(gameInterval) + .startTime(LocalDateTime.now().minusHours(1)) + .build(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/user/controller/UserAdminControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/user/controller/UserAdminControllerTest.java new file mode 100644 index 000000000..f07602ba8 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/admin/user/controller/UserAdminControllerTest.java @@ -0,0 +1,266 @@ +package gg.pingpong.api.admin.user.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.List; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.admin.repo.user.UserAdminRepository; +import gg.admin.repo.user.UserImageAdminRepository; +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.pingpong.api.admin.user.controller.response.UserDetailAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserImageListAdminResponseDto; +import gg.pingpong.api.admin.user.controller.response.UserSearchAdminResponseDto; +import gg.pingpong.api.admin.user.dto.UserImageAdminDto; +import gg.pingpong.api.admin.user.dto.UserSearchAdminDto; +import gg.pingpong.api.admin.user.service.UserAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.user.UserNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +class UserAdminControllerTest { + + @Autowired + UserAdminService userAdminService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + UserAdminRepository userAdminRepository; + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + UserImageAdminRepository userImageAdminRepository; + + @BeforeEach + public void setUp() { + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + } + + @Test + @DisplayName("GET /pingpong/admin/users") + @Transactional + public void userSearchAllTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + int page = 1; + int size = 20; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); + String url = "/pingpong/admin/users?page=1"; + String url2 = "/pingpong/admin/users?page=1&intraId=" + user.getIntraId(); + //when + //200 ์„ฑ๊ณต + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, + UserSearchAdminResponseDto.class); + //200 ์„ฑ๊ณต + contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, + UserSearchAdminResponseDto.class); + + //then + List userList1 = userAdminRepository.findAll(pageable).getContent(); + List actureUserList1 = actureResponse1.getUserSearchAdminDtos(); + for (int i = 0; i < userList1.size(); i++) { + Assertions.assertThat(userList1.get(i).getIntraId()).isEqualTo(actureUserList1.get(i).getIntraId()); + } + + List userList2 = userAdminRepository.findAll(pageable).getContent(); + List actureUserList2 = actureResponse2.getUserSearchAdminDtos(); + for (int i = 0; i < userList1.size(); i++) { + Assertions.assertThat(userList2.get(i).getIntraId()).isEqualTo(actureUserList2.get(i).getIntraId()); + } + } + + @Test + @DisplayName("์œ ์ € ํ•„ํ„ฐ๋ง ์กฐํšŒ ํ…Œ์ŠคํŠธ") + @Transactional + public void userFiltering() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.findById(userId).get(); + int page = 1; + int size = 20; + Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); + String url = "/pingpong/admin/users?page=1&userFilter=\"" + user.getIntraId() + "\""; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, + "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, + UserSearchAdminResponseDto.class); + + List actureUserList = actureResponse.getUserSearchAdminDtos(); + for (UserSearchAdminDto userDto : actureUserList) { + Assertions.assertThat(userDto.getIntraId()).isEqualTo(user.getIntraId()); + } + } + + @Test + @DisplayName("GET /pingpong/admin/users/{intraId}") + @Transactional + public void userGetDetailTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = testDataUtils.createNewUser("nheo"); + User target = userRepository.findByIntraId(user.getIntraId()).get(); + String url = "/pingpong/admin/users/" + user.getIntraId(); + UserDetailAdminResponseDto expectedResponse = userAdminService.getUserDetailByIntraId(user.getIntraId()); + + //when + //200 ์„ฑ๊ณต + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserDetailAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, + UserDetailAdminResponseDto.class); + + //then + Assertions.assertThat(actureResponse.getUserId()).isEqualTo(expectedResponse.getUserId()); + Assertions.assertThat(actureResponse.getIntraId()).isEqualTo(expectedResponse.getIntraId()); + Assertions.assertThat(actureResponse.getUserImageUri()).isEqualTo(expectedResponse.getUserImageUri()); + Assertions.assertThat(actureResponse.getRacketType()).isEqualTo(expectedResponse.getRacketType()); + Assertions.assertThat(actureResponse.getWins()).isEqualTo(expectedResponse.getWins()); + Assertions.assertThat(actureResponse.getLosses()).isEqualTo(expectedResponse.getLosses()); + Assertions.assertThat(actureResponse.getPpp()).isEqualTo(expectedResponse.getPpp()); + Assertions.assertThat(actureResponse.getEmail()).isEqualTo(expectedResponse.getEmail()); + Assertions.assertThat(actureResponse.getRoleType()).isEqualTo(expectedResponse.getRoleType()); + Assertions.assertThat(actureResponse.getExp()).isEqualTo(expectedResponse.getExp()); + Assertions.assertThat(actureResponse.getCoin()).isEqualTo(expectedResponse.getCoin()); + } + + /** + * ์ถ”๊ฐ€์ ์œผ๋กœ ์˜๋„ ํ™•์ธ์ด ํ•„์š”ํ•œ ํ…Œ์ŠคํŠธ + * @throws Exception + */ + @Test + @DisplayName("DELETE /pingpong/admin/users/{intraId}") + @Transactional + public void deleteUserProfileImageTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User klew = testDataUtils.createNewUser("klew"); + User user = userRepository.findByIntraId(klew.getIntraId()).get(); + testDataUtils.createUserImages(user, 2); + String url = "/pingpong/admin/users/images/" + user.getIntraId(); + UserImage prevUserImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user) + .orElseThrow(UserNotFoundException::new); + //when + //200 ์„ฑ๊ณต + mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()); + } + + @Test + @DisplayName("GET /pingpong/admin/users/delete-list") + @Transactional + public void getUserImageDeleteListTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + int page = 1; + int size = 30; + String url = "/pingpong/admin/users/delete-list?page=1"; + + //when + //200 ์„ฑ๊ณต + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, + UserImageListAdminResponseDto.class); + + //then + //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ + List actureUserImageList = actureResponse.getUserImageList(); + for (UserImageAdminDto userImageDto : actureUserImageList) { + Assertions.assertThat(userImageDto.getDeletedAt()).isNotEqualTo(null); + } + } + + @Test + @DisplayName("GET /pingpong/admin/users/images") + @Transactional + public void getUserImageListTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + String url = "/pingpong/admin/users/images?page=1"; + testDataUtils.createUserImages(testDataUtils.createNewUser(), 4); + + //when + //200 ์„ฑ๊ณต + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, + UserImageListAdminResponseDto.class); + assertThat(actureResponse.getUserImageList().size()).isEqualTo(3); + } + + @Test + @DisplayName("GET /pingpong/admin/users/images/{intraId}") + @Transactional + public void getUserImageListByIntraIdTest() throws Exception { + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + User user = testDataUtils.createNewUser("klew"); + String url = "/pingpong/admin/users/images/" + user.getIntraId() + "?page=1"; + testDataUtils.createUserImages(user, 3); + + //when + //200 ์„ฑ๊ณต + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ + UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, + UserImageListAdminResponseDto.class); + assertThat(actureResponse.getUserImageList().size()).isEqualTo(2); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/GameUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/GameUnitTest.java new file mode 100644 index 000000000..ce67c4ca7 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/GameUnitTest.java @@ -0,0 +1,121 @@ +package gg.pingpong.api.data.game; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +@UnitTest +@DisplayName("GameUnitTest") +class GameUnitTest { + List mockTeams; + List games; + + @BeforeEach + void setUp() { + mockTeams = IntStream.range(0, 10) + .mapToObj(i -> mock(Team.class)) + .collect(Collectors.toCollection(ArrayList::new)); + games = IntStream.range(0, 10) + .mapToObj(i -> new Game()) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Nested + @DisplayName("AddTeam") + class AddTeam { + @Test + @DisplayName("๋‹จ์ผ Team ์ถ”๊ฐ€ ์„ฑ๊ณต") + public void addSingleTeamSuccess() { + //given + Game game = games.get(0); + Team mockTeam = mockTeams.get(0); + + //when + game.addTeam(mockTeam); + + //then + assertEquals(1, game.getTeams().size()); + assertEquals(mockTeam, game.getTeams().get(0)); + } + + @Test + @DisplayName("๋‘๊ฐœ Team ์ถ”๊ฐ€ ์„ฑ๊ณต") + void addMultiTeamSuccess() { + //given + Game game = games.get(0); + + //when + game.addTeam(mockTeams.get(0)); + game.addTeam(mockTeams.get(1)); + + //then + assertEquals(2, game.getTeams().size()); + assertEquals(mockTeams.get(0), game.getTeams().get(0)); + assertEquals(mockTeams.get(1), game.getTeams().get(1)); + } + + @Test + @DisplayName("๋‘๊ฐœ ์ด์ƒ์˜ Team ์ถ”๊ฐ€ ์‹คํŒจ") + void addExceedTeamFailed() { + //given + Game game = games.get(0); + + //when + game.addTeam(mockTeams.get(0)); + game.addTeam(mockTeams.get(1)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> game.addTeam(mockTeams.get(2))); + assertEquals(ErrorCode.TEAM_SIZE_EXCEED, businessException.getErrorCode()); + assertEquals(ErrorCode.TEAM_SIZE_EXCEED.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("๋™์ผํ•œ Team ์ถ”๊ฐ€ ์‹คํŒจ") + void duplicatedTeamAddFailed() { + //given + Game game = games.get(0); + + //when + game.addTeam(mockTeams.get(0)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> game.addTeam(mockTeams.get(0))); + assertEquals(ErrorCode.TEAM_DUPLICATION, businessException.getErrorCode()); + assertEquals(ErrorCode.TEAM_DUPLICATION.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Game game = games.get(0); + + //when + Team team = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> game.addTeam(team)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/PChangeDataTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/PChangeDataTest.java new file mode 100644 index 000000000..3db8c6c64 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/PChangeDataTest.java @@ -0,0 +1,41 @@ +package gg.pingpong.api.data.game; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.game.PChange; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +public class PChangeDataTest { + + @Test + public void checkPChangeTest() { + + //given + PChange pChange = new PChange(); + + //when + pChange.checkPChange(); + + //then + Assertions.assertThat(pChange.getIsChecked()).isEqualTo(true); + } + + @Test + public void updatePPPTest() { + + //given + PChange pChange = new PChange(); + int testPPP = 4242; + + //when + pChange.updatePPP(testPPP); + + //then + Assertions.assertThat(pChange.getPppResult()).isEqualTo(testPPP); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TeamUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TeamUnitTest.java new file mode 100644 index 000000000..1bb720d3a --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TeamUnitTest.java @@ -0,0 +1,123 @@ +package gg.pingpong.api.data.game; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +@UnitTest +@DisplayName("TeamUnitTest") +class TeamUnitTest { + + List mockTeamUsers; + List teams; + + @BeforeEach + void setUp() { + mockTeamUsers = IntStream.range(0, 10) + .mapToObj(i -> mock(TeamUser.class)) + .collect(Collectors.toCollection(ArrayList::new)); + teams = IntStream.range(0, 10) + .mapToObj(i -> new Team()) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Nested + @DisplayName("AddTeamUser") + class AddTeam { + + @Test + @DisplayName("๋‹จ์ผ TeamUser ์ถ”๊ฐ€ ์„ฑ๊ณต") + public void addSingleTeamSuccess() { + //given + Team team = teams.get(0); + TeamUser mockTeamUser = mockTeamUsers.get(0); + + //when + team.addTeamUser(mockTeamUser); + + //then + assertEquals(1, team.getTeamUsers().size()); + assertEquals(mockTeamUser, team.getTeamUsers().get(0)); + } + + @Test + @DisplayName("๋‘๊ฐœ TeamUser ์ถ”๊ฐ€ ์„ฑ๊ณต") + void addMultiTeamSuccess() { + //given + Team team = teams.get(0); + + //when + team.addTeamUser(mockTeamUsers.get(0)); + team.addTeamUser(mockTeamUsers.get(1)); + + //then + assertEquals(2, team.getTeamUsers().size()); + assertEquals(mockTeamUsers.get(0), team.getTeamUsers().get(0)); + assertEquals(mockTeamUsers.get(1), team.getTeamUsers().get(1)); + } + + @Test + @DisplayName("๋‘๊ฐœ ์ด์ƒ์˜ TeamUser ์ถ”๊ฐ€ ์‹คํŒจ") + void addExceedTeamFailed() { + //given + Team team = teams.get(0); + + //when + team.addTeamUser(mockTeamUsers.get(0)); + team.addTeamUser(mockTeamUsers.get(1)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> team.addTeamUser(mockTeamUsers.get(2))); + assertEquals(ErrorCode.TEAM_USER_EXCEED, businessException.getErrorCode()); + assertEquals(ErrorCode.TEAM_USER_EXCEED.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("๋™์ผํ•œ TeamUser ์ถ”๊ฐ€ ์‹คํŒจ") + void duplicatedTeamAddFailed() { + //given + Team team = teams.get(0); + + //when + team.addTeamUser(mockTeamUsers.get(0)); + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> team.addTeamUser(mockTeamUsers.get(0))); + assertEquals(ErrorCode.TEAM_USER_ALREADY_EXIST, businessException.getErrorCode()); + assertEquals(ErrorCode.TEAM_USER_ALREADY_EXIST.getMessage(), businessException.getMessage()); + } + + @Test + @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") + void nullAddFailed() { + //given + Team team = teams.get(0); + + //when + TeamUser teamUser = null; + + //then + BusinessException businessException = assertThrows(BusinessException.class, + () -> team.addTeamUser(teamUser)); + assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); + assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentGameUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentGameUnitTest.java new file mode 100644 index 000000000..27519a10e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentGameUnitTest.java @@ -0,0 +1,43 @@ +package gg.pingpong.api.data.game; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import gg.data.game.Game; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.utils.annotation.UnitTest; + +@UnitTest +@DisplayName("TournamentGameUnitTest") +public class TournamentGameUnitTest { + + TournamentGame tournamentGame; + + @Nested + @DisplayName("UpdateGame") + class UpdateGame { + @Test + @DisplayName("TournamentGame์˜ ๊ฒŒ์ž„ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") + void updateSuccess() { + //given + tournamentGame = new TournamentGame(new Game(), + new Tournament("", "", LocalDateTime.now(), LocalDateTime.now(), + TournamentType.MASTER, TournamentStatus.BEFORE), null); + Game game = Mockito.mock(Game.class); + + //when + tournamentGame.updateGame(game); + + //then + Assertions.assertEquals(game, tournamentGame.getGame()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentUserUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentUserUnitTest.java new file mode 100644 index 000000000..f96c9afc0 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/game/TournamentUserUnitTest.java @@ -0,0 +1,64 @@ +package gg.pingpong.api.data.game; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.utils.annotation.UnitTest; + +@UnitTest +@DisplayName("TournamentUserUnitTest") +public class TournamentUserUnitTest { + Tournament tournament; + TournamentUser tournamentUser; + User user; + + @Nested + @DisplayName("DeleteTournament") + class DeleteTournament { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ์„ฑ๊ณต") + void deleteSuccess() { + //given + user = Mockito.mock(User.class); + tournament = new Tournament("", "", LocalDateTime.now(), LocalDateTime.now(), + TournamentType.MASTER, TournamentStatus.END); + tournamentUser = new TournamentUser(user, tournament, false, LocalDateTime.now()); + + //when + tournamentUser.deleteTournament(); + + //then + Assertions.assertNull(tournamentUser.getTournament()); + } + } + + @Nested + @DisplayName("UpdateIsJoined") + class UpdateIsJoined { + @Test + @DisplayName("์ฐธ๊ฐ€ ์ •๋ณด ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") + void updateSuccess() { + //given + tournamentUser = new TournamentUser(null, + new Tournament("", "", LocalDateTime.now(), LocalDateTime.now(), null, null), + false, LocalDateTime.now()); + boolean isjoined = true; + + //when + tournamentUser.updateIsJoined(isjoined); + + //then + Assertions.assertEquals(isjoined, tournamentUser.getIsJoined()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/manage/AnnouncementUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/manage/AnnouncementUnitTest.java new file mode 100644 index 000000000..b813cbd68 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/manage/AnnouncementUnitTest.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.data.manage; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.manage.Announcement; +import gg.pingpong.api.admin.manage.dto.AnnouncementAdminAddDto; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("AnnouncementUnitTest") +class AnnouncementUnitTest { + final String content = "content"; + final String intraId = "intraId"; + + @Nested + @DisplayName("findLastAnnouncement_๋ฉ”์„œ๋“œ_unitTest") + class FindLastAnnounceContentTest { + @Test + @DisplayName("update_๋ฉ”์„œ๋“œ_unitTest") + void updateTest() { + String deleterIntraId = "deleter"; + LocalDateTime curTime = LocalDateTime.now(); + Announcement announcement = new Announcement(content, intraId); + announcement.update(deleterIntraId, curTime); + assertThat(announcement.getDeleterIntraId()).isEqualTo(deleterIntraId); + assertThat(announcement.getDeletedAt()).isEqualTo(curTime); + } + + @Test + @DisplayName("from_๋ฉ”์„œ๋“œ_unitTest") + void fromTest() { + AnnouncementAdminAddDto dto = new AnnouncementAdminAddDto(content, intraId); + Announcement announcement = Announcement.from(dto.getContent(), dto.getCreatorIntraId()); + assertThat(announcement.getContent()).isEqualTo(dto.getContent()); + assertThat(announcement.getCreatorIntraId()).isEqualTo(dto.getCreatorIntraId()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/data/store/ItemUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/store/ItemUnitTest.java new file mode 100644 index 000000000..33da59006 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/data/store/ItemUnitTest.java @@ -0,0 +1,47 @@ +package gg.pingpong.api.data.store; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.store.Item; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class ItemUnitTest { + @Nested + @DisplayName("imageUpdateTest") + class ImageUpdateTest { + @Test + @DisplayName("success") + void success() { + Item item = new Item(); + String after = "after"; + setFieldWithReflection(item, "imageUri", "before"); + item.imageUpdate(after); + assertThat(item.getImageUri()).isEqualTo(after); + } + } + + @Nested + @DisplayName("setVisibilityTest") + class SetVisibilityTest { + @Test + @DisplayName("success") + void success() { + Item item = new Item(); + String intraId = "intraId"; + setFieldWithReflection(item, "isVisible", true); + item.setVisibility(intraId); + assertThat(item.getIsVisible()).isFalse(); + assertThat(item.getDeleterIntraId()).isEqualTo(intraId); + } + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerTest.java new file mode 100644 index 000000000..f8c207877 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerTest.java @@ -0,0 +1,85 @@ +package gg.pingpong.api.user.announcement.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.manage.Announcement; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.manage.AnnouncementRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.announcement.AnnounceNotFoundException; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +class AnnouncementControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + AnnouncementRepository announcementRepository; + + @BeforeEach + void setUp() { + User admin = testDataUtils.createAdminUser(); + testDataUtils.createAnnouncements(admin, 5); + } + + @Test + @Transactional + @DisplayName("[GET]/pingpong/announcement") + void getAnnouncement() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + + String contentAsString = mockMvc.perform(get("/pingpong/announcement") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @Transactional + @DisplayName("[GET]/pingpong/announcement") + void getAnnouncementEmpty() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + Announcement announcement = announcementRepository.findFirstByOrderByIdDesc() + .orElseThrow(AnnounceNotFoundException::new); + + announcement.update("testId", LocalDateTime.now()); + + String contentAsString = mockMvc.perform(get("/pingpong/announcement") + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerUnitTest.java new file mode 100644 index 000000000..a6ac432bb --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/controller/AnnouncementControllerUnitTest.java @@ -0,0 +1,43 @@ +package gg.pingpong.api.user.announcement.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.pingpong.api.user.manage.controller.AnnouncementController; +import gg.pingpong.api.user.manage.controller.response.AnnouncementResponseDto; +import gg.pingpong.api.user.manage.dto.AnnouncementDto; +import gg.pingpong.api.user.manage.service.AnnouncementService; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("AnnouncementControllerUnitTest") +class AnnouncementControllerUnitTest { + @Mock + AnnouncementService announcementService; + @InjectMocks + AnnouncementController announcementController; + + @Nested + @DisplayName("findLastAnnounceContent_๋ฉ”์„œ๋“œ_unitTest") + class FindLastAnnounceContentTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + String content = "content"; + given(announcementService.findLastAnnouncement()).willReturn(new AnnouncementDto(content)); + // when, then + assertThat(announcementController.findLastAnnounceContent()).isInstanceOf(AnnouncementResponseDto.class); + assertThat(announcementController.findLastAnnounceContent().getContent()).isEqualTo(content); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/service/AnnouncementServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/service/AnnouncementServiceUnitTest.java new file mode 100644 index 000000000..f30e86f5c --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/announcement/service/AnnouncementServiceUnitTest.java @@ -0,0 +1,73 @@ +package gg.pingpong.api.user.announcement.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.manage.Announcement; +import gg.pingpong.api.user.manage.service.AnnouncementService; +import gg.repo.manage.AnnouncementRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.announcement.AnnounceNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("AnnouncementServiceUnitTest") +class AnnouncementServiceUnitTest { + @Mock + AnnouncementRepository announcementRepository; + @InjectMocks + AnnouncementService announcementService; + + @Nested + @DisplayName("findLastAnnouncement_๋ฉ”์„œ๋“œ_unitTest") + class FindLastAnnounceContentTest { + @Test + @DisplayName("์„ฑ๊ณต") + void success() { + //given + String content = "content"; + String intraId = "intraId"; + Announcement announcement = new Announcement(content, intraId); + given(announcementRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + // when, then + assertThat(announcementService.findLastAnnouncement().getContent()).isEqualTo(content); + verify(announcementRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("์„ฑ๊ณต_์‚ญ์ œ๋œ_announcement") + void successAnnouncementDeleted() { + //given + String content = "content"; + String intraId = "intraId"; + Announcement announcement = new Announcement(content, intraId); + announcement.update(intraId, LocalDateTime.now()); + given(announcementRepository.findFirstByOrderByIdDesc()).willReturn(Optional.of(announcement)); + // when, then + assertThat(announcementService.findLastAnnouncement().getContent()).isEqualTo(""); + verify(announcementRepository, times(1)).findFirstByOrderByIdDesc(); + } + + @Test + @DisplayName("Announcement_404") + void announcementNotFound() { + //given + given(announcementRepository.findFirstByOrderByIdDesc()).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> announcementService.findLastAnnouncement()) + .isInstanceOf(AnnounceNotFoundException.class); + verify(announcementRepository, times(1)).findFirstByOrderByIdDesc(); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/CoinHistoryServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/CoinHistoryServiceTest.java new file mode 100644 index 000000000..3b61b83ba --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/CoinHistoryServiceTest.java @@ -0,0 +1,156 @@ +package gg.pingpong.api.user.coin.service; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.store.CoinHistory; +import gg.data.store.CoinPolicy; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.repo.store.CoinHistoryRepository; +import gg.repo.store.CoinPolicyRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@RequiredArgsConstructor +@Transactional +class CoinHistoryServiceTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinHistoryService coinHistoryService; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + CoinPolicyRepository coinPolicyRepository; + + @BeforeEach + void beforeEach() { + CoinPolicy coinPolicy = CoinPolicy.builder() + .user(testDataUtils.createAdminUser()) + .attendance(1) + .normal(3) + .rankWin(10) + .rankLose(5) + .build(); + coinPolicyRepository.save(coinPolicy); + } + + @Test + @DisplayName("์ถœ์„ ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") + void addAttendanceCoinHistory() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addAttendanceCoinHistory(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for (CoinHistory ch : afterCoinHistory) { + System.out.println("์ด๋ ฅ : " + ch.getHistory()); + System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); + System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); + System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); + } + } + + @Test + @DisplayName("์ผ๋ฐ˜๊ฒŒ์ž„ ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") + void addNormalCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addNormalCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for (CoinHistory ch : afterCoinHistory) { + System.out.println("์ด๋ ฅ : " + ch.getHistory()); + System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); + System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); + System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); + } + + } + + @Test + @DisplayName("๋žญํฌ๊ฒŒ์ž„ win ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") + void addRankWinCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addRankWinCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for (CoinHistory ch : afterCoinHistory) { + System.out.println("์ด๋ ฅ : " + ch.getHistory()); + System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); + System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); + System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); + } + } + + @Test + @DisplayName("๋žญํฌ๊ฒŒ์ž„ lose ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") + void addRankLoseCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); + + coinHistoryService.addRankLoseCoin(user); + coinHistoryService.addRankLoseCoin(user); + + List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); + + assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 2); + + System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); + for (CoinHistory ch : afterCoinHistory) { + System.out.println("์ด๋ ฅ : " + ch.getHistory()); + System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); + System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); + System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/UserCoinChangeServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/UserCoinChangeServiceTest.java new file mode 100644 index 000000000..afcf7a41b --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/coin/service/UserCoinChangeServiceTest.java @@ -0,0 +1,228 @@ +package gg.pingpong.api.user.coin.service; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.season.Season; +import gg.data.store.CoinPolicy; +import gg.data.store.Item; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.dto.UserGameCoinResultDto; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.pingpong.api.user.store.service.UserCoinChangeService; +import gg.repo.store.CoinHistoryRepository; +import gg.repo.store.CoinPolicyRepository; +import gg.repo.store.ItemRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.coin.CoinHistoryNotFoundException; +import gg.utils.exception.coin.CoinPolicyNotFoundException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@RequiredArgsConstructor +@Transactional +class UserCoinChangeServiceTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + CoinHistoryService coinHistoryService; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + CoinPolicyRepository coinPolicyRepository; + + @Autowired + UserRepository userRepository; + + @Autowired + UserCoinChangeService userCoinChangeService; + + @Autowired + ItemRepository itemRepository; + + User admin; + + @BeforeEach + void init() { + admin = testDataUtils.createAdminUser(); + } + + @Test + @DisplayName("์ถœ์„์‹œ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") + void addAttendanceCoin() { + CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).attendance(100).build(); + coinPolicyRepository.save(coinPolicy); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + int beforeCoin = user.getGgCoin(); + + int coinIncrement = userCoinChangeService.addAttendanceCoin(user); + + assertThat(beforeCoin + coinIncrement).isEqualTo(user.getGgCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getAttendance()).isEqualTo(coinIncrement); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getHistory()); + + try { + coinIncrement = userCoinChangeService.addAttendanceCoin(user); + } catch (Exception e) { + System.out.println(e.getMessage() + " " + e); + System.out.println("===์ถœ์„ ์ค‘๋ณต ์ œ๊ฑฐ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); + } + } + + @Test + @DisplayName("์•„์ดํ…œ ๊ตฌ๋งค์‹œ ์ฝ”์ธ์‚ฌ์šฉ ํ…Œ์ŠคํŠธ") + void purchaseItemCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + user.addGgCoin(100); + int beforeCoin = user.getGgCoin(); + + Item item = new Item("๊ณผ์ž", "111", "1", "1", 100, true, 0, + ItemType.EDGE, LocalDateTime.now(), user.getIntraId()); + itemRepository.save(item); + + userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); + + assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory() + + coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getAmount()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + try { + userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); + } catch (Exception e) { + System.out.println(e.getMessage() + " " + e); + System.out.println("===coin์ด ์—†์„ ๋•Œ ๋ฐฉ์–ด๋กœ์ง ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); + } + } + + @Test + @DisplayName("์•„์ดํ…œ ์„ ๋ฌผ์‹œ ์ฝ”์ธ์‚ฌ์šฉ ํ…Œ์ŠคํŠธ") + void giftItemCoin() { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + user.addGgCoin(100); + int beforeCoin = user.getGgCoin(); + + Item item = new Item("๊ณผ์ž", "111", "1", "1", 100, true, 0, + ItemType.EDGE, LocalDateTime.now(), user.getIntraId()); + itemRepository.save(item); + + userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); + + assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getHistory() + + coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getAmount()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getHistory()); + + try { + userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); + } catch (Exception e) { + System.out.println(e.getMessage() + " " + e); + System.out.println("===coin์ด ์—†์„ ๋•Œ ๋ฐฉ์–ด๋กœ์ง ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); + } + } + + @Test + @DisplayName("๋…ธ๋ง ๊ฒŒ์ž„ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") + void addNormalGameService() { + CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).normal(100).build(); + coinPolicyRepository.save(coinPolicy); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal()).isEqualTo( + userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); + } + + @Test + @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ์Šน๋ฆฌ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") + void addRankWinGameService() { + CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).rankWin(100).build(); + coinPolicyRepository.save(coinPolicy); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + Season season = testDataUtils.createSeason(); + Game mockMatch = testDataUtils.createMockMatch(user, season, + LocalDateTime.now().minusMinutes(20), + LocalDateTime.now().minusMinutes(5), Mode.RANK, 2, 1); + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService + .addRankGameCoin(mockMatch.getId(), user.getId()); //๋ณธ์ธ์˜ ๊ฒŒ์ž„Id์™€ id ๊ฐ’ + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getRankWin()) + .isEqualTo(userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getHistory()); + } + + @Test + @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ํŒจ๋ฐฐ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") + void addRankLoseGameService() { + CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).rankLose(100).build(); + coinPolicyRepository.save(coinPolicy); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + + Season season = testDataUtils.createSeason(); + Game mockMatch = testDataUtils.createMockMatch(user, season, + LocalDateTime.now().minusMinutes(20), + LocalDateTime.now().minusMinutes(5), Mode.RANK, 1, 2); + + UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService + .addRankGameCoin(mockMatch.getId(), user.getId()); + + assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); + assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() + .orElseThrow(CoinPolicyNotFoundException::new).getRankLose()) + .isEqualTo(userGameCoinResultDto.getCoinIncrement()); + System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() + .orElseThrow(CoinHistoryNotFoundException::new).getHistory()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerTest.java new file mode 100644 index 000000000..ea796ed73 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerTest.java @@ -0,0 +1,76 @@ +package gg.pingpong.api.user.feedback.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.manage.Feedback; +import gg.data.manage.type.FeedbackType; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.manage.controller.request.FeedbackRequestDto; +import gg.repo.manage.FeedbackRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +class FeedbackControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + FeedbackRepository feedbackRepository; + + @Test + @Transactional + @DisplayName("[Post]/pingpong/feedback") + void getAnnouncementList() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + + FeedbackRequestDto addDto = FeedbackRequestDto.builder() + .content("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜ํ…Œ์ŠคํŠธ") + .category(FeedbackType.ETC) + .build(); + + String content = objectMapper.writeValueAsString(addDto); + String url = "/pingpong/feedback"; + + String contentAsString = mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + Feedback result = feedbackRepository.findFirstByOrderByIdDesc(); + assertThat(result.getCategory()).isEqualTo(addDto.getCategory()); + assertThat(result.getContent()).isEqualTo(addDto.getContent()); + + System.out.println(result.getId() + ", " + result.getUser().getIntraId()); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerUnitTest.java new file mode 100644 index 000000000..be96ba9ac --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/controller/FeedbackControllerUnitTest.java @@ -0,0 +1,40 @@ +package gg.pingpong.api.user.feedback.controller; + +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.pingpong.api.user.manage.controller.FeedbackController; +import gg.pingpong.api.user.manage.controller.request.FeedbackRequestDto; +import gg.pingpong.api.user.manage.service.FeedbackService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("FeedbackAdminServiceUnitTest") +class FeedbackControllerUnitTest { + @Mock + FeedbackService feedbackService; + @InjectMocks + FeedbackController feedbackController; + + @Nested + @DisplayName("FeedbackSaveUnitTest") + class FeedbackSaveUnitTest { + @Test + @DisplayName("success") + void success() { + // given + UserDto userDto = UserDto.builder().id(1L).build(); + // when, then + feedbackController.feedbackSave(mock(FeedbackRequestDto.class), userDto); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/service/FeedbackServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/service/FeedbackServiceUnitTest.java new file mode 100644 index 000000000..452020e35 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/feedback/service/FeedbackServiceUnitTest.java @@ -0,0 +1,62 @@ +package gg.pingpong.api.user.feedback.service; + +import static org.mockito.BDDMockito.*; + +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.manage.Feedback; +import gg.data.user.User; +import gg.pingpong.api.user.manage.controller.request.FeedbackRequestDto; +import gg.pingpong.api.user.manage.service.FeedbackService; +import gg.repo.manage.FeedbackRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("FeedbackServiceUnitTest") +class FeedbackServiceUnitTest { + @Mock + UserRepository userRepository; + @Mock + FeedbackRepository feedbackRepository; + @InjectMocks + FeedbackService feedbackService; + + @Nested + @DisplayName("FeedbackSaveUnitTest") + class FeedbackSaveUnitTest { + @Test + @DisplayName("success") + void success() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(mock(User.class))); + given(feedbackRepository.save(any(Feedback.class))).willReturn(mock(Feedback.class)); + // when, then + feedbackService.addFeedback(new FeedbackRequestDto(), 1L); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(feedbackRepository, times(1)).save(any(Feedback.class)); + } + + @Test + @DisplayName("user_not_found") + void userNotFound() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + Assertions.assertThatThrownBy(() -> feedbackService.addFeedback(new FeedbackRequestDto(), 1L)) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/GameControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/GameControllerTest.java new file mode 100644 index 000000000..ff71b42b0 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/GameControllerTest.java @@ -0,0 +1,838 @@ +package gg.pingpong.api.user.game; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.pingpong.api.user.game.controller.request.TournamentResultReqDto; +import gg.pingpong.api.user.game.controller.response.GameListResDto; +import gg.pingpong.api.user.game.dto.GameTeamInfo; +import gg.pingpong.api.user.game.service.GameFindService; +import gg.pingpong.api.user.game.service.GameService; +import gg.pingpong.api.user.rank.redis.RankRedisService; +import gg.repo.game.GameRepository; +import gg.repo.game.PChangeRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@AutoConfigureMockMvc +@RequiredArgsConstructor +@Transactional +public class GameControllerTest { + @Autowired + GameRepository gameRepository; + @Autowired + SeasonRepository seasonRepository; + @Autowired + TeamRepository teamRepository; + @Autowired + TeamUserRepository teamUserRepository; + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + PChangeRepository pChangeRepository; + @Autowired + TournamentRepository tournamentRepository; + @Autowired + RankRedisService rankRedisService; + @Autowired + RankRepository rankRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + GameService gameService; + @Autowired + GameFindService gameFindService; + @Autowired + private MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + private String accessToken; + private Season season; + private User user1; + private User user2; + private User user3; + private Game game1; + private Game game2; + ArrayList tiers; + + @BeforeEach + void init() { + tiers = testDataUtils.createTierSystem("pingpong"); + season = seasonRepository.save( + new Season("test season", LocalDateTime.of(2023, 7, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), + 1000, 100)); + user1 = testDataUtils.createNewUser("test1", "test1@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + accessToken = tokenProvider.createToken(user1.getId()); + user2 = testDataUtils.createNewUser("test2", "test2@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + Tier tier = tiers.get(0); + rankRepository.save(Rank.from(user1, season, season.getStartPpp(), tier)); + rankRepository.save(Rank.from(user2, season, season.getStartPpp(), tier)); + RankRedis userRank = RankRedis.from(user1.getId(), user1.getIntraId(), user1.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); + userRank = RankRedis.from(user2.getId(), user2.getIntraId(), user2.getTextColor(), season.getStartPpp(), + tier.getImageUri()); + rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank); + + game1 = gameRepository.save( + new Game(season, StatusType.END, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game1, 1, false)); + Team team2 = teamRepository.save(new Team(game1, 2, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + game2 = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); + team1 = teamRepository.save(new Team(game2, 1, false)); + team2 = teamRepository.save(new Team(game2, 2, true)); + List teams = new ArrayList<>(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + gameService.expUpdates(game2, teams); + rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game2); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + // GET /pingpong/games/{gameId} + @Nested + @DisplayName("๊ฒŒ์ž„ ์กฐํšŒ ํ…Œ์ŠคํŠธ") + class GetGameInfoTest { + /** + * getGameInfo() -> GameFindService.getGameInfo() + */ + @Test + @DisplayName("์œ ์ € ์ฟผ๋ฆฌ ํฌํ•จ ์„ฑ๊ณต") + public void getGameInfoTest() throws Exception { + //given + String url = "/pingpong/games/" + game1.getId().toString(); + GameTeamInfo expect = gameService.getUserGameInfo(game1.getId(), user1.getId()); + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + GameTeamInfo result = objectMapper.readValue(contentAsString, GameTeamInfo.class); + System.out.println("expect: " + expect); + System.out.println("result: " + result); + assertThat(result.getGameId()).isEqualTo(expect.getGameId()); + assertThat(result.getStartTime()).isEqualTo(expect.getStartTime()); + assertThat(result.getMatchTeamsInfo().getMyTeam().getTeamId()).isEqualTo( + expect.getMatchTeamsInfo().getMyTeam().getTeamId()); + assertThat(result.getMatchTeamsInfo().getEnemyTeam().getTeamId()).isEqualTo( + expect.getMatchTeamsInfo().getEnemyTeam().getTeamId()); + } + } + + // GET /pingpong/games/normal + @Nested + @DisplayName("normal ๊ฒŒ์ž„ ์กฐํšŒ") + class NormalGameListTest { + /** + * GET /pingpong/games/normal?page=1&size=10 + * normalGameList() -> GameFindService.normalGameList() + */ + @Test + @DisplayName("์กฐํšŒ ์„ฑ๊ณต") + public void success() throws Exception { + //given + testDataUtils.createGame(user1, LocalDateTime.now().minusMinutes(16), + LocalDateTime.now().minusMinutes(1), season, Mode.NORMAL); + String url = "/pingpong/games/normal?page=1&size=10"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.getNormalGameList(pageable); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + /** + * GET /pingpong/games/normal?page=1&size=10&intraId=test1 + * normalGameList() -> GameFindService.normalGameListByIntra() + */ + @Test + @DisplayName("์œ ์ € ์ฟผ๋ฆฌ ํฌํ•จ ์„ฑ๊ณต") + public void successUserQuery() throws Exception { + //given + String url = "/pingpong/games/normal?page=1&size=10&intraId=test1"; + for (int i = 0; i < 10; i++) { + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, 1, false)); + Team team2 = teamRepository.save(new Team(game, 2, true)); + List teams = new ArrayList<>(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + gameService.expUpdates(game, teams); + rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game); + game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + team1 = teamRepository.save(new Team(game, 0, false)); + team2 = teamRepository.save(new Team(game, 0, false)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + teams.clear(); + teams.add(teamUserRepository.save(new TeamUser(team1, user1))); + teams.add(teamUserRepository.save(new TeamUser(team2, user2))); + game.updateStatus(); + gameService.expUpdates(game, teams); + pChangeRepository.save(new PChange(game, user1, 0, true)); + pChangeRepository.save(new PChange(game, user2, 0, true)); + } + + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.normalGameListByIntra(pageable, "test1"); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + } + + // GET /pingpong/games/rank + @Nested + @DisplayName("rank ๊ฒŒ์ž„ ์กฐํšŒ") + class RankGameListTest { + /** + * GET /pingpong/games/rank?page=1&size=10&seasonId=1 + * rankGameList() -> GameFindService.rankGameList() + */ + @Test + @DisplayName("์กฐํšŒ ์„ฑ๊ณต") + public void success() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId(); + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.rankGameList(pageable, season.getId()); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + /** + * GET /pingpong/games/rank?page=1&size=10&seasonId={seasonId}&nickname=test1 + * rankGameList() -> GameFindService.rankGameListByIntra() + */ + @Test + @DisplayName("nickname ์ฟผ๋ฆฌ ํฌํ•จ ์กฐํšŒ ์„ฑ๊ณต") + public void successNicknameQuery() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId() + "&nickname=" + "test1"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.rankGameListByIntra(pageable, season.getId(), "test1"); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + /** + * GET /pingpong/games/rank?page=1&size=0 + * allGameList() -> GameFindService.allGameList() + */ + @Test + @DisplayName("Bad Request exception ๋ฐœ์ƒ") + public void failBadRequest() throws Exception { + //given + String url = "/pingpong/games/rank?page=1&size=0"; + //then + mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + } + + // GET /pingpong/games + @Nested + @DisplayName("์ „์ฒด ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ") + class AllGameListTest { + /** + * GET /pingpong/games?page=1&size=10 + */ + @Test + @DisplayName("์กฐํšŒ ์„ฑ๊ณต") + public void success() throws Exception { + //given + String url = "/pingpong/games?page=1&size=10"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.allGameList(pageable, null); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames() + .get(result.getGames().size() - 1) + .getGameId() + .equals(expect.getGames().get(expect.getGames().size() - 1).getGameId())); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + /** + * GET /pingpong/games?page=1&size=10&nickname=test1 + */ + @Test + @DisplayName("nickname ์ฟผ๋ฆฌ ํฌํ•จ ์กฐํšŒ ์„ฑ๊ณต") + public void suceessNicknameQuery() throws Exception { + //given + String url = "/pingpong/games?page=1&size=10&nickname=test1"; + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto expect = gameFindService.allGameListUser(pageable, "test1", null); + //when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); + //then + System.out.println(result.getGames().size() + ", " + result.getIsLast()); + System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); + assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); + assertThat(result.getGames().get(result.getGames().size() - 1).getGameId()).isEqualTo( + expect.getGames().get(expect.getGames().size() - 1).getGameId()); + assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); + } + + /** + * GET /pingpong/games?pageNum=1&pageSize=10&status=live + */ + @Test + @DisplayName("์ž˜๋ชป๋œ query parameter์ธ ๊ฒฝ์šฐ, Bad Request exception ๋ฐœ์ƒ") + public void failBadRequest() throws Exception { + String url = "/pingpong/games?pageNum=1&pageSize=10&status=live"; // LIVE ๋Œ€๋ฌธ์ž์—ฌ์•ผ ํ•จ + mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + } + + /** + * GET /pingpong/games?page=1&size=10&status=2 + */ + @Test + @DisplayName("์ž˜๋ชป๋œ query parameter์ธ ๊ฒฝ์šฐ, Bad Request exception ๋ฐœ์ƒ") + public void failBadRequest2() throws Exception { + String url = "/pingpong/games?page=1&size=10&status=2"; + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + System.out.println(contentAsString); + } + } + + // POST /pingpong/games/rank + @Nested + @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ์ ์ˆ˜ ๊ฒฐ๊ณผ ์ž…๋ ฅ") + class CreateRankResultTest { + /** + * POST /pingpong/games/rank + */ + @Test + @DisplayName("๋‘˜ ์ค‘ ํ•œ๋ช… ์ž…๋ ฅ ํ›„ ๋‚˜๋จธ์ง€ ํ•œ ๋ช…์ด ์ž…๋ ฅํ•  ๊ฒฝ์šฐ conflict exception ๋ฐœ์ƒ") + public void success() throws Exception { + String url = "/pingpong/games/rank"; + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + String ac2 = tokenProvider.createToken(user2.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + teamUserRepository.flush(); + gameRepository.flush(); + teamRepository.flush(); + String content = objectMapper.writeValueAsString( + new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + // then + System.out.println("======================="); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse(); + System.out.println("======================="); + content = objectMapper.writeValueAsString( + new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isConflict()) + .andReturn().getResponse(); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + } + + // TODO : ๋žญํฌ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์ž…๋ ฅ ์‹คํŒจ ํ…Œ์ŠคํŠธ (์ž˜๋ชป๋œ ์ ์ˆ˜ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ InvalidParameterException ๋ฐœ์ƒ) + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ๊ฒฐ๊ณผ ์ž…๋ ฅ") + class CreateTournamentResultTest { + @Test + @DisplayName("์ž…๋ ฅ ์„ฑ๊ณต") + public void success() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Tournament tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "ttt"); + List tournamentGameList = testDataUtils.createTournamentGameList(tournament, + Tournament.ALLOWED_JOINED_NUMBER - 1); + // 8๊ฐ• ๊ฒฝ๊ธฐ ์ƒ์„ฑ + Game game = null; + Team team1 = null; + Team team2 = null; + for (int i = 0; i < Tournament.ALLOWED_JOINED_NUMBER / 2; ++i) { + game = new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now()); + team1 = new Team(game, -1, false); + team2 = new Team(game, -1, false); + TeamUser teamUser1 = new TeamUser(team1, tournament.getTournamentUsers().get(i * 2).getUser()); + TeamUser teamUser2 = new TeamUser(team2, tournament.getTournamentUsers().get(i * 2 + 1).getUser()); + gameRepository.save(game); + tournamentGameList.get(i).updateGame(game); + } + + testDataUtils.createUserRank(team1.getTeamUsers().get(0).getUser(), "", season); + testDataUtils.createUserRank(team2.getTeamUsers().get(0).getUser(), "", season); + + String ac1 = tokenProvider.createToken(team1.getTeamUsers().get(0).getUser().getId()); + String content = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + + //when + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + //then + assertThat(game.getStatus()).isEqualTo(StatusType.END); + assertThat(pChangeRepository.findByUserIdAndGameId(team1.getTeamUsers().get(0).getUser().getId(), + game.getId())).isNotEmpty(); + assertThat(pChangeRepository.findByUserIdAndGameId(team2.getTeamUsers().get(0).getUser().getId(), + game.getId())).isNotEmpty(); + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ Game Id") + public void invalidGameId() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content = objectMapper.writeValueAsString( + new TournamentResultReqDto(99999999L, team1.getId(), 1, team2.getId(), 2)); + //when + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + //then + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ Team Id") + public void invalidTeamId() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Game game2 = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(30), + LocalDateTime.now().minusMinutes(15))); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + Team team3 = teamRepository.save(new Team(game2, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content1 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), -1L, 1, team2.getId(), 2)); + String content2 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, -1L, 2)); + String content3 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, team3.getId(), 2)); + //when1 - ์กด์žฌํ•˜์ง€ ์•Š๋Š” myTeamId + String contentAsString1 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content1)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then + System.out.println(contentAsString1); + + //when2 - ์กด์žฌํ•˜์ง€ ์•Š๋Š” enemyTeamId + String contentAsString2 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content2)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then2 + System.out.println(contentAsString2); + + //when3 - game์— ์กด์žฌํ•˜์ง€ ์•Š์€ TeamId + String contentAsString3 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content3)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + //then3 + System.out.println(contentAsString2); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ ์ ์ˆ˜") + public void invalidScore() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content1 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), -1, team2.getId(), 2)); + String content2 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 1)); + String content3 = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 3, team2.getId(), 0)); + //when1 + String contentAsString1 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content1)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then1 + System.out.println(contentAsString1); + + //when2 + String contentAsString2 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content2)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then2 + System.out.println(contentAsString2); + + //when3 + String contentAsString3 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content3)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then3 + System.out.println(contentAsString3); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ Game Status") + public void invalidStatus() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Game game = gameRepository.save( + new Game(season, StatusType.END, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + //when + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ด๋ฏธ ์ ์ˆ˜ ์ž…๋ ฅ์ด ์™„๋ฃŒ๋œ ๊ฒŒ์ž„") + public void scoreAlreadyEntered() throws Exception { + //given + String url = "/pingpong/games/tournament"; + Game game = gameRepository.save( + new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, 2, true)); + Team team2 = teamRepository.save(new Team(game, 1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 2, team2.getId(), 1)); + //when + String contentAsString = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ Team User") + public void invalidTeamUser() throws Exception { + //given + String url = "/pingpong/games/tournament"; + user3 = testDataUtils.createNewUser("test3", "test3@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + teamUserRepository.save(new TeamUser(team1, user3)); + teamUserRepository.save(new TeamUser(team2, user2)); + String content = objectMapper.writeValueAsString( + new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + //when + String contentAsString1 = mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + //then + System.out.println(contentAsString1); + } + } + + // POST /pingpong/games/normal + @Nested + @DisplayName("์ผ๋ฐ˜ ๊ฒŒ์ž„ ์ข…๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ") + class CreateNormalResultTest { + /** + * POST /pingpong/games/normal + */ + @Test + @DisplayName("๊ฒŒ์ž„ ์ข…๋ฃŒ") + public void success() throws Exception { + String url = "/pingpong/games/normal"; + Game game = gameRepository.save( + new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), + LocalDateTime.now())); + Team team1 = teamRepository.save(new Team(game, -1, false)); + Team team2 = teamRepository.save(new Team(game, -1, false)); + String ac1 = tokenProvider.createToken(user1.getId()); + String ac2 = tokenProvider.createToken(user2.getId()); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + teamUserRepository.flush(); + gameRepository.flush(); + teamRepository.flush(); + String content = objectMapper.writeValueAsString( + new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + // then + System.out.println("======================="); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse(); + System.out.println("======================="); + content = objectMapper.writeValueAsString( + new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); + mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andExpect(status().isCreated()) + .andReturn().getResponse(); + System.out.println(user1.getTotalExp()); + System.out.println(user2.getTotalExp()); + } + // TODO HttpStatus.ACCEPTED ํ…Œ์ŠคํŠธ - service ํ•จ์ˆ˜์—์„œ BEFORE ์ƒํƒœ์ผ ๋•Œ false ๋ฆฌํ„ดํ•  ๊ฒฝ์šฐ + } + + @Nested + @DisplayName("/{gameId}/result?mode=?") + class GameChangeRestTest { + @Test + @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") + public void successGetRankPppChange() throws Exception { + Game mockMatch = testDataUtils.createMockMatch(user1, season, + LocalDateTime.now().minusMinutes(16), + LocalDateTime.now().minusMinutes(1), Mode.RANK); + testDataUtils.createUserRank(user1, "hello", season, tiers.get(0)); + testDataUtils.createCoinPolicy(user1, 0, 0, 1, 0); + + String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.RANK; + String content = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println("result: " + content); + } + + @Test + @DisplayName("์ผ๋ฐ˜ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") + public void normalGameResult() throws Exception { + Game mockMatch = testDataUtils.createMockMatch(user1, season, + LocalDateTime.now().minusMinutes(16), + LocalDateTime.now().minusMinutes(1), Mode.NORMAL); + testDataUtils.createCoinPolicy(user1, 0, 1, 0, 0); + String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.NORMAL; + String content = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println("result: " + content); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") + public void tournamentGameResult() throws Exception { + Game mockMatch = testDataUtils.createMockMatch(user1, season, + LocalDateTime.now().minusMinutes(16), + LocalDateTime.now().minusMinutes(1), Mode.TOURNAMENT); + testDataUtils.createCoinPolicy(user1, 0, 1, 0, 0); + String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.TOURNAMENT; + String content = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + System.out.println("result: " + content); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameDBTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameDBTest.java new file mode 100644 index 000000000..dd1fad1e7 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameDBTest.java @@ -0,0 +1,106 @@ +package gg.pingpong.api.user.game.service; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import javax.persistence.EntityManager; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.admin.game.service.GameAdminService; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.game.GameRepository; +import gg.repo.game.PChangeRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@RequiredArgsConstructor +@AutoConfigureMockMvc +@Transactional +@Slf4j +public class GameDBTest { + + @Autowired + GameFindService gameFindService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RankRedisRepository rankRedisRepository; + @Autowired + GameRepository gameRepository; + @Autowired + GameAdminService gameAdminService; + @Autowired + TeamRepository teamRepository; + @Autowired + TeamUserRepository teamUserRepository; + @Autowired + PChangeRepository pChangeRepository; + @Autowired + EntityManager em; + @Autowired + MockMvc mockMvc; + + @Test + @DisplayName(value = "Cascade ์ข…์†์‚ญ์ œํ…Œ์ŠคํŠธ") + @Transactional + public void cascadeTest() throws Exception { + pChangeRepository.deleteAll(); + gameRepository.deleteAll(); + em.flush(); + List gameList = gameRepository.findAll(); + List teamList = teamRepository.findAll(); + List teamUserList = teamUserRepository.findAll(); + log.info("GAME LIST SIZE : " + Integer.toString(gameList.size())); + log.info("TEAM LIST SIZE: " + Integer.toString(teamList.size())); + log.info("TEAM_USER LIST SIZE: " + Integer.toString(teamUserList.size())); + Assertions.assertThat(teamList.size()).isEqualTo(0); + Assertions.assertThat(teamUserList.size()).isEqualTo(0); + } + + @Test + @DisplayName(value = "game ์ „์ ์กฐํšŒ ์ฟผ๋ฆฌ ์ˆ˜ ํ…Œ์ŠคํŠธ") + @Transactional + public void gameStatusQuery() throws Exception { + Season season = testDataUtils.createSeason(); + User user = testDataUtils.createNewUser(); + for (int i = 0; i < 20; i++) { + testDataUtils.createMockMatch(user, season, LocalDateTime.now().minusMinutes(15 * i + 20), + LocalDateTime.now().minusMinutes(15 * i + 5), Mode.RANK, 2, 1); + } + //given + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/admin/games?page=1&seasonId=" + season.getId(); + + //when + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameFindServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameFindServiceTest.java new file mode 100644 index 000000000..deca8b8f5 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameFindServiceTest.java @@ -0,0 +1,108 @@ +package gg.pingpong.api.user.game.service; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.Sort; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.game.controller.response.GameListResDto; +import gg.pingpong.api.user.game.controller.response.GameResultResDto; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameTeamUser; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@RequiredArgsConstructor +@Transactional +public class GameFindServiceTest { + + @Autowired + GameFindService gameFindService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + GameRepository gameRepository; + + @BeforeEach + void init() { + testDataUtils.createTierSystem("pingpong"); + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + String accessToken = tokenProvider.createToken(newUser.getId()); + String statusMsg = "status message test1"; + + LocalDateTime startTime = LocalDateTime.now().minusDays(1); + LocalDateTime endTime = startTime.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime, endTime); + + LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); + LocalDateTime endTime1 = startTime1.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); + + LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); + LocalDateTime endTime2 = startTime2.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); + + testDataUtils.createUserRank(newUser, statusMsg, season); + RankRedis userRank = RankRedis.from(newUser.getId(), newUser.getIntraId(), newUser.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, newUser.getId(), userRank); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + @Test + void normalGameListGet() { + Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); + GameListResDto response = gameFindService.getNormalGameList(pageable); + Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); + GameListResDto expect = new GameListResDto( + getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), + games.isLast()); + assertThat(response).isEqualTo(expect); + } + + private List getGameResultList(List games) { + List teamViews = gameRepository.findTeamsByGameIsIn(games); + return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameServiceTest.java new file mode 100644 index 000000000..e26469fe4 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameServiceTest.java @@ -0,0 +1,123 @@ +package gg.pingpong.api.user.game.service; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.repo.game.GameRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.rank.RankNotFoundException; +import gg.utils.exception.tier.TierNotFoundException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@RequiredArgsConstructor +@Transactional +public class GameServiceTest { + + @Autowired + RankRedisRepository rankRedisRepository; + + @Autowired + GameRepository gameRepository; + @Autowired + TeamRepository teamRepository; + + @Autowired + TeamUserRepository teamUserRepository; + + @Autowired + RankRepository rankRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + GameService gameService; + + User user1; + User user2; + Game game1; + Team team1; + Team team2; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + + @BeforeEach + void init() { + testDataUtils.createTierSystem("pingpong"); + Season season = testDataUtils.createSeason(); + Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); + user1 = testDataUtils.createNewUser(); + user2 = testDataUtils.createNewUser(); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), + now.getHour(), now.getMinute()); + game1 = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime, startTime.plusMinutes(15))); + team1 = teamRepository.save(new Team(game1, -1, false)); + team2 = teamRepository.save(new Team(game1, -1, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + String statusMsg = "status message test1"; + + testDataUtils.createUserRank(user1, statusMsg, season); + RankRedis userRank = RankRedis.from(user1.getId(), user1.getIntraId(), user1.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + String redisHashKey = RedisKeyManager.getHashKey(season.getId()); + rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); + statusMsg = "status message test2"; + testDataUtils.createUserRank(user2, statusMsg, season); + RankRedis userRank2 = RankRedis.from(user2.getId(), user2.getIntraId(), user2.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank2); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + @Test + void ppp_change_test() throws Exception { + String key = RedisKeyManager.getHashKey(game1.getSeason().getId()); + Integer user1BeforePpp = rankRedisRepository.findRankByUserId(key, user1.getId()) + .getPpp(); + System.out.println("Before ppp: " + user1BeforePpp); + assertThat(gameService.createRankResult(new RankResultReqDto(game1.getId(), team1.getId(), + 1, team2.getId(), 2), user1.getId())).isEqualTo(true); + Integer user1AfterPpp = rankRedisRepository.findRankByUserId(key, user1.getId()).getPpp(); + System.out.println("After ppp: " + rankRedisRepository.findRankByUserId(key, user1.getId()) + .getPpp()); + Rank rank = rankRepository.findByUserIdAndSeasonId(user1.getId(), game1.getSeason().getId()) + .orElseThrow(RankNotFoundException::new); + assertThat(rank.getPpp()).isEqualTo(user1AfterPpp); + assertThat(user1BeforePpp).isGreaterThan(user1AfterPpp); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameStatusServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameStatusServiceTest.java new file mode 100644 index 000000000..383b15f97 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/game/service/GameStatusServiceTest.java @@ -0,0 +1,112 @@ +package gg.pingpong.api.user.game.service; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.season.Season; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.repo.game.GameRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@RequiredArgsConstructor +@Transactional +public class GameStatusServiceTest { + @Autowired + private GameRepository gameRepository; + @Autowired + private SeasonRepository seasonRepository; + @Autowired + private GameStatusService gameStatusService; + @Autowired + private RankRedisRepository rankRedisRepository; + @Autowired + TestDataUtils testDataUtils; + @Autowired + private TeamRepository teamRepository; + @Autowired + private TeamUserRepository teamUserRepository; + @Autowired + private SlotManagementRepository slotManagementRepository; + private Season season; + User user1; + User user2; + Game game1; + Game liveGame; + + @BeforeEach + void init() { + season = seasonRepository.save( + new Season("test season", LocalDateTime.of(2023, 5, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), + 1000, 100)); + user1 = testDataUtils.createNewUser("test2", "test2@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + user2 = testDataUtils.createNewUser("test3", "test3@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), + now.getHour(), now.getMinute()); + game1 = gameRepository.save( + new Game(season, StatusType.BEFORE, Mode.RANK, startTime, startTime.plusMinutes(15))); + Team team1 = teamRepository.save(new Team(game1, 1, false)); + Team team2 = teamRepository.save(new Team(game1, 2, true)); + teamUserRepository.save(new TeamUser(team1, user1)); + teamUserRepository.save(new TeamUser(team2, user2)); + liveGame = gameRepository.save( + new Game(season, StatusType.LIVE, Mode.RANK, startTime.minusMinutes(15), startTime)); + } + + @AfterEach + public void flushRedis() { + rankRedisRepository.deleteAll(); + } + + @Test + void gameBeforeStatusChange() throws Exception { + System.out.println("g1.startTime: " + game1.getStartTime()); + System.out.println(game1.getStatus()); + gameStatusService.updateBeforeToLiveStatus(); + assertThat(game1.getStatus()).isEqualTo(StatusType.LIVE); + } + + @Test + void gameLiveStatusChange() throws Exception { + gameStatusService.updateLiveToWaitStatus(); + assertThat(liveGame.getStatus()).isEqualTo(StatusType.WAIT); + } + + @Test + void game5BeforeNoti() throws Exception { + SlotManagement slotManagement = SlotManagement.builder() + .futureSlotTime(12) + .pastSlotTime(0) + .openMinute(5) + .gameInterval(15) + .startTime(LocalDateTime.now().minusMinutes(1)) + .build(); + slotManagementRepository.save(slotManagement); + System.out.println("=============="); + gameStatusService.imminentGame(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemGiftControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemGiftControllerTest.java new file mode 100644 index 000000000..822070f34 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemGiftControllerTest.java @@ -0,0 +1,77 @@ +package gg.pingpong.api.user.item.controller; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.controller.request.ItemGiftRequestDto; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class ItemGiftControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Post]/pingpong/items/gift/{itemId} - success") + public void giftItemSuccessTest() throws Exception { + + // given + Long testItemId = 1L; + UserDto testUser = UserDto.builder() + .id(1L) + .intraId("testIntraId") + .build(); + + ItemGiftRequestDto requestDto = new ItemGiftRequestDto("recipientId"); + + doNothing().when(itemService).giftItem(testItemId, requestDto.getOwnerId(), testUser); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/gift/" + testItemId; + + // when + mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isCreated()); + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemPurchaseControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemPurchaseControllerTest.java new file mode 100644 index 000000000..c9f285c73 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemPurchaseControllerTest.java @@ -0,0 +1,71 @@ +package gg.pingpong.api.user.item.controller; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class ItemPurchaseControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Post]/pingpong/items/purchases/{itemId} - success") + public void purchaseItemSuccessTest() throws Exception { + + // given + Long testItemId = 1L; + UserDto testUser = UserDto.builder() + .id(1L) + .intraId("testIntraId") + .build(); + + doNothing().when(itemService).purchaseItem(testItemId, testUser); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/purchases/" + testItemId; + + // when + mockMvc.perform(post(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()); + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemStoreListControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemStoreListControllerTest.java new file mode 100644 index 000000000..48fc990f5 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/ItemStoreListControllerTest.java @@ -0,0 +1,107 @@ +package gg.pingpong.api.user.item.controller; + +import static gg.data.store.type.ItemType.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.Arrays; +import java.util.List; + +import javax.transaction.Transactional; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.controller.response.ItemStoreListResponseDto; +import gg.pingpong.api.user.store.controller.response.ItemStoreResponseDto; +import gg.pingpong.api.user.store.service.ItemService; +import gg.repo.store.ItemRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class ItemStoreListControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ItemRepository itemRepository; + + @MockBean + private ItemService itemService; + + @Test + @DisplayName("[Get]/pingpong/items/store") + public void getAllItemsTest() throws Exception { + + //given + List testItems = Arrays.asList( + new ItemStoreResponseDto(1L, "itemName 1", "mainContent 1", "subContent 1", MEGAPHONE, "ImageUrl 1", 1000, + 10, 900), + new ItemStoreResponseDto(2L, "itemName 2", "mainContent 2", "subContent 2", PROFILE_IMAGE, "ImageUrl 2", + 2000, 20, 1800), + new ItemStoreResponseDto(3L, "itemName 3", "mainContent 2", "subContent 2", TEXT_COLOR, "ImageUrl 3", 3000, + 30, 2700) + ); + ItemStoreListResponseDto testResponse = new ItemStoreListResponseDto(testItems); + when(itemService.getAllItems()).thenReturn(testResponse); + + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + System.out.println(userId); + String url = "/pingpong/items/store"; + + //when + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + //then + ItemStoreListResponseDto result = objectMapper.readValue(contentAsString, ItemStoreListResponseDto.class); + assertThat(result.getItemList()).isNotNull(); + assertThat(result.getItemList()).isNotEmpty(); + assertThat(result.getItemList()).hasSize(testItems.size()); + + for (int i = 0; i < result.getItemList().size(); i++) { + ItemStoreResponseDto actual = result.getItemList().get(i); + ItemStoreResponseDto expected = testItems.get(i); + + assertThat(actual.getItemId()).isEqualTo(expected.getItemId()); + assertThat(actual.getItemName()).isEqualTo(expected.getItemName()); + assertThat(actual.getMainContent()).isEqualTo(expected.getMainContent()); + assertThat(actual.getSubContent()).isEqualTo(expected.getSubContent()); + assertThat(actual.getItemType()).isEqualTo(expected.getItemType()); + assertThat(actual.getImageUri()).isEqualTo(expected.getImageUri()); + assertThat(actual.getOriginalPrice()).isEqualTo(expected.getOriginalPrice()); + assertThat(actual.getDiscount()).isEqualTo(expected.getDiscount()); + assertThat(actual.getSalePrice()).isEqualTo(expected.getSalePrice()); + } + + System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result)); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/UserItemResponseControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/UserItemResponseControllerTest.java new file mode 100644 index 000000000..3cedff4b8 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/controller/UserItemResponseControllerTest.java @@ -0,0 +1,52 @@ +package gg.pingpong.api.user.item.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.HttpHeaders; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.pingpong.api.user.store.service.ItemService; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +public class UserItemResponseControllerTest { + + @Autowired + ItemService itemService; + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + MockMvc mockMvc; + + @Test + @DisplayName("GET /pingpong/items?page=1&size=20") + public void getItemByUser() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + + Integer page = 1; + Integer size = 20; + + String url = "/pingpong/items?page=" + page + "&size=" + size; + + mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/service/ItemServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/service/ItemServiceUnitTest.java new file mode 100644 index 000000000..45aeb4b29 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/item/service/ItemServiceUnitTest.java @@ -0,0 +1,470 @@ +package gg.pingpong.api.user.item.service; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import gg.data.store.Item; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.store.service.UserCoinChangeService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.store.ItemRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.store.UserItemRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.item.ItemNotFoundException; +import gg.utils.exception.item.ItemNotPurchasableException; +import gg.utils.exception.item.ItemTypeException; +import gg.utils.exception.item.KakaoGiftException; +import gg.utils.exception.item.KakaoPurchaseException; +import gg.utils.exception.receipt.ItemStatusException; +import gg.utils.exception.receipt.ReceiptNotOwnerException; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class ItemServiceUnitTest { + @Mock + ItemRepository itemRepository; + @Mock + UserRepository userRepository; + @Mock + ReceiptRepository receiptRepository; + @Mock + NotiService notiService; + @Mock// ๋‚ด๋ถ€ ๋กœ์ง์—์„œ void ๊ฐ’ ๋ฐ˜ํ™˜์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ ์žˆ์Œ + UserCoinChangeService userCoinChangeService; + @Mock + UserItemRepository userItemRepository; + @InjectMocks + ItemService itemService; + + @Nested + @DisplayName("getAllItems method unitTest") + class GetAllItemsTest { + @Test + @DisplayName("success") + void success() { + // given + List items = new ArrayList<>(); + given(itemRepository.findAllByCreatedAtDesc()).willReturn(items); + // when, then + itemService.getAllItems(); + verify(itemRepository, times(1)).findAllByCreatedAtDesc(); + } + } + + @Nested + @DisplayName("purchaseItem method unitTest") + class PurchaseItemTest { + User payUser; + UserDto userDto; + Item item; + + @BeforeEach + void beforeEach() { + payUser = new User("", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + setFieldWithReflection(payUser, "id", 1L); + userDto = UserDto.from(payUser); + item = new Item(); + setFieldWithReflection(item, "isVisible", true); + } + + @Test + @DisplayName("success -> no discount") + void successNoDiscount() { + // given + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(receiptRepository.save(any(Receipt.class))).willReturn(mock(Receipt.class)); + // when, then 1 + itemService.purchaseItem(1L, userDto); + // when, then 2 + setFieldWithReflection(item, "discount", 0); + itemService.purchaseItem(1L, userDto); + verify(itemRepository, times(2)).findById(any(Long.class)); + verify(userRepository, times(2)).findById(any(Long.class)); + verify(userCoinChangeService, times(2)).purchaseItemCoin(any(), any(), any()); + verify(receiptRepository, times(2)).save(any(Receipt.class)); + + } + + @Test + @DisplayName("success -> discount") + void successDiscount() { + // given + setFieldWithReflection(item, "price", 100); + setFieldWithReflection(item, "discount", 10); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(receiptRepository.save(any(Receipt.class))).willReturn(mock(Receipt.class)); + // when, then + itemService.purchaseItem(1L, userDto); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(userCoinChangeService, times(1)).purchaseItemCoin(any(), any(), any()); + verify(receiptRepository, times(1)).save(any(Receipt.class)); + } + + @Test + @DisplayName("item not found") + void itemNotFound() { + // given + given(itemRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemService.purchaseItem(1L, userDto)) + .isInstanceOf(ItemNotFoundException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("Item Not Purchasable") + void itemNotPurchasable() { + // given + setFieldWithReflection(item, "isVisible", false); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + // when, then + assertThatThrownBy(() -> itemService.purchaseItem(1L, userDto)) + .isInstanceOf(ItemNotPurchasableException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("User Not Found") + void userNotFound() { + // given + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemService.purchaseItem(1L, userDto)) + .isInstanceOf(UserNotFoundException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("GuestUser Exception") + void guestUserException() { + // given + setFieldWithReflection(payUser, "roleType", RoleType.GUEST); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + // when, then + assertThatThrownBy(() -> itemService.purchaseItem(1L, userDto)) + .isInstanceOf(KakaoPurchaseException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + } + + } + + @Nested + @DisplayName("giftItemTest method unitTest") + class GiftItemTest { + User payUser; + User owner; + UserDto userDto; + Item item; + + @BeforeEach + void beforeEach() { + payUser = new User("", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + setFieldWithReflection(payUser, "id", 1L); + userDto = UserDto.from(payUser); + owner = new User("", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + item = new Item(); + setFieldWithReflection(item, "isVisible", true); + } + + @Test + @DisplayName("success -> No Discount") + void successNoDiscount() { + // given + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(receiptRepository.save(any(Receipt.class))).willReturn(mock(Receipt.class)); + given(userRepository.findByIntraId(any(String.class))).willReturn(Optional.of(owner)); + // when, then 1 + itemService.giftItem(1L, "owner", userDto); + // when, then 2 + setFieldWithReflection(item, "discount", 0); + itemService.giftItem(1L, "owner", userDto); + verify(itemRepository, times(2)).findById(any(Long.class)); + verify(userRepository, times(2)).findById(any(Long.class)); + verify(userRepository, times(2)).findByIntraId(any(String.class)); + verify(userCoinChangeService, times(2)).giftItemCoin(any(), any(), any(), any()); + verify(receiptRepository, times(2)).save(any(Receipt.class)); + verify(notiService, times(2)).createGiftNoti(any(), any(), any()); + + } + + @Test + @DisplayName("success -> Discount") + void successDiscount() { + // given + setFieldWithReflection(item, "price", 100); + setFieldWithReflection(item, "discount", 10); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(receiptRepository.save(any(Receipt.class))).willReturn(mock(Receipt.class)); + given(userRepository.findByIntraId(any(String.class))).willReturn(Optional.of(owner)); + // when, then + itemService.giftItem(1L, "owner", userDto); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findByIntraId(any(String.class)); + verify(userCoinChangeService, times(1)).giftItemCoin(any(), any(), any(), any()); + verify(receiptRepository, times(1)).save(any(Receipt.class)); + verify(notiService, times(1)).createGiftNoti(any(), any(), any()); + } + + @Test + @DisplayName("guest Owner") + void guestOwnerTest() { + // given + setFieldWithReflection(owner, "roleType", RoleType.GUEST); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(userRepository.findByIntraId(any(String.class))).willReturn(Optional.of(owner)); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(KakaoGiftException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findByIntraId(any(String.class)); + } + + @Test + @DisplayName("Owner not Found") + void ownerNotFoundTest() { + // given + setFieldWithReflection(owner, "roleType", RoleType.GUEST); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + given(userRepository.findByIntraId(any(String.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(UserNotFoundException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findByIntraId(any(String.class)); + } + + @Test + @DisplayName("guest payUser") + void guestPayUserTest() { + // given + setFieldWithReflection(payUser, "roleType", RoleType.GUEST); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(payUser)); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(KakaoPurchaseException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("payUser Not Found") + void payUserNotFoundTest() { + // given + setFieldWithReflection(payUser, "roleType", RoleType.GUEST); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(UserNotFoundException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + verify(userRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("Item Not Purchasable") + void itemNotPurchasableTest() { + // given + setFieldWithReflection(item, "isVisible", false); + given(itemRepository.findById(any(Long.class))).willReturn(Optional.of(item)); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(ItemNotPurchasableException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("Item Not Found") + void itemNotFoundTest() { + // given + given(itemRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> itemService.giftItem(1L, "owner", userDto)) + .isInstanceOf(ItemNotFoundException.class); + verify(itemRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("getItemByUser method unitTest") + class GetItemByUserTest { + @Test + @DisplayName("success") + void success() { + // given + User user = new User("intraId", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + given(userItemRepository.findByOwnerIntraId(any(String.class), any(Pageable.class))) + .willReturn(new PageImpl<>(new ArrayList<>())); + // when, then + itemService.getItemByUser(UserDto.from(user), mock(Pageable.class)); + verify(userItemRepository, times(1)).findByOwnerIntraId(any(String.class), any(Pageable.class)); + } + } + + @Nested + @DisplayName("checkItemOwner method unitTest") + class CheckItemOwnerTest { + User user; + Receipt receipt; + + @BeforeEach + void beforeEach() { + user = new User("intraId", "", "", RacketType.NONE, RoleType.USER, 0, SnsType.NONE, 1L); + receipt = new Receipt(); + setFieldWithReflection(receipt, "ownerIntraId", user.getIntraId()); + } + + @Test + @DisplayName("success") + void success() { + // given + // when, then + itemService.checkItemOwner(user, receipt); + } + + @Test + @DisplayName("Receipt Not Owner Exception") + void receiptNotOwnerTest() { + // given + setFieldWithReflection(receipt, "ownerIntraId", user.getIntraId() + "1234"); + // when, then + assertThatThrownBy(() -> itemService.checkItemOwner(user, receipt)) + .isInstanceOf(ReceiptNotOwnerException.class); + } + } + + @Nested + @DisplayName("checkItemType method unitTest") + class CheckItemTypeTest { + Receipt receipt; + + @BeforeEach + void beforeEach() { + receipt = new Receipt(); + Item item = new Item(); + setFieldWithReflection(item, "type", ItemType.MEGAPHONE); + setFieldWithReflection(receipt, "item", item); + } + + @Test + @DisplayName("success") + void success() { + // given + // when, then + itemService.checkItemType(receipt, receipt.getItem().getType()); + } + + @Test + @DisplayName("Receipt Not Owner Exception") + void receiptNotOwnerTest() { + // given + // when, then + assertThatThrownBy(() -> itemService.checkItemType(receipt, ItemType.EDGE)) + .isInstanceOf(ItemTypeException.class); + } + } + + @Nested + @DisplayName("checkItemStatus method unitTest") + class CheckItemStatusTest { + Receipt receipt; + + @BeforeEach + void beforeEach() { + receipt = new Receipt(); + Item item = new Item(); + setFieldWithReflection(item, "type", ItemType.MEGAPHONE); + setFieldWithReflection(receipt, "status", ItemStatus.BEFORE); + setFieldWithReflection(receipt, "item", item); + } + + @Test + @DisplayName("success Megaphone1") + void successMegaphone1() { + // given + setFieldWithReflection(receipt, "status", ItemStatus.USING); + // when, then + itemService.checkItemStatus(receipt); + } + + @Test + @DisplayName("success Megaphone2") + void successMegaphone2() { + // given + setFieldWithReflection(receipt, "status", ItemStatus.WAITING); + // when, then + itemService.checkItemStatus(receipt); + } + + @Test + @DisplayName("success Megaphone") + void successNotMegaphone() { + // given + setFieldWithReflection(receipt.getItem(), "type", ItemType.EDGE); + // when, then + itemService.checkItemStatus(receipt); + } + + @Test + @DisplayName("Receipt Not Owner Exception") + void failMegaphone() { + // given + // when, then + assertThatThrownBy(() -> itemService.checkItemStatus(receipt)) + .isInstanceOf(ItemStatusException.class); + } + + @Test + @DisplayName("Receipt Not Owner Exception") + void failNotMegaphone() { + // given + setFieldWithReflection(receipt.getItem(), "type", ItemType.EDGE); + setFieldWithReflection(receipt, "status", ItemStatus.USING); + // when, then + assertThatThrownBy(() -> itemService.checkItemStatus(receipt)) + .isInstanceOf(ItemStatusException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/dto/MatchStatusDtoUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/dto/MatchStatusDtoUnitTest.java new file mode 100644 index 000000000..b0e726e53 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/dto/MatchStatusDtoUnitTest.java @@ -0,0 +1,98 @@ +package gg.pingpong.api.user.match.dto; + +import static org.mockito.Mockito.*; + +import java.time.LocalDateTime; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.manage.SlotManagement; +import gg.utils.annotation.UnitTest; + +@UnitTest +class MatchStatusDtoUnitTest { + + @Nested + @DisplayName("MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement)") + class MatchStatusDtoConstructor { + Game tournamentGame; + Game rankGame; + Game normalGame; + SlotManagement slotManagement; + String userIntraId = "myId"; + String enemyIntraId = "enemyId"; + LocalDateTime time = LocalDateTime.now(); + + @BeforeEach + void setup() { + tournamentGame = mock(Game.class); + rankGame = mock(Game.class); + normalGame = mock(Game.class); + slotManagement = mock(SlotManagement.class); + when(slotManagement.getOpenMinute()).thenReturn(5); + } + + @ParameterizedTest + @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ์ธ ๊ฒฝ์šฐ ํ•ญ์ƒ Imminent") + @ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + void ifGameTypeTournamentAlwaysImminent(int arg) { + //Arrange + when(tournamentGame.getMode()).thenReturn(Mode.TOURNAMENT); + when(tournamentGame.getStartTime()).thenReturn(time.plusMinutes(arg)); + + //Act + MatchStatusDto dto = new MatchStatusDto(tournamentGame, userIntraId, enemyIntraId, slotManagement); + + //Assert + Assertions.assertThat(dto.getIsImminent()).isEqualTo(true); + } + + @ParameterizedTest + @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์‹œ๊ฐ„์— ๋”ฐ๋ผ NotImminent") + @ValueSource(ints = {6, 7, 8, 9, 10}) + void rankAndNormalGameNotImminent(int arg) { + //Arrange + when(rankGame.getMode()).thenReturn(Mode.RANK); + when(normalGame.getMode()).thenReturn(Mode.RANK); + when(rankGame.getStartTime()).thenReturn(time.plusMinutes(arg)); + when(normalGame.getStartTime()).thenReturn(time.plusMinutes(arg)); + + //Act + MatchStatusDto rankDto = new MatchStatusDto(rankGame, userIntraId, enemyIntraId, slotManagement); + MatchStatusDto normalDto = new MatchStatusDto(normalGame, userIntraId, enemyIntraId, slotManagement); + + //Assert + Assertions.assertThat(rankDto.getIsImminent()) + .isEqualTo(normalDto.getIsImminent()) + .isEqualTo(false); + } + + @ParameterizedTest + @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์‹œ๊ฐ„์— ๋”ฐ๋ผ Imminent") + @ValueSource(ints = {0, 1, 2, 3, 4, 5}) + void rankAndNormalGameImminent(int arg) { + //Arrange + when(rankGame.getMode()).thenReturn(Mode.RANK); + when(normalGame.getMode()).thenReturn(Mode.RANK); + when(rankGame.getStartTime()).thenReturn(time.plusMinutes(arg)); + when(normalGame.getStartTime()).thenReturn(time.plusMinutes(arg)); + + //Act + MatchStatusDto rankDto = new MatchStatusDto(rankGame, userIntraId, enemyIntraId, slotManagement); + MatchStatusDto normalDto = new MatchStatusDto(normalGame, userIntraId, enemyIntraId, slotManagement); + + //Assert + Assertions.assertThat(rankDto.getIsImminent()) + .isEqualTo(normalDto.getIsImminent()) + .isEqualTo(true); + } + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchBothServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchBothServiceTest.java new file mode 100644 index 000000000..6cac860e4 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchBothServiceTest.java @@ -0,0 +1,149 @@ +package gg.pingpong.api.user.match.service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.PenaltyAdminRepository; +import gg.data.game.Game; +import gg.data.manage.SlotManagement; +import gg.data.manage.type.PenaltyKey; +import gg.data.match.type.Option; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.manage.redis.PenaltyUserRedisRepository; +import gg.pingpong.api.user.match.utils.MatchIntegrationTestUtils; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.match.RedisMatchTimeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.noti.NotiRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.match.SlotNotFoundException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@Transactional +@AutoConfigureMockMvc +@RequiredArgsConstructor +class MatchBothServiceTest { + @Autowired + MatchFindService matchFindService; + @Autowired + MatchService matchService; + @Autowired + RedisMatchTimeRepository redisMatchTimeRepository; + @Autowired + RedisMatchUserRepository redisMatchUserRepository; + @Autowired + RedisConnectionFactory redisConnectionFactory; + @Autowired + RedisTemplate redisTemplate; + @Autowired + MatchIntegrationTestUtils matchTestSetting; + @Autowired + GameRepository gameRepository; + @Autowired + RankRedisRepository rankRedisRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + PenaltyAdminRepository penaltyAdminRepository; + @Autowired + PenaltyUserRedisRepository penaltyUserRedisRepository; + @Autowired + SlotManagementRepository slotManagementRepository; + @Autowired + TestDataUtils testDataUtils; + List users; + List slotTimes; + + Season testSeason; + + @BeforeEach + void init() { + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + Random random = new Random(); + Integer userCount = random.nextInt(10) + 5; + Integer pppGap = random.nextInt(100) + 50; + Season season = matchTestSetting.makeTestSeason(pppGap); + this.testSeason = season; + List users = new ArrayList(); + for (int i = 0; i < userCount; i++) { + User user = matchTestSetting.createUser(); + users.add(user); + } + this.users = users; + users.stream().forEach(user -> + matchTestSetting.addUsertoRankRedis(user.getId(), 1000, season.getId())); + SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); + List slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); + this.slotTimes = slotTimes; + } + + @AfterEach + void clear() { + RedisConnection connection = redisConnectionFactory.getConnection(); + connection.flushDb(); + connection.close(); + } + + @DisplayName("both ๋งค์นญ ์‹œ๋ฎฌ๋ ˆ์ด์…˜") + @Test + void makeGameWithNormalAndBoth() { + System.out.println("this.users = " + this.users); + // ์œ ์ € 0 slot 2, 3, 0 ๋“ฑ๋ก ์œ ์ € 1 slot 2 + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); + + System.out.println("matchFindService.getAllMatchStatus(users.get(0).getId(), Option.BOTH) = " + + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.BOTH).getMatchBoards().get(0)); + System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); + System.out.println( + "matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch( + UserDto.from(users.get(1)))); + System.out.println("matchFindService.getAllMatchStatus(users.get(1).getId(), Option.BOTH) = " + + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), Option.BOTH)); + Optional game1 = gameRepository.findByStartTime(slotTimes.get(2)); + Assertions.assertThat(game1).isPresent(); + matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(2)); + System.out.println( + "matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch( + UserDto.from(users.get(1)))); + redisTemplate.delete(PenaltyKey.USER_ADMIN + users.get(0).getIntraId()); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(2)); + System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); + } + + @DisplayName("๋งค์นญ ๊ฒฝ๊ธฐ ์ƒ๋Œ€๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์œ ์ €์˜ ๋งค์นญ ๊ฒฝ๊ธฐ ์ทจ์†Œ") + @Test + void cancelByNotMatchedUser() { + System.out.println("this.users = " + this.users); + // ์œ ์ € 0 slot 2, 3, 0 ๋“ฑ๋ก ์œ ์ € 1 slot 2 + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); + org.junit.jupiter.api.Assertions.assertThrows(SlotNotFoundException.class, () -> { + matchService.cancelMatch(UserDto.from(users.get(2)), this.slotTimes.get(2)); + }); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchFindServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchFindServiceUnitTest.java new file mode 100644 index 000000000..e84103f51 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchFindServiceUnitTest.java @@ -0,0 +1,255 @@ +package gg.pingpong.api.user.match.service; + +import static gg.pingpong.api.user.match.utils.GameTestUtils.*; +import static gg.pingpong.api.user.match.utils.UserTestUtils.*; +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.game.Game; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.match.RedisMatchTime; +import gg.data.match.type.Option; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.match.utils.SlotGenerator; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.match.RedisMatchTimeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +public class MatchFindServiceUnitTest { + @InjectMocks + MatchFindService matchFindService; + @Mock + private SlotManagementRepository slotManagementRepository; + @Mock + private GameRepository gameRepository; + @Mock + private UserRepository userRepository; + @Mock + private RedisMatchUserRepository redisMatchUserRepository; + @Mock + private SeasonFindService seasonFindService; + @Mock + private RankRedisRepository rankRedisRepository; + @Mock + private RedisMatchTimeRepository redisMatchTimeRepository; + @Mock + private TierRepository tierRepository; + + private static final SlotManagement slotManagement = SlotManagement.builder() + .pastSlotTime(0) + .futureSlotTime(12) + .openMinute(5) + .gameInterval(15) + .startTime(LocalDateTime.now()) + .build(); + private static final Season season = Season.builder().startTime(LocalDateTime.now()).startPpp(123).build(); + private static final Tier tier = new Tier(); + + @BeforeEach + public void init() { + setFieldWithReflection(slotManagement, "id", 1L); + setFieldWithReflection(season, "id", 1L); + setFieldWithReflection(tier, "id", 1L); + } + + @Nested + @DisplayName("ํ˜„์žฌ ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ") + class GetCurrentMatch { + private final User user = createUser(); + + @BeforeEach + public void init() { + setFieldWithReflection(user, "id", 1L); + } + + @Test + @DisplayName("๋“ฑ๋กํ•œ ์Šฌ๋กฏ(์ตœ๋Œ€ 3๊ฐœ) ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.") + void successUnmatchedSlots() { + // given + UserDto userDto = UserDto.from(user); + LocalDateTime startTime = LocalDateTime.of(2024, 1, 1, 0, 0); + RedisMatchTime redisMatchTime = new RedisMatchTime(startTime, Option.BOTH); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(slotManagement)); + given(gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, user.getId())).willReturn( + Optional.empty()); + given(redisMatchUserRepository.getAllMatchTime(user.getId())).willReturn(Set.of(redisMatchTime)); + + // when + matchFindService.getCurrentMatch(userDto); + + // then + verify(slotManagementRepository, times(1)).findCurrent(any(LocalDateTime.class)); + verify(gameRepository, times(1)).findByStatusTypeAndUserId(StatusType.BEFORE, user.getId()); + verify(redisMatchUserRepository, times(1)).getAllMatchTime(user.getId()); + } + + @Test + @DisplayName("๋งค์นญ๋œ ์Šฌ๋กฏ(1๊ฐœ) ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.") + void successMatchedSlot() { + // given + UserDto userDto = UserDto.from(user); + User enemy = createUser(); + Game myGame = createNormalGame(user, enemy, season); + setFieldWithReflection(enemy, "id", 2L); + setFieldWithReflection(myGame, "id", 1L); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(slotManagement)); + given(gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, user.getId())).willReturn( + Optional.of(myGame)); + given(userRepository.findEnemyByGameAndUser(myGame.getId(), user.getId())).willReturn(List.of(enemy)); + + // when + matchFindService.getCurrentMatch(userDto); + + // then + verify(slotManagementRepository, times(1)).findCurrent(any(LocalDateTime.class)); + verify(gameRepository, times(1)).findByStatusTypeAndUserId(StatusType.BEFORE, user.getId()); + verify(userRepository, times(1)).findEnemyByGameAndUser(myGame.getId(), user.getId()); + } + + } + + @Nested + @DisplayName("๊ฒฝ๊ธฐ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ์กฐํšŒ") + class GetAllMatchStatus { + private final User user = createUser(); + private SlotGenerator slotGenerator; + + @BeforeEach + void init() { + setFieldWithReflection(user, "id", 1L); + given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn( + Optional.of(slotManagement)); + given(seasonFindService.findCurrentSeason(any(LocalDateTime.class))).willReturn(season); + given(tierRepository.findStartTier()).willReturn(Optional.of(tier)); + List games = List.of(); // TODO ์ˆ˜์ •? ๋˜๋Š” slogGenerator์—์„œ ๊ฒ€์ฆ? + given(gameRepository.findAllBetween(any(LocalDateTime.class), any(LocalDateTime.class))).willReturn(games); + } + + @AfterEach + void verifyEach() { + verify(slotManagementRepository, times(1)).findCurrent(any(LocalDateTime.class)); + verify(seasonFindService, times(1)).findCurrentSeason(any(LocalDateTime.class)); + verify(tierRepository, times(1)).findStartTier(); + verify(gameRepository, times(1)).findAllBetween(any(LocalDateTime.class), any(LocalDateTime.class)); + } + + @Test + @DisplayName("์Šฌ๋กฏ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ์—†๋Š” ๊ฒฝ์šฐ") + void success() { + // given + UserDto userDto = UserDto.from(user); + RankRedis redisUser = RankRedis.from(userDto.getId(), userDto.getIntraId(), userDto.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + slotGenerator = new SlotGenerator(redisUser, slotManagement, season, Option.BOTH); + given(rankRedisRepository.findRankByUserId(hashKey, user.getId())).willReturn( + redisUser); // guest๊ฐ€ ์•„๋‹Œ ์œ ์ €์ผ ๊ฒฝ์šฐ + given(gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(user).getId())).willReturn( + Optional.empty()); + given(redisMatchTimeRepository.getAllEnrolledStartTimes()).willReturn(Set.of(LocalDateTime.now())); + given(redisMatchUserRepository.getAllMatchTime(slotGenerator.getMatchUser().getUserId())).willReturn( + Set.of()); + given(redisMatchTimeRepository.getAllMatchUsers(any(LocalDateTime.class))).willReturn( + List.of()); // TODO ์ˆ˜์ • + + // when + matchFindService.getAllMatchStatus(userDto, Option.BOTH); + + // then + verify(rankRedisRepository, times(1)).findRankByUserId(hashKey, user.getId()); + verify(gameRepository, times(1)).findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(user).getId()); + verify(redisMatchTimeRepository, times(1)).getAllEnrolledStartTimes(); + verify(redisMatchUserRepository, times(1)).getAllMatchTime(slotGenerator.getMatchUser().getUserId()); + verify(redisMatchTimeRepository, times(1)).getAllMatchUsers(any(LocalDateTime.class)); + + // TODO slotGenerator ๊ฒ€์ฆ (response dto) + } + + @Test + @DisplayName("GUEST ์œ ์ €๊ฐ€ ์Šฌ๋กฏ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ ์—†๋Š” ๊ฒฝ์šฐ") + void successGuest() { + // given + User guest = createGuestUser(); + RankRedis redisUser = RankRedis.from(guest.getId(), guest.getIntraId(), guest.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + slotGenerator = new SlotGenerator(redisUser, slotManagement, season, Option.BOTH); + given(gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(guest).getId())).willReturn( + Optional.empty()); + given(redisMatchTimeRepository.getAllEnrolledStartTimes()).willReturn(Set.of(LocalDateTime.now())); + given(redisMatchUserRepository.getAllMatchTime(slotGenerator.getMatchUser().getUserId())).willReturn( + Set.of()); + given(redisMatchTimeRepository.getAllMatchUsers(any(LocalDateTime.class))).willReturn( + List.of()); // TODO ์ˆ˜์ • + + // when + matchFindService.getAllMatchStatus(UserDto.from(guest), Option.BOTH); + + // then + verify(gameRepository, times(1)).findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(guest).getId()); + verify(redisMatchTimeRepository, times(1)).getAllEnrolledStartTimes(); + verify(redisMatchUserRepository, times(1)).getAllMatchTime(slotGenerator.getMatchUser().getUserId()); + verify(redisMatchTimeRepository, times(1)).getAllMatchUsers(any(LocalDateTime.class)); + } + + @Test + @DisplayName("์Šฌ๋กฏ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ์žˆ๋Š” ๊ฒฝ์šฐ") + void successWithMySlot() { + // given + UserDto userDto = UserDto.from(user); + RankRedis redisUser = RankRedis.from(userDto.getId(), userDto.getIntraId(), userDto.getTextColor(), + season.getStartPpp(), tier.getImageUri()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + User enemy = createUser(); + Game game = createNormalGame(user, enemy, season); + setFieldWithReflection(enemy, "id", 2L); + setFieldWithReflection(game, "id", 1L); + given(rankRedisRepository.findRankByUserId(hashKey, user.getId())).willReturn(redisUser); + given(gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(user).getId())).willReturn( + Optional.of(game)); + given(redisMatchTimeRepository.getAllEnrolledStartTimes()).willReturn(Set.of(LocalDateTime.now())); + given(redisMatchTimeRepository.getAllMatchUsers(any(LocalDateTime.class))).willReturn( + List.of()); // TODO ์ˆ˜์ • + + // when + matchFindService.getAllMatchStatus(userDto, Option.BOTH); + + // then + verify(rankRedisRepository, times(1)).findRankByUserId(hashKey, user.getId()); + verify(gameRepository, times(1)).findByStatusTypeAndUserId(StatusType.BEFORE, UserDto.from(user).getId()); + verify(redisMatchTimeRepository, times(1)).getAllEnrolledStartTimes(); + verify(redisMatchTimeRepository, times(1)).getAllMatchUsers(any(LocalDateTime.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchServiceTest.java new file mode 100644 index 000000000..e40f7f2dc --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchServiceTest.java @@ -0,0 +1,556 @@ +package gg.pingpong.api.user.match.service; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.transaction.annotation.Transactional; + +import gg.admin.repo.manage.PenaltyAdminRepository; +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.manage.SlotManagement; +import gg.data.manage.redis.RedisPenaltyUser; +import gg.data.match.RedisMatchUser; +import gg.data.match.type.MatchKey; +import gg.data.match.type.Option; +import gg.data.match.type.SlotStatus; +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.pingpong.api.user.manage.redis.PenaltyUserRedisRepository; +import gg.pingpong.api.user.match.controller.response.MatchStatusResponseListDto; +import gg.pingpong.api.user.match.controller.response.SlotStatusResponseListDto; +import gg.pingpong.api.user.match.dto.MatchStatusDto; +import gg.pingpong.api.user.match.dto.SlotStatusDto; +import gg.pingpong.api.user.match.utils.MatchIntegrationTestUtils; +import gg.pingpong.api.user.rank.redis.RedisUploadService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.match.RedisMatchTimeRepository; +import gg.repo.match.RedisMatchUserRepository; +import gg.repo.noti.NotiRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.custom.BusinessException; +import gg.utils.exception.match.EnrolledSlotException; +import gg.utils.exception.match.PenaltyUserSlotException; +import gg.utils.exception.tournament.TournamentConflictException; +import lombok.RequiredArgsConstructor; + +@IntegrationTest +@Transactional +@RequiredArgsConstructor +class MatchServiceTest { + @Autowired + MatchFindService matchFindService; + @Autowired + MatchService matchService; + @Autowired + RedisMatchTimeRepository redisMatchTimeRepository; + @Autowired + RedisMatchUserRepository redisMatchUserRepository; + @Autowired + RedisConnectionFactory redisConnectionFactory; + @Autowired + RedisTemplate redisTemplate; + @Autowired + MatchIntegrationTestUtils matchTestSetting; + @Autowired + GameRepository gameRepository; + @Autowired + RankRedisRepository rankRedisRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + PenaltyAdminRepository penaltyRepository; + @Autowired + PenaltyUserRedisRepository penaltyUserRedisRepository; + @Autowired + TournamentRepository tournamentRepository; + @Autowired + SlotManagementRepository slotManagementRepository; + @Autowired + TierRepository tierRepository; + @Autowired + RedisUploadService redisUploadService; + @Autowired + TestDataUtils testDataUtils; + List users; + List slotTimes; + + Season testSeason; + + @BeforeEach + void init() { + testDataUtils.createTierSystem("pingpong"); + Random random = new Random(); + Integer userCount = random.nextInt(10) + 5; + Integer pppGap = random.nextInt(100) + 50; + Season season = matchTestSetting.makeTestSeason(pppGap); + testSeason = season; + users = new ArrayList(); + for (int i = 0; i < userCount; i++) { + User user = matchTestSetting.createUser(); + users.add(user); + } + users.stream().forEach(user -> + matchTestSetting.addUsertoRankRedis(user.getId(), random.nextInt(season.getPppGap()), season.getId())); + SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); + slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); + } + + @AfterEach + void clear() { + RedisConnection connection = redisConnectionFactory.getConnection(); + connection.flushDb(); + connection.close(); + } + + @Nested + @DisplayName("๋งค์นญ ์š”์ฒญ API ํ…Œ์ŠคํŠธ") + class MatchTest { + @DisplayName("๋งค์นญ ๊ฐ€๋Šฅ ์ƒ๋Œ€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ์— ๋“ค์–ด๊ฐ") + @Test + void addMatchDifferentOption() { + System.out.println("users = " + users); + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(0)); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + Assertions.assertThat(size).isEqualTo(2L); + } + + @DisplayName("normal both ๋งค์นญ ์‹œ ๊ฒŒ์ž„ ์ƒ์„ฑ") + @Test + void makeGameWithNormalAndBoth() { + System.out.println("users = " + users); + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.BOTH, slotTimes.get(1)); + matchService.makeMatch(UserDto.from(users.get(3)), Option.NORMAL, slotTimes.get(1)); + Optional game1 = gameRepository.findByStartTime(slotTimes.get(0)); + Optional game2 = gameRepository.findByStartTime(slotTimes.get(1)); + Assertions.assertThat(game1).isPresent(); + Assertions.assertThat(game2).isPresent(); + System.out.println( + "normal user + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), + Option.NORMAL)); + System.out.println(); + System.out.println( + "normal user both + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), + Option.BOTH)); + System.out.println( + "both user + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), + Option.BOTH)); + System.out.println( + "both user normal matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), + Option.NORMAL)); + } + + @DisplayName("Queue์— ๋งค์นญ ๊ฐ€๋Šฅํ•œ normal ์ƒ๋Œ€๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„ ์ƒ์„ฑ") + @Test + void addMatchSameNormalOption() { + matchService.makeMatch(UserDto.from(users.get(2)), Option.RANK, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(0)); + matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(0)); + Optional game = gameRepository.findByStartTime(slotTimes.get(0)); + Assertions.assertThat(game).isEmpty(); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(slotTimes.get(0)); + Assertions.assertThat(size).isEqualTo(2L); + RedisMatchUser remainedUser = (RedisMatchUser)redisTemplate.opsForList() + .index(MatchKey.getTime(slotTimes.get(0)), 0); + Assertions.assertThat(remainedUser.getUserId()).isEqualTo(users.get(2).getId()); + Assertions.assertThat(notiRepository.findAllByUser(users.get(1)).size()).isEqualTo(2); + Assertions.assertThat(notiRepository.findAllByUser(users.get(0)).size()).isEqualTo(1); + Assertions.assertThat(notiRepository.findAllByUser(users.get(2)).size()).isEqualTo(0); + } + + @DisplayName("๊ฒŒ์ž„ ์žฌ์ƒ์„ฑ ํ…Œ์ŠคํŠธ") + @Test + void remakeGameAfterCancelling() { + matchService.makeMatch(UserDto.from(users.get(2)), Option.RANK, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, slotTimes.get(0)); + matchService.cancelMatch(UserDto.from(users.get(2)), slotTimes.get(0)); + Optional game = gameRepository.findByStartTime(slotTimes.get(0)); + Assertions.assertThat(game).isPresent(); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + Assertions.assertThat(size).isEqualTo(2L); + RedisMatchUser remainedUser = (RedisMatchUser)redisTemplate.opsForList() + .index(MatchKey.getTime(slotTimes.get(0)), 0); + Assertions.assertThat(remainedUser.getUserId()).isEqualTo(users.get(0).getId()); + Assertions.assertThat(notiRepository.findAllByUser(users.get(1)).size()).isEqualTo(1); + Assertions.assertThat(notiRepository.findAllByUser(users.get(0)).size()).isEqualTo(1); + Assertions.assertThat(notiRepository.findAllByUser(users.get(2)).size()).isEqualTo(1); + } + + @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ random option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์—†์„ ๊ฒฝ์šฐ") + @Test + void addMatchRankOptionAndPppGapBiggerThanSeasonPppGap() { + User user1 = matchTestSetting.createUser(); + matchTestSetting.addUsertoRankRedis(user1.getId(), + testSeason.getStartPpp() + testSeason.getPppGap() + 1, testSeason.getId()); //pppGap์ฐจ์ด๊ฐ€ ์ถฉ๋ถ„ํžˆ ํฐ ๊ฒฝ์šฐ + matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(0)); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + Assertions.assertThat(size).isEqualTo(3L); + Optional game = gameRepository.findByStartTime(slotTimes.get(0)); + Assertions.assertThat(game.isEmpty()).isEqualTo(true); + + } + + @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ random option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ") + @Test + void addMatchRankOptionAndPppGapSamllerThanOrEqualToSeasonPppGap() { + RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager + .getHashKey(testSeason.getId()), users.get(0).getId()); + User user1 = matchTestSetting.createUser(); + matchTestSetting.addUsertoRankRedis(user1.getId(), userRank.getPpp() + testSeason.getPppGap(), + testSeason.getId()); //pppGap์ฐจ์ด๊ฐ€ pppGap๋งŒํผ + matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(0)); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + // ํ˜„์žฌ ์‹œ์Šคํ…œ ์ฝ”๋“œ์—์„œ๋Š” ๋งค์นญ๋œ ์Šฌ๋กฏ์€ ์•ˆ์ง€์šฐ๊ณ  ์žˆ์Œ, ๋งค์นญ๋˜์ง€ ์•Š์€ ์Šฌ๋กฏ๋งŒ ์‚ญ์ œ์ค‘์ด๋ฏ€๋กœ 2๊ฐ€ ๋‚˜์˜ด + Assertions.assertThat(size).isEqualTo(2L); + Optional game = gameRepository.findByStartTime(slotTimes.get(0)); + Assertions.assertThat(game.isEmpty()).isEqualTo(false); + } + + @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ both option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ") + @Test + void addMatchBothOptionAndPppGapSmallerThanOrEqualToSeasonPppGap() { + RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager + .getHashKey(testSeason.getId()), users.get(0).getId()); + User user1 = matchTestSetting.createUser(); + matchTestSetting.addUsertoRankRedis(user1.getId(), userRank.getPpp() + testSeason.getPppGap(), + testSeason.getId()); //pppGap์ฐจ์ด๊ฐ€ pppGap๋งŒํผ + matchService.makeMatch(UserDto.from(user1), Option.BOTH, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(0)); + Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); + // ํ˜„์žฌ ์‹œ์Šคํ…œ ์ฝ”๋“œ์—์„œ๋Š” ๋งค์นญ๋œ ์Šฌ๋กฏ์€ ์•ˆ์ง€์šฐ๊ณ  ์žˆ์Œ, ๋งค์นญ๋˜์ง€ ์•Š์€ ์Šฌ๋กฏ๋งŒ ์‚ญ์ œ์ค‘์ด๋ฏ€๋กœ 2๊ฐ€ ๋‚˜์˜ด + Assertions.assertThat(size).isEqualTo(2L); + Optional game = gameRepository.findByStartTime(slotTimes.get(0)); + Assertions.assertThat(game.isEmpty()).isEqualTo(false); + Assertions.assertThat(game.get().getMode()).isEqualTo(Mode.RANK); + } + + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„๊ณผ ๊ฒน์น  ๊ฒฝ์šฐ ๊ฒŒ์ž„ ์ƒ์„ฑ ์•ˆ๋จ") + @Test + void addMatchTournamentTime() { + // given + Tournament tournament = Tournament.builder() + .title("test tournament") + .contents("test contents") + .startTime(LocalDateTime.now().plusHours(1)) + .endTime(LocalDateTime.now().plusHours(2)) + .type(TournamentType.MASTER) + .status(TournamentStatus.BEFORE) + .build(); + tournamentRepository.save(tournament); + + // when, then + Assertions.assertThatThrownBy( + () -> matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, tournament.getStartTime())) + .isInstanceOf(TournamentConflictException.class); + + } + } + + @Nested + @DisplayName("๋งค์นญ ์ทจ์†Œ API ํ…Œ์ŠคํŠธ") + class CancelMatch { + @DisplayName("๊ฒŒ์ž„ ์ƒ์„ฑ๋˜์—ˆ์„ ๋•Œ ๊ฒฝ๊ธฐ ์ทจ์†Œ") + @Test + void cancelMatchAfterMakingGameEntity() { + //normal ๊ฒŒ์ž„ ์ƒ์„ฑ + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); + //user2 ๋‹ค๋ฅธ ์Šฌ๋กฏ ๋“ฑ๋ก + //์ฒซ๋ฒˆ์งธ ์œ ์ € ๊ฒฝ๊ธฐ ์ทจ์†Œ + assertThrows( + EnrolledSlotException.class, + () -> matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)) + ); + matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(3)); + Optional game = gameRepository.findByStartTime(slotTimes.get(3)); + Assertions.assertThat(game.isEmpty()).isEqualTo(true); + // ์ทจ์†Œํ•œ ์œ ์ €๋Š” ํ์— ์—†์Œ + Assertions.assertThat(redisMatchUserRepository.countMatchTime(users.get(0).getId())).isEqualTo(0L); + // ์ทจ์†Œํ•˜์ง€ ์•Š์€ ์œ ์ €๋Š” ํ์— ์œ ์ง€ + Assertions.assertThat(redisMatchUserRepository.countMatchTime(users.get(1).getId())).isEqualTo(1L); + + //์•Œ๋žŒ ํ™•์ธ + List notifications = notiRepository.findAllByUser(users.get(1)); + System.out.println("users.get(0).getIntraId() = " + users.get(0).getIntraId()); + for (Noti noti : notifications) { + System.out.println("noti.getMessage() = " + noti.getMessage()); + } + Assertions.assertThat(notifications.size()).isEqualTo(2); + Assertions.assertThat(notifications.get(0).getType()).isEqualTo(NotiType.MATCHED); + Assertions.assertThat(notifications.get(1).getType()).isEqualTo(NotiType.CANCELEDBYMAN); + + //ํŒจ๋„ํ‹ฐ ํ™•์ธ + Optional penaltyUser = penaltyUserRedisRepository.findByIntraId( + users.get(0).getIntraId()); + Assertions.assertThat(penaltyUser).isPresent(); + // ํŒจ๋„ํ‹ฐ ์‹œ๊ฐ„์€ ํ•˜๋“œ ์ฝ”๋”ฉ ์‹œ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์šฐ๋‹ˆ Static์ด๋‚˜ enum์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š”๊ฒŒ ์ข‹์„ ๋“ฏ ํ•˜๋‹ค. + assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(30); + assertThrows(PenaltyUserSlotException.class, () -> { + matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(10)); + }); + } + + @DisplayName("๊ฒŒ์ž„ ์ƒ์„ฑ ์ „ ๊ฒฝ๊ธฐ ์ทจ์†Œ") + @Test + void cancelBeforeMakingGameEntity() { + RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager + .getHashKey(testSeason.getId()), users.get(0).getId()); + User user1 = matchTestSetting.createUser(); + matchTestSetting.addUsertoRankRedis(user1.getId(), userRank.getPpp() + testSeason.getPppGap() + 100, + testSeason.getId()); + //๋งค์นญ์ด ์ด๋ฃจ์–ด์งˆ ์ˆ˜ ์—†๋Š” ์œ ์ € 3๋ช…์„ ํ์— ๋“ฑ๋ก + matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); + //user1์˜ ์ทจ์†Œ + matchService.cancelMatch(UserDto.from(users.get(1)), slotTimes.get(0)); + List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(slotTimes.get(0)); + Assertions.assertThat(allMatchUsers.size()).isEqualTo(2L); + + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ทจ์†Œ ํ…Œ์ŠคํŠธ") + void cancelMatchedTournamentGame() { + // given + LocalDateTime time = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).withNano(0); + Game game = testDataUtils.createMockMatch(users.get(0), testSeason, time, time.withMinute(15), + Mode.TOURNAMENT); + // when, then + Assertions.assertThatThrownBy( + () -> matchService.cancelMatch(UserDto.from(users.get(0)), game.getStartTime())) + .isInstanceOf(BusinessException.class); + } + } + + @Nested + @DisplayName("ํŠน์ • ์‹œ๊ฐ„๋Œ€์˜ ๊ฒฝ๊ธฐ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ์กฐํšŒ API ํ…Œ์ŠคํŠธ") + class GetMatchTimeScope { + @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ์ƒ์„ฑํ•œ ํ›„ ๋‚ด ํ…Œ์ด๋ธ”๋กœ ์ธ์‹") + @Test + void readMyTableAfterMakingGame() { + //normal ๊ฒŒ์ž„ ์ƒ์„ฑ + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); + matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(4)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(1)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(2)); + SlotStatusResponseListDto slotStatusList = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), + Option.NORMAL); + for (int i = 0; i < 3; i++) { + System.out.println("slotTimes = " + String.valueOf(i) + slotTimes.get(i)); + } + for (List dtos : slotStatusList.getMatchBoards()) { + for (SlotStatusDto dto : dtos) { + System.out.println("dto = " + dto); + if (dto.getStartTime().equals(slotTimes.get(0))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(1))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.OPEN.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(2))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MATCH.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(4))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); + } + } + } + + } + + @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ์ƒ์„ฑ ์ „ ๋‚ด ํ…Œ์ด๋ธ”๋กœ ์ธ์‹") + @Test + void readMyTableBeforeMakingGame() { + for (int i = 0; i < 3; i++) { + matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(i)); + } + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); + SlotStatusResponseListDto slotStatusList = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), + Option.NORMAL); + for (List dtos : slotStatusList.getMatchBoards()) { + for (SlotStatusDto dto : dtos) { + if (dto.getStartTime().equals(slotTimes.get(0))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(1))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(2))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); + } + if (dto.getStartTime().equals(slotTimes.get(3))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); + } + } + } + + } + + @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ๋“ฑ๋ก ๋˜๋ฉด ์ œ 3์žํ•œํ…Œ closed ์ฒ˜๋ฆฌ") + @Test + void getClosedStatusOfExistGame() { + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); + SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(3)), + Option.NORMAL); + for (List dtos : allMatchStatus.getMatchBoards()) { + for (SlotStatusDto dto : dtos) { + if (dto.getStartTime().equals(slotTimes.get(3))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); + } + } + } + } + + @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ๋“ฑ๋ก ๋˜๋ฉด ์ œ3์ž๊ฐ€ ๋‹ค๋ฅธ ๊ฒŒ์ž„ ๋“ฑ๋กํ•ด๋„ ์ œ 3์žํ•œํ…Œ closed ์ฒ˜๋ฆฌ") + @Test + void getClosedStatusOfExistGame2() { + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(3)), Option.NORMAL, slotTimes.get(4)); + matchService.makeMatch(UserDto.from(users.get(4)), Option.NORMAL, slotTimes.get(4)); + SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(3)), + Option.NORMAL); + for (List dtos : allMatchStatus.getMatchBoards()) { + for (SlotStatusDto dto : dtos) { + if (dto.getStartTime().equals(slotTimes.get(3))) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); + } + } + } + } + + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์— ๋Œ€ํ•œ ์Šฌ๋กฏ ๋ธ”๋ฝ") + @Test + @Disabled + void getClosedStatusOfTournament() { + // given + Tournament tournament = Tournament.builder() + .title("test tournament") + .contents("test contents") + .startTime(LocalDateTime.now().plusHours(1)) + .endTime(LocalDateTime.now().plusHours(2)) + .type(TournamentType.MASTER) + .status(TournamentStatus.BEFORE) + .build(); + tournamentRepository.save(tournament); + tierRepository.save(new Tier("image url")); + + // TODO ํ˜„์žฌ upload redisํ•ด๋„ redis ๋ฐ์ดํ„ฐ ์—†๋‹ค๋Š” ์—๋Ÿฌ ๋ฐœ์ƒํ•จ + redisUploadService.uploadRedis(); + // when + LocalDateTime now = LocalDateTime.now(); + SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), + Option.NORMAL); + + // then + for (List dtos : allMatchStatus.getMatchBoards()) { + for (SlotStatusDto dto : dtos) { + if (dto.getStartTime().isBefore(tournament.getStartTime()) + || dto.getEndTime().isAfter(tournament.getEndTime())) { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.OPEN.getCode()); + } else { + Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); + } + } + } + } + } + + @Nested + @DisplayName("ํ˜„์žฌ ๋งค์น˜ ์ •๋ณด ์กฐํšŒ API ํ…Œ์ŠคํŠธ") + class GetCurrentMatch { + @DisplayName("current Match ์กฐํšŒ : user๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ๋งค์นญ๋˜์—ˆ์„ ๋•Œ") + @Test + void readCurrentMatchAfterMakingGameEntity() { + //๊ฒŒ์ž„์ƒ์„ฑ + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); + matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); + UserDto userDto = UserDto.from(users.get(1)); + MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(userDto); + //user์˜ current match ํ™•์ธ + List match = currentMatch.getMatch(); + Assertions.assertThat(match.size()).isEqualTo(1); + Assertions.assertThat(match.get(0).getMyTeam().get(0)).isEqualTo(users.get(1).getIntraId()); + Assertions.assertThat(match.get(0).getEnemyTeam().get(0)).isEqualTo(users.get(2).getIntraId()); + Assertions.assertThat(match.get(0).getStartTime()).isEqualTo(slotTimes.get(3)); + Assertions.assertThat(match.get(0).getIsMatched()).isEqualTo(true); + } + + @DisplayName("current Match ์กฐํšŒ : user๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ๋งค์นญ๋˜์ง€ ์•Š์•˜์„ ๋•Œ") + @Test + void readCurrentMatchBeforeMakingGameEntity() { + //์œ ์ € ์Šฌ๋กฏ 3๊ฐœ ๋“ฑ๋ก ์‹œ๋„ + for (int i = 0; i < 3; i++) { + System.out.println("slotTimes = " + slotTimes.get(i)); + matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(i)); + } + UserDto userDto = UserDto.from(users.get(1)); + MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(userDto); + List match = currentMatch.getMatch(); + //user current match ํ™•์ธ + Assertions.assertThat(match.size()).isEqualTo(3); + for (int i = 0; i < 3; i++) { + System.out.println("match = " + match.get(i).getStartTime()); + Assertions.assertThat(match.get(i).getMyTeam().size()).isEqualTo(0); + Assertions.assertThat(match.get(i).getEnemyTeam().size()).isEqualTo(0); + Assertions.assertThat(match.get(i).getStartTime()).isEqualTo(slotTimes.get(i)); + Assertions.assertThat(match.get(i).getIsMatched()).isEqualTo(false); + } + } + + @DisplayName("Guest User slot ์กฐํšŒ") + @Test + void readAllSlotsAndCurrentMatchForGuset() { + User guestUser = matchTestSetting.createGuestUser(); + MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(UserDto.from(guestUser)); + SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(guestUser), + Option.NORMAL); + Assertions.assertThat(currentMatch.getMatch().size()).isEqualTo(0); + System.out.println("allMatchStatus = " + allMatchStatus); + } + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceTest.java new file mode 100644 index 000000000..0b7aa2530 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceTest.java @@ -0,0 +1,344 @@ +package gg.pingpong.api.user.match.service; + +import static gg.data.tournament.type.RoundNumber.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.type.StatusType; +import gg.data.match.type.TournamentMatchStatus; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.match.utils.MatchIntegrationTestUtils; +import gg.pingpong.api.user.match.utils.TournamentGameTestUtils; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.match.EnrolledSlotException; +import gg.utils.exception.match.SlotNotFoundException; +import gg.utils.exception.match.WinningTeamNotFoundException; + +@IntegrationTest +@Transactional +public class MatchTournamentServiceTest { + @Autowired + TestDataUtils testDataUtils; + @Autowired + SlotManagementRepository slotManagementRepository; + @Autowired + GameRepository gameRepository; + @Autowired + MatchTournamentService matchTournamentService; + @Autowired + MatchIntegrationTestUtils matchTestUtils; + @MockBean + NotiAdminService notiAdminService; + + Tournament tournament; + List allTournamentGames; + + @BeforeEach + public void beforeEach() { + testDataUtils.createSeason(); + testDataUtils.createSlotManagement(15); + tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "test"); + allTournamentGames = testDataUtils.createTournamentGameList(tournament, 7); + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ๋ณ„ ๊ฒฝ๊ธฐ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ") + class MatchTournament { + @Test + @DisplayName("8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ ์„ฑ๊ณต") + public void quarterTest() { + // when + matchTournamentService.matchGames(tournament, QUARTER_FINAL); + + // then + List quarterRounds = TournamentRound.getSameRounds(QUARTER_FINAL); + List quarterRoundGames = allTournamentGames.stream() + .filter(o -> quarterRounds.contains(o.getTournamentRound())) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + LocalDateTime startTime = tournament.getStartTime(); + int gameInterval = slotManagementRepository.findCurrent(startTime) + .orElseThrow(SlotNotFoundException::new) + .getGameInterval(); + + // 4๊ฐœ์˜ 8๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + assertThat(quarterRoundGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 2); + for (TournamentGame tournamentGame : quarterRoundGames) { + assertThat(tournamentGame.getGame()).isNotNull(); + assertThat(tournamentGame.getGame().getStatus()).isEqualTo(StatusType.BEFORE); + assertThat(tournamentGame.getGame().getStartTime()).isEqualTo(startTime); + assertThat(tournamentGame.getGame().getEndTime()).isEqualTo(startTime.plusMinutes(gameInterval)); + startTime = startTime.plusMinutes((long)gameInterval); + } + verify(notiAdminService, times(8)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); + } + + @Test + @DisplayName("4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ ์„ฑ๊ณต") + public void semiTest() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ + List tournamentGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(tournamentGames, List.of(2, 0)); + + // when + matchTournamentService.matchGames(tournament, SEMI_FINAL); + + // then + List semiRounds = TournamentRound.getSameRounds(SEMI_FINAL); + List semiRoundGames = allTournamentGames.stream() + .filter(o -> semiRounds.contains(o.getTournamentRound())) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + // 2๊ฐœ์˜ 4๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + assertThat(semiRoundGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 4); + for (TournamentGame tournamentGame : semiRoundGames) { + assertThat(tournamentGame.getGame()).isNotNull(); + assertThat(tournamentGame.getGame().getStatus()).isEqualTo(StatusType.BEFORE); + } + // 8๊ฐ•์—์„œ ์ด๊ธด ์œ ์ €๋ผ๋ฆฌ 4๊ฐ•์— ๋งค์นญ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + List quarterRounds = TournamentRound.getSameRounds(QUARTER_FINAL); + List quarterRoundGames = allTournamentGames.stream() + .filter(o -> quarterRounds.contains(o.getTournamentRound())) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + List semiTeams = new ArrayList<>(); + List quarterWinningTeams = new ArrayList<>(); + for (TournamentGame semiRoundGame : semiRoundGames) { + semiTeams.add(semiRoundGame.getGame().getTeams().get(0).getTeamUsers().get(0).getUser()); + semiTeams.add(semiRoundGame.getGame().getTeams().get(1).getTeamUsers().get(0).getUser()); + } + for (TournamentGame quarterRoundGame : quarterRoundGames) { + Team winningTeam = TournamentGameTestUtils.getWinningTeam(quarterRoundGame.getGame()); + quarterWinningTeams.add(winningTeam.getTeamUsers().get(0).getUser()); + } + assertThat(semiTeams).contains(quarterWinningTeams.get(0)); + assertThat(semiTeams).contains(quarterWinningTeams.get(1)); + verify(notiAdminService, times(4)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); + } + + @Test + @DisplayName("๊ฒฐ์Šน ๊ฒฝ๊ธฐ ๋งค์นญ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต") + public void finalTest() { + // given + // 8๊ฐ• & 4๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ ์ž…๋ ฅ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); + + // when + matchTournamentService.matchGames(tournament, THE_FINAL); + + // then + // 1๊ฐœ์˜ ๊ฒฐ์Šน ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + TournamentGame finalRoundGame = allTournamentGames.stream() + .filter(o -> TournamentRound.THE_FINAL.equals(o.getTournamentRound())).findAny().orElse(null); + assertThat(finalRoundGame.getGame()).isNotNull(); + verify(notiAdminService, times(2)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); + } + + @Test + @DisplayName("์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ์‹คํŒจ") + public void failAlreadyMatched() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + 4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); + + // when, then + assertThatThrownBy(() -> matchTournamentService.matchGames(tournament, SEMI_FINAL)) + .isInstanceOf(EnrolledSlotException.class); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ํ™•์ธ ํ…Œ์ŠคํŠธ") + class CheckTournament { + @Test + @DisplayName("IMPOSSIBLE : ๊ฒฐ์Šน ๊ฒฝ๊ธฐ ์ ์ˆ˜ ์ž…๋ ฅ ํ›„ ํ† ๋„ˆ๋จผํŠธ END ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต & ์ข…๋ฃŒ ์‹œ๊ฐ„ ๊ฐฑ์‹ ") + public void finalEndTest() { + // given + // 8๊ฐ• & 4๊ฐ• & ๊ฒฐ์Šน ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ ์ž…๋ ฅ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); + Game finalGame = matchTestUtils.matchTournamentGames(tournament, TournamentRound.THE_FINAL) + .get(0) + .getGame(); + matchTestUtils.updateTournamentGameResult(finalGame, List.of(2, 0)); + + // when + TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(finalGame); + + // then + // ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ๊ฐ€ END๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ + // winner๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ + assertThat(TournamentMatchStatus.NO_MORE_MATCHES).isEqualTo(tournamentMatchStatus); + assertThat(tournament.getStatus()).isEqualTo(TournamentStatus.END); + assertThat(tournament.getWinner()).isNotNull(); + assertThat(tournament.getEndTime()).isEqualTo(finalGame.getEndTime()); + } + + @Test + @DisplayName("IMPOSSBLE : ์ง„ํ–‰์ค‘์ธ ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ๊ฒฝ๊ธฐ๊ฐ€ ์ ์ˆ˜์ž…๋ ฅ ์™„๋ฃŒ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ") + public void impossibleTest() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + + // when + matchTestUtils.updateTournamentGameResult(quarterGames.get(0).getGame(), List.of(2, 0)); + TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame( + quarterGames.get(0).getGame()); + + // then + assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.UNNECESSARY); + } + + @Test + @DisplayName("ALREADY_MATCHED : ์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ") + public void alreadyMatchedTest() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + 4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); + + // when + TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame( + quarterGames.get(0).getGame()); + + // then + assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.ALREADY_MATCHED); + } + + @Test + @DisplayName("POSSIBLE : ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ") + public void possibleTest() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + + // when + TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame( + quarterGames.get(0).getGame()); + + // then + assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.REQUIRED); + } + + } + + @Nested + @DisplayName("์œ„๋„ˆ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋‹ค์Œ ๊ฒฝ๊ธฐ ํŒ€ ๋ณ€๊ฒฝ ํ…Œ์ŠคํŠธ") + class ChangeTeam { + @Test + @DisplayName("8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ 4๊ฐ• ๊ฒฝ๊ธฐ๋กœ ํŒ€ ๋ณ€๊ฒฝ ์„ฑ๊ณต") + public void quarterToSemiTest() { + // given + // 8๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ + 4๊ฐ• ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); + List semiGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.SEMI_FINAL_1); + + Game game = quarterGames.get(0) + .getGame(); // QAUARTER_FINAL_1l Game + TournamentRound nextRound = quarterGames.get(0).getTournamentRound().getNextRound(); // SEMI_FINAL_1 + Game nextMatchedGame = semiGames.stream() // SEMI_FINAL_1 Game + .filter(o -> nextRound.equals(o.getTournamentRound())) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("๋‹ค์Œ ๊ฒฝ๊ธฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")).getGame(); + + // when + // ๊ธฐ์กด 8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ ์ง„ ํŒ€์ด ์ ์ˆ˜ ์ˆ˜์ •์œผ๋กœ ์ด๊ธด ํŒ€์œผ๋กœ ๋ณ€๊ฒฝ + Team losingTeam = game.getTeams() + .stream() + .filter(Team::getWin) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("์Šน๋ฆฌํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); + Team winningTeam = game.getTeams() + .stream() + .filter(o -> !o.getWin()) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("ํŒจ๋ฐฐํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); + losingTeam.updateScore(0, false); + winningTeam.updateScore(2, true); + matchTournamentService.updateMatchedGameUser(game, nextMatchedGame); + + // then + // ์ ์ˆ˜ ์ˆ˜์ •์œผ๋กœ 8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ ์ด๊ธด ํŒ€์ด ๋‹ค์Œ ๊ฒฝ๊ธฐ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + List nextGameUsers = new ArrayList<>(); + nextGameUsers.add(nextMatchedGame.getTeams().get(0).getTeamUsers().get(0).getUser()); + nextGameUsers.add(nextMatchedGame.getTeams().get(1).getTeamUsers().get(0).getUser()); + + assertThat(nextGameUsers.contains(winningTeam.getTeamUsers().get(0).getUser())).isTrue(); + assertThat(nextGameUsers.contains(losingTeam.getTeamUsers().get(0).getUser())).isFalse(); + verify(notiAdminService, times(2)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); + } + + @Test + @DisplayName("์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์‹คํŒจ") + public void failUpdateWinner() { + // given + // 8๊ฐ• ๋งค์นญ + List quarterGames = matchTestUtils.matchTournamentGames(tournament, + TournamentRound.QUARTER_FINAL_1); + TournamentGame targetTournamentGame = quarterGames.get(0); + TournamentRound nextRound = targetTournamentGame.getTournamentRound().getNextRound(); + Game nextMatchedGame = allTournamentGames.stream() + .filter(o -> nextRound.equals(o.getTournamentRound())) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("๋‹ค์Œ ๊ฒฝ๊ธฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")).getGame(); + + // when, then + assertThatThrownBy( + () -> matchTournamentService.updateMatchedGameUser(targetTournamentGame.getGame(), nextMatchedGame)) + .isInstanceOf(WinningTeamNotFoundException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceUnitTest.java new file mode 100644 index 000000000..c0acdbb9e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/service/MatchTournamentServiceUnitTest.java @@ -0,0 +1,331 @@ +package gg.pingpong.api.user.match.service; + +import static gg.data.tournament.type.RoundNumber.*; +import static gg.pingpong.api.user.match.utils.TournamentGameTestUtils.*; +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.manage.SlotManagement; +import gg.data.match.type.TournamentMatchStatus; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.RoundNumber; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.match.utils.GameTestUtils; +import gg.pingpong.api.user.match.utils.TournamentTestUtils; +import gg.pingpong.api.user.match.utils.UserTestUtils; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.match.EnrolledSlotException; +import gg.utils.exception.match.WinningTeamNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +public class MatchTournamentServiceUnitTest { + @InjectMocks + private MatchTournamentService matchTournamentService; + @Mock + private TournamentGameRepository tournamentGameRepository; + @Mock + private GameRepository gameRepository; + @Mock + private SlotManagementRepository slotManagementRepository; + @Mock + private SeasonFindService seasonFindService; + @Mock + private NotiAdminService notiAdminService; + private static final Season season = Season.builder().startTime(LocalDateTime.now()).startPpp(123).build(); + private static Long gameId; + private static Long tournamentGameId; + + @BeforeEach + void init() { + gameId = 1L; + tournamentGameId = 1L; + } + + @Nested + @DisplayName("checkTournamentGame() - 8๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ง„ํ–‰์ค‘์ธ ํ† ๋„ˆ๋จผํŠธ์—์„œ ๋‹ค์Œ ๋ผ์šด๋“œ์˜ ๋งค์นญ ํ•„์š” ์œ ๋ฌด๋ฅผ ํ™•์ธํ•œ๋‹ค.") + class CheckNextRoundTest { + private Tournament tournament; + + @BeforeEach + void init() { + tournament = TournamentTestUtils.createTournament(TournamentStatus.LIVE); + setFieldWithReflection(tournament, "id", 1L); + for (TournamentGame tournamentGame : tournament.getTournamentGames()) { + setFieldWithReflection(tournamentGame, "id", tournamentGameId++); + } + matchTournamentGames(tournament, QUARTER_FINAL, season); + List games = tournament.getTournamentGames().stream() + .filter(tournamentGame -> tournamentGame.getTournamentRound().getRoundNumber() == QUARTER_FINAL) + .map(TournamentGame::getGame).collect(Collectors.toList()); + setGameIds(games); + } + + @Test + @DisplayName("8๊ฐ•์˜ ๋ชจ๋“  ๊ฒŒ์ž„์ด ์ข…๋ฃŒ๋œ ๊ฒฝ์šฐ, 4๊ฐ•์ด ๋งค์นญ ํ•„์š”ํ•˜๋ฏ€๋กœ REQUIRED ๋ฐ˜ํ™˜") + void checkRequiredMatch() { + // given + List quarterGames = getTournamentGamesByRoundNum(tournament, QUARTER_FINAL); + finishTournamentGames(quarterGames); + Random random = new Random(); + TournamentGame target = quarterGames.get(random.nextInt(quarterGames.size())); + RoundNumber nextRound = target.getTournamentRound().getNextRound().getRoundNumber(); + given(tournamentGameRepository.findByGameId(target.getGame().getId())).willReturn(Optional.of(target)); + given(tournamentGameRepository.findAllByTournamentId(tournament.getId())) + .willReturn(tournament.getTournamentGames()); + given(tournamentGameRepository.findByTournamentIdAndTournamentRoundIn( + tournament.getId(), TournamentRound.getSameRounds(nextRound))) + .willReturn(getTournamentGamesByRoundNum(tournament, nextRound)); + + // when + TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(target.getGame()); + + // then + assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.REQUIRED); + } + + @Test + @DisplayName("8๊ฐ•์— ์ข…๋ฃŒ๋˜์ง€ ์•Š์€ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ, 4๊ฐ• ๋งค์นญ์ด ๋ถˆํ•„์š”ํ•˜๋ฏ€๋กœ UNNECESSARY ๋ฐ˜ํ™˜") + void checkUnnecessaryMatch() { + // given + TournamentGame quarterGame = getTournamentGameByRound(tournament, TournamentRound.QUARTER_FINAL_1).get(); + given(tournamentGameRepository.findByGameId(quarterGame.getGame().getId())).willReturn( + Optional.of(quarterGame)); + given(tournamentGameRepository.findAllByTournamentId(tournament.getId())) + .willReturn(tournament.getTournamentGames()); + + // when + TournamentMatchStatus matchStatus = matchTournamentService.checkTournamentGame(quarterGame.getGame()); + + // then + assertThat(matchStatus).isEqualTo(TournamentMatchStatus.UNNECESSARY); + } + + @Test + @DisplayName("๊ฒฐ์Šน์ „ ๊ฒŒ์ž„์ผ ๊ฒฝ์šฐ, ๋งค์นญํ•  ๊ฒฝ๊ธฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ NO_MORE_MATCHES์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ํ† ๋„ˆ๋จผํŠธ๋Š” ์ข…๋ฃŒ๋œ๋‹ค.") + void checkFinalGame() { + // given + User user = UserTestUtils.createUser(); + User enemy = UserTestUtils.createUser(); + Game finalGame = GameTestUtils.createGame(user, enemy, season, Mode.TOURNAMENT); + TournamentGame finalTournamentGame = getTournamentGameByRound(tournament, TournamentRound.THE_FINAL).get(); + finalTournamentGame.updateGame(finalGame); + finishTournamentGame(finalTournamentGame); + given(tournamentGameRepository.findByGameId(finalGame.getId())).willReturn( + Optional.of(finalTournamentGame)); + + // when + TournamentMatchStatus matchStatus = matchTournamentService.checkTournamentGame(finalGame); + + // then + assertThat(matchStatus).isEqualTo(TournamentMatchStatus.NO_MORE_MATCHES); + assertThat(tournament.getStatus()).isEqualTo(TournamentStatus.END); + assertThat(tournament.getWinner()).isNotNull(); + } + + @Test + @DisplayName("๋‹ค์Œ ๋ผ์šด๋“œ์ธ 4๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ด๋ฏธ ๋งค์นญ๋œ ๊ฒฝ์šฐ, ALREADY_MATCHED๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.") + void checkAlreadyMatched() { + // given + finishTournamentGames(getTournamentGamesByRoundNum(tournament, QUARTER_FINAL)); + matchTournamentGames(tournament, SEMI_FINAL, season); + Game targetGame = getTournamentGameByRound(tournament, TournamentRound.QUARTER_FINAL_1).get().getGame(); + given(tournamentGameRepository.findByGameId(targetGame.getId())).willReturn(Optional.of( + getTournamentGameByRound(tournament, TournamentRound.QUARTER_FINAL_1).get())); + given(tournamentGameRepository.findAllByTournamentId(tournament.getId())) + .willReturn(tournament.getTournamentGames()); + given(tournamentGameRepository.findByTournamentIdAndTournamentRoundIn( + tournament.getId(), TournamentRound.getSameRounds(SEMI_FINAL))) + .willReturn(getTournamentGamesByRoundNum(tournament, SEMI_FINAL)); + + // when + TournamentMatchStatus matchStatus = matchTournamentService.checkTournamentGame(targetGame); + + // then + assertThat(matchStatus).isEqualTo(TournamentMatchStatus.ALREADY_MATCHED); + } + } + + @Nested + @DisplayName("matchGames() - ํ† ๋„ˆ๋จผํŠธ์˜ ๊ฒŒ์ž„ ๋งค์นญ") + class MatchTournamentGameTest { + private Tournament tournament; + private SlotManagement slotManagement; + + @BeforeEach + void init() { + tournament = TournamentTestUtils.createTournament(TournamentStatus.LIVE); + setFieldWithReflection(tournament, "id", 1L); + for (TournamentGame tournamentGame : tournament.getTournamentGames()) { + setFieldWithReflection(tournamentGame, "id", tournamentGameId++); + } + matchTournamentGames(tournament, QUARTER_FINAL, season); + List games = tournament.getTournamentGames().stream() + .filter(tournamentGame -> tournamentGame.getTournamentRound().getRoundNumber() == QUARTER_FINAL) + .map(TournamentGame::getGame).collect(Collectors.toList()); + setGameIds(games); + + slotManagement = SlotManagement.builder() + .startTime(tournament.getStartTime()) + .gameInterval(10) + .build(); + } + + @Test + @DisplayName("์ด๋ฏธ ๋งค์นญ๋œ 8๊ฐ•์„ ๋งค์นญํ•˜๋ ค๊ณ  ํ•  ๋•Œ, EnrolledSlotException ๋ฐœ์ƒ") + void matchAlreadyMatchedGame() { + // given + given(tournamentGameRepository.findByTournamentIdAndTournamentRoundIn( + tournament.getId(), TournamentRound.getSameRounds(QUARTER_FINAL))) + .willReturn(getTournamentGamesByRoundNum(tournament, QUARTER_FINAL)); + + // when, then + assertThatThrownBy(() -> matchTournamentService.matchGames(tournament, QUARTER_FINAL)) + .isInstanceOf(EnrolledSlotException.class); + } + + @Test + @DisplayName("4๊ฐ• ๋งค์นญ ์„ฑ๊ณต ํ›„ noti ์ „์†ก ๋ฐ ๊ฒŒ์ž„ ์ €์žฅ ํ™•์ธ") + void matchSuccess() { + // given + List quarterGames = getTournamentGamesByRoundNum(tournament, QUARTER_FINAL); + finishTournamentGames(quarterGames); + given(seasonFindService.findCurrentSeason(tournament.getStartTime())).willReturn(season); + given(slotManagementRepository.findCurrent(tournament.getStartTime())).willReturn( + Optional.of(slotManagement)); + given(tournamentGameRepository.findAllByTournamentId(tournament.getId())) + .willReturn(tournament.getTournamentGames()); + + // when + matchTournamentService.matchGames(tournament, SEMI_FINAL); + + // then + verify(gameRepository, times(SEMI_FINAL.getRound() / 2)).save(any(Game.class)); + verify(notiAdminService, times(SEMI_FINAL.getRound())).sendAnnounceNotiToUser( + any(SendNotiAdminRequestDto.class)); + List semiGames = getTournamentGamesByRoundNum(tournament, SEMI_FINAL); + for (TournamentGame semiGame : semiGames) { + assertThat(semiGame.getGame()).isNotNull(); + } + } + } + + @Nested + @DisplayName("updateMatchedGameUser() - ์ด์ „ ๊ฒฝ๊ธฐ 8๊ฐ•์˜ ์ˆ˜์ •๋œ ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋งค์นญ๋œ 4๊ฐ• ๊ฒฝ๊ธฐ์˜ ํ”Œ๋ ˆ์ด์–ด ์ˆ˜์ •") + class UpdateMatchResultTest { + private Tournament tournament; + + @BeforeEach + void init() { + tournament = TournamentTestUtils.createTournament(TournamentStatus.LIVE); + setFieldWithReflection(tournament, "id", 1L); + for (TournamentGame tournamentGame : tournament.getTournamentGames()) { + setFieldWithReflection(tournamentGame, "id", tournamentGameId++); + } + matchTournamentGames(tournament, QUARTER_FINAL, season); + List games = tournament.getTournamentGames().stream() + .filter(tournamentGame -> tournamentGame.getTournamentRound().getRoundNumber() == QUARTER_FINAL) + .map(TournamentGame::getGame).collect(Collectors.toList()); + setGameIds(games); + } + + @Test + @DisplayName("์ด์ „ ๊ฒฝ๊ธฐ 8๊ฐ•์˜ ๊ฒฐ๊ณผ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ, WinningTeamNotFoundException ๋ฐœ์ƒ") + void updateMatchResultWithoutWinner() { + // given + Game game = getTournamentGameByRound(tournament, TournamentRound.QUARTER_FINAL_1).get().getGame(); + + // when, then + Game nextMatchedGame = getTournamentGameByRound(tournament, TournamentRound.SEMI_FINAL_1).get().getGame(); + assertThatThrownBy(() -> matchTournamentService.updateMatchedGameUser(game, nextMatchedGame)) + .isInstanceOf(WinningTeamNotFoundException.class); + } + + @Test + @DisplayName("์ด๋ฏธ ๋งค์นญ๋œ 4๊ฐ• ๊ฒฝ๊ธฐ์˜ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ") + void success() { + // given + finishTournamentGames(getTournamentGamesByRoundNum(tournament, QUARTER_FINAL)); + matchTournamentGames(tournament, SEMI_FINAL, season); + List semiGames = tournament.getTournamentGames().stream() + .filter(tournamentGame -> tournamentGame.getTournamentRound().getRoundNumber() == SEMI_FINAL) + .map(TournamentGame::getGame).collect(Collectors.toList()); + setGameIds(semiGames); + Game modifiedGame = getTournamentGameByRound(tournament, TournamentRound.QUARTER_FINAL_1).get().getGame(); + Game nextMatchedGame = getTournamentGameByRound(tournament, TournamentRound.SEMI_FINAL_1).get().getGame(); + Team losingTeam = getWinningTeam(modifiedGame); + Team winningTeam = getLosingTeam(modifiedGame); + losingTeam.updateScore(1, false); + winningTeam.updateScore(2, true); + + // when + matchTournamentService.updateMatchedGameUser(modifiedGame, nextMatchedGame); + + // then + List nextGameUsers = new ArrayList<>(); + nextGameUsers.add(nextMatchedGame.getTeams().get(0).getTeamUsers().get(0).getUser()); + nextGameUsers.add(nextMatchedGame.getTeams().get(1).getTeamUsers().get(0).getUser()); + + assertThat(nextGameUsers.contains(winningTeam.getTeamUsers().get(0).getUser())).isTrue(); + assertThat(nextGameUsers.contains(losingTeam.getTeamUsers().get(0).getUser())).isFalse(); + verify(notiAdminService, times(2)).sendAnnounceNotiToUser( + any(SendNotiAdminRequestDto.class)); + } + } + + private void finishTournamentGame(TournamentGame tournamentGame) { + Game game = tournamentGame.getGame(); + setFieldWithReflection(game, "status", StatusType.END); + List teams = game.getTeams(); + teams.get(0).updateScore(2, true); + teams.get(1).updateScore(1, false); + } + + private void finishTournamentGames(List tournamentGames) { + for (TournamentGame tournamentGame : tournamentGames) { + finishTournamentGame(tournamentGame); + } + } + + private void setGameId(Game game) { + setFieldWithReflection(game, "id", gameId++); + } + + private void setGameIds(List games) { + for (Game game : games) { + setGameId(game); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/GameTestUtils.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/GameTestUtils.java new file mode 100644 index 000000000..1b6b44346 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/GameTestUtils.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.match.utils; + +import java.time.LocalDateTime; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.season.Season; +import gg.data.user.User; + +public class GameTestUtils { + public static Game createGame(User user, User enemy, Season season, Mode mode) { + LocalDateTime startTime = LocalDateTime.of(2024, 1, 1, 0, 0); + Game game = new Game(season, StatusType.BEFORE, mode, startTime, startTime.plusMinutes(15)); + Team teamA = new Team(game, -1, false); + Team teamB = new Team(game, -1, false); + new TeamUser(teamA, user); + new TeamUser(teamB, enemy); + return game; + } + + public static Game createNormalGame(User user, User enemy, Season season) { + return createGame(user, enemy, season, Mode.NORMAL); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/MatchIntegrationTestUtils.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/MatchIntegrationTestUtils.java new file mode 100644 index 000000000..0bb2d3def --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/MatchIntegrationTestUtils.java @@ -0,0 +1,154 @@ +package gg.pingpong.api.user.match.utils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.manage.SlotManagement; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentRound; +import gg.data.user.User; +import gg.repo.game.GameRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.repo.user.UserRepository; +import gg.utils.RedisKeyManager; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class MatchIntegrationTestUtils { + private final UserRepository userRepository; + private final SeasonRepository seasonRepository; + private final RankRedisRepository rankRedisRepository; + private final SlotManagementRepository slotManagementRepository; + private final GameRepository gameRepository; + + public User createUser() { + User user = UserTestUtils.createUser(); + userRepository.save(user); + return user; + } + + public User createGuestUser() { + User guest = UserTestUtils.createGuestUser(); + userRepository.save(guest); + return guest; + } + + public RankRedis addUsertoRankRedis(Long userId, Integer ppp, Long seasonId) { + String randomId = UUID.randomUUID().toString(); + RankRedis rankRedis = new RankRedis(userId, randomId, ppp, 0, 0, "test", + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + rankRedisRepository.addRankData(RedisKeyManager.getHashKey(seasonId), userId, rankRedis); + rankRedisRepository.addToZSet(RedisKeyManager.getZSetKey(seasonId), userId, ppp); + return rankRedis; + } + + public List getTestSlotTimes(Integer interval) { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime standard = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), + now.getHour(), 0); + List sampleSlots = new ArrayList(); + for (int i = 0; i < 15; i++) { + if (standard.plusMinutes(interval * i).isAfter(now)) { + sampleSlots.add(standard.plusMinutes(interval * i)); + } + } + return sampleSlots; + } + + public Season makeTestSeason(Integer pppGap) { + Optional currentSeason = seasonRepository.findCurrentSeason(LocalDateTime.now()); + if (currentSeason.isPresent()) { + return currentSeason.get(); + } + Season season = new Season( + "test", + LocalDateTime.now().minusDays(1), + LocalDateTime.of(9999, 12, 31, 23, 59, 59), + 1000, + pppGap + ); + seasonRepository.save(season); + return season; + } + + public SlotManagement makeTestSlotManagement(Integer interval) { + SlotManagement slotManagement = SlotManagement.builder() + .futureSlotTime(10) + .pastSlotTime(0) + .gameInterval(interval) + .openMinute(5) + .startTime(LocalDateTime.now().minusHours(2)) + .build(); + slotManagementRepository.save(slotManagement); + return slotManagement; + } + + /** + * ํ† ๋„ˆ๋จผํŠธ์—์„œ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๊ฒฝ๊ธฐ๋“ค์„ ๋งค์นญ (์ƒ์„ฑ) + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param round ํ•ด๋‹น ๋ผ์šด๋“œ์™€ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ + * ex ) 8๊ฐ•์˜ ๊ฒฝ์šฐ 8๊ฐ•์˜ 4๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ + * @return ๋งค์นญ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + */ + public List matchTournamentGames(Tournament tournament, TournamentRound round) { + Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()) + .orElseThrow(() -> new IllegalArgumentException("ํ˜„์žฌ ์‹œ์ฆŒ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); + List sameRoundGames = TournamentGameTestUtils.matchTournamentGames(tournament, + round.getRoundNumber(), season); + for (TournamentGame tournamentGame : sameRoundGames) { + Game game = tournamentGame.getGame(); + gameRepository.save(game); + } + return sameRoundGames; + } + + /** + * ์—ฌ๋Ÿฌ ๊ฒฝ๊ธฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์ˆ˜์ • + * @param tournamentGames + * @param scores + */ + public void updateTournamentGamesResult(List tournamentGames, List scores) { + int sum = scores.stream().mapToInt(Integer::intValue).sum(); + if (sum > 3 || sum < 0) { + throw new IllegalArgumentException("๊ฒŒ์ž„ ์ ์ˆ˜๋Š” 0 ~ 3 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); + } + List games = tournamentGames.stream().map(TournamentGame::getGame).collect(Collectors.toList()); + for (Game game : games) { + updateTournamentGameResult(game, scores); + } + } + + /** + * ํ•˜๋‚˜์˜ ๊ฒฝ๊ธฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์—…๋ฐ์ดํŠธ + * @param game + * @param scores + */ + public void updateTournamentGameResult(Game game, List scores) { + int sum = scores.stream().mapToInt(Integer::intValue).sum(); + if (sum > 3 || sum < 0) { + throw new IllegalArgumentException("๊ฒŒ์ž„ ์ ์ˆ˜๋Š” 0 ~ 3 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); + } + List teams = game.getTeams(); + teams.get(0).updateScore(scores.get(0), scores.get(0) > scores.get(1)); + teams.get(1).updateScore(scores.get(1), scores.get(0) < scores.get(1)); + // BEFORE -> LIVE -> WAIT -> END + game.updateStatus(); + game.updateStatus(); + game.updateStatus(); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentGameTestUtils.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentGameTestUtils.java new file mode 100644 index 000000000..2bbd24485 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentGameTestUtils.java @@ -0,0 +1,110 @@ +package gg.pingpong.api.user.match.utils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import gg.data.game.Game; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.RoundNumber; +import gg.data.tournament.type.TournamentRound; +import gg.data.user.User; +import gg.utils.exception.match.WinningTeamNotFoundException; + +public class TournamentGameTestUtils { + + /** + * ํ† ๋„ˆ๋จผํŠธ์—์„œ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๊ฒฝ๊ธฐ๋“ค์„ ๋งค์นญ (์ƒ์„ฑ) + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ํ•ด๋‹น ๋ผ์šด๋“œ์™€ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ + * ex ) 8๊ฐ•์˜ ๊ฒฝ์šฐ 8๊ฐ•์˜ 4๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ + * @return ๋งค์นญ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ + */ + public static List matchTournamentGames(Tournament tournament, RoundNumber roundNumber, + Season season) { + List sameRounds = TournamentRound.getSameRounds(roundNumber); + List sameRoundGames = tournament.getTournamentGames().stream() + .filter(o -> sameRounds.contains(o.getTournamentRound())) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + RoundNumber previousRoundNumber = TournamentRound.getPreviousRoundNumber(roundNumber); + List previousRoundTournamentGames = previousRoundNumber != null + ? findSameRoundGames(tournament.getTournamentGames(), previousRoundNumber) + : new ArrayList<>(); + + for (int i = 0; i < roundNumber.getRound() / 2; ++i) { + Game game = new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, LocalDateTime.now(), LocalDateTime.now()); + Team team1 = new Team(game, -1, false); + Team team2 = new Team(game, -1, false); + User user1 = findMatchUser(previousRoundTournamentGames, i * 2, tournament); + User user2 = findMatchUser(previousRoundTournamentGames, i * 2 + 1, tournament); + new TeamUser(team1, user1); + new TeamUser(team2, user2); + sameRoundGames.get(i).updateGame(game); + } + return sameRoundGames; + } + + /** + * + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param roundNumber ํ•ด๋‹น ๋ผ์šด๋“œ์™€ ๋™์ผํ•œ ๋ผ์šด๋“œ๋ฅผ ์ฐพ๋Š”๋‹ค. + * @return ํ•ด๋‹น ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + */ + public static List getTournamentGamesByRoundNum(Tournament tournament, RoundNumber roundNumber) { + return tournament.getTournamentGames().stream() + .filter(tournamentGame -> roundNumber == tournamentGame.getTournamentRound().getRoundNumber()) + .collect(Collectors.toList()); + } + + /** + * + * @param tournament ํ† ๋„ˆ๋จผํŠธ + * @param round ํ•ด๋‹น ๋ผ์šด๋“œ์™€ ๋™์ผํ•œ ๋ผ์šด๋“œ๋ฅผ ์ฐพ๋Š”๋‹ค. + * @return ํ•ด๋‹น ๋ผ์šด๋“œ์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. + */ + public static Optional getTournamentGameByRound(Tournament tournament, TournamentRound round) { + return tournament.getTournamentGames().stream() + .filter(tournamentGame -> round == tournamentGame.getTournamentRound()) + .findFirst(); + } + + public static Team getWinningTeam(Game game) { + return game.getTeams().stream() + .filter(team -> Boolean.TRUE.equals(team.getWin())) + .findAny() + .orElseThrow(WinningTeamNotFoundException::new); + } + + public static Team getLosingTeam(Game game) { + return game.getTeams().stream() + .filter(team -> Boolean.FALSE.equals(team.getWin())) + .findAny() + .orElseThrow(WinningTeamNotFoundException::new); + } + + private static User findMatchUser(List previousTournamentGames, int index, Tournament tournament) { + if (previousTournamentGames.isEmpty()) { + return tournament.getTournamentUsers().get(index).getUser(); + } + Game game = previousTournamentGames.get(index).getGame(); + return getWinningTeam(game) + .getTeamUsers().get(0).getUser(); + } + + private static List findSameRoundGames(List tournamentGames, RoundNumber roundNum) { + return tournamentGames.stream() + .filter(tournamentGame -> roundNum == tournamentGame.getTournamentRound().getRoundNumber()) + .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) + .collect(Collectors.toList()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentTestUtils.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentTestUtils.java new file mode 100644 index 000000000..b39ac3b02 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/TournamentTestUtils.java @@ -0,0 +1,46 @@ +package gg.pingpong.api.user.match.utils; + +import java.time.LocalDateTime; + +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; + +public class TournamentTestUtils { + /** + * ํ…Œ์ŠคํŠธ์šฉ Tournament ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. user์™€ tournamentGame๋„ ํ•จ๊ป˜ ์ƒ์„ฑํ•œ๋‹ค. + * @param status ํ…Œ์ŠคํŠธ์šฉ Tournament ๊ฐ์ฒด์˜ status + * @return ํ…Œ์ŠคํŠธ์šฉ Tournament ๊ฐ์ฒด + */ + public static Tournament createTournament(TournamentStatus status) { + LocalDateTime startTime = LocalDateTime.of(2024, 1, 1, 0, 0); + LocalDateTime endTime = startTime.plusHours(3); + Tournament tournament = Tournament.builder() + .title("title") + .contents("contents") + .startTime(startTime) + .endTime(endTime) + .type(TournamentType.ROOKIE) + .status(status) + .build(); + createJoinedTournamentUsers(tournament); + createTournamentGames(tournament); + return tournament; + } + + private static void createJoinedTournamentUsers(Tournament tournament) { + LocalDateTime registerTime = tournament.getStartTime(); + for (int i = 0; i < Tournament.ALLOWED_JOINED_NUMBER; ++i) { + new TournamentUser(UserTestUtils.createUser(), tournament, true, registerTime); + } + } + + private static void createTournamentGames(Tournament tournament) { + for (TournamentRound round : TournamentRound.values()) { + new TournamentGame(null, tournament, round); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/UserTestUtils.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/UserTestUtils.java new file mode 100644 index 000000000..28ae8de88 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/match/utils/UserTestUtils.java @@ -0,0 +1,35 @@ +package gg.pingpong.api.user.match.utils; + +import java.util.UUID; + +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; + +public class UserTestUtils { + public static User createUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + return User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + } + + public static User createGuestUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + return User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.GUEST) + .totalExp(1000) + .build(); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/controller/MegaphoneControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/controller/MegaphoneControllerTest.java new file mode 100644 index 000000000..eb7ac45c5 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/controller/MegaphoneControllerTest.java @@ -0,0 +1,161 @@ +package gg.pingpong.api.user.megaphone.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalTime; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.store.Item; +import gg.data.store.Megaphone; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.store.controller.request.MegaphoneUseRequestDto; +import gg.repo.store.MegaphoneRepository; +import gg.repo.store.ReceiptRepository; +import gg.utils.ItemTestUtils; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +class MegaphoneControllerTest { + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + MegaphoneRepository megaphoneRepository; + + @Autowired + ReceiptRepository receiptRepository; + + @Autowired + ItemTestUtils itemTestUtils; + + @Test + @Transactional + @DisplayName("[Post] /pingpong/megaphones") + void useMegaphoneTest() throws Exception { + // ํ•ด๋‹น ํ…Œ์ŠคํŠธ๋Š” ์‹œ์Šคํ…œ์ƒ 23:55 ~ 00:05 ์‚ฌ์ด์— ํ…Œ์ŠคํŠธ ๋ถˆ๊ฐ€๋Šฅ + if (LocalTime.now().isAfter(LocalTime.of(23, 54)) + || LocalTime.now().isBefore(LocalTime.of(0, 6))) { + return; + } + String intraId = "intra"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + // db์— ์ €์žฅํ•ด๋‘๊ณ  ํ…Œ์ŠคํŠธ + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", + "default", 40, 50, ItemType.MEGAPHONE); + Item item = itemTestUtils.createItem(newUser, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + MegaphoneUseRequestDto megaphoneUseRequestDto = new MegaphoneUseRequestDto(receipt.getId(), "test"); + String content = objectMapper.writeValueAsString(megaphoneUseRequestDto); + String url = "/pingpong/megaphones"; + + mockMvc.perform(post(url) + .content(content) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + Megaphone result = megaphoneRepository.findFirstByOrderByIdDesc(); + assertThat(result.getContent()).isEqualTo(megaphoneUseRequestDto.getContent()); + } + + @Test + @Transactional + @DisplayName("DELETE /pingpong/megaphones/{megaphoneId}") + public void deleteMegaphoneTest() throws Exception { + //given + String intraId = "intra2"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", + "default", 40, 50, ItemType.MEGAPHONE); + Item item = itemTestUtils.createItem(newUser, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + Receipt receipt2 = itemTestUtils.purchaseItem(newUser, newUser, item); + Megaphone megaphone = itemTestUtils.createMegaPhone(newUser, receipt, "test"); + Megaphone megaphone2 = itemTestUtils.createMegaPhone(newUser, receipt2, "test"); + String url = "/pingpong/megaphones/" + megaphone2.getId(); + + //when + mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse(); + + //then + assertThat(receipt2.getStatus()).isEqualTo(ItemStatus.DELETED); + } + + @Test + @Transactional + @DisplayName("[GET] /pingpong/megaphones/receipt/{receiptId}") + void getMegaphoneDetailTest() throws Exception { + String intraId = "intra"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + String accessToken = tokenProvider.createToken(newUser.getId()); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", + "default", 40, 50, ItemType.MEGAPHONE); + Item item = itemTestUtils.createItem(newUser, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + Megaphone megaphone = itemTestUtils.createMegaPhone(newUser, receipt, "test"); + String url = "/pingpong/megaphones/receipt/" + receipt.getId(); + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @Transactional + @DisplayName("[GET] /pingpong/megaphones") + void getMegaphoneTodayListTest() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + String url = "/pingpong/megaphones"; + mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/service/MegaphoneServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/service/MegaphoneServiceUnitTest.java new file mode 100644 index 000000000..1dd4dce0d --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/megaphone/service/MegaphoneServiceUnitTest.java @@ -0,0 +1,366 @@ +package gg.pingpong.api.user.megaphone.service; + +import static gg.pingpong.api.utils.ReflectionUtilsForUnitTest.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.store.Item; +import gg.data.store.Megaphone; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.store.controller.request.MegaphoneUseRequestDto; +import gg.pingpong.api.user.store.redis.MegaphoneRedisRepository; +import gg.pingpong.api.user.store.service.ItemService; +import gg.pingpong.api.user.store.service.MegaphoneService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.store.MegaphoneRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.megaphone.MegaphoneContentException; +import gg.utils.exception.megaphone.MegaphoneNotFoundException; +import gg.utils.exception.megaphone.MegaphoneTimeException; +import gg.utils.exception.receipt.ItemStatusException; +import gg.utils.exception.receipt.ReceiptNotFoundException; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class MegaphoneServiceUnitTest { + @Mock + UserRepository userRepository; + @Mock + ReceiptRepository receiptRepository; + @Mock + MegaphoneRepository megaphoneRepository; + @Mock + MegaphoneRedisRepository megaphoneRedisRepository; + @Mock + ItemService itemService; + @InjectMocks + MegaphoneService megaphoneService; + + User user; + Receipt receipt; + Item item; + + @BeforeEach + void beforeEach() { + user = new User("", "", "", RacketType.NONE, RoleType.USER, + 0, SnsType.NONE, 1L); + setFieldWithReflection(user, "id", 1L); + item = new Item(); + receipt = new Receipt(item, "", "testUser", ItemStatus.BEFORE, LocalDateTime.now()); + } + + @Nested + @DisplayName("useMegaphone ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class UseMegaphoneUnitTest { + MegaphoneUseRequestDto megaphoneUseRequestDto; + + @BeforeEach + void beforeEach() { + setFieldWithReflection(item, "type", ItemType.MEGAPHONE); + megaphoneUseRequestDto = new MegaphoneUseRequestDto(1L, "test"); + } + + @Test + @DisplayName("success") + void success() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.of(receipt)); + given(megaphoneRepository.save(any(Megaphone.class))).willReturn(mock(Megaphone.class)); + // when + megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(23).withMinute(54)); + setFieldWithReflection(receipt, "status", ItemStatus.BEFORE); + megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(0).withMinute(6)); + // then + assertThat(receipt.getStatus()).isEqualTo(ItemStatus.WAITING); + verify(userRepository, times(2)).findById(any(Long.class)); + verify(receiptRepository, times(2)).findById(any(Long.class)); + verify(itemService, times(2)).checkItemType(any(), any()); + verify(itemService, times(2)).checkItemOwner(any(), any()); + verify(megaphoneRepository, times(2)).save(any(Megaphone.class)); + } + + @Test + @DisplayName("MegaphoneContentException") + void megaphoneContentException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.of(receipt)); + setFieldWithReflection(megaphoneUseRequestDto, "content", ""); + // when, then + Assertions.assertThatThrownBy(() -> megaphoneService.useMegaphone( + megaphoneUseRequestDto, UserDto.from(user), LocalTime.now().withHour(23).withMinute(54))) + .isInstanceOf(MegaphoneContentException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + verify(itemService, times(1)).checkItemType(any(), any()); + verify(itemService, times(1)).checkItemOwner(any(), any()); + } + + @Test + @DisplayName("ItemStatusException") + void itemStatusException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.of(receipt)); + setFieldWithReflection(receipt, "status", ItemStatus.USING); + // when, then + Assertions.assertThatThrownBy( + () -> megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(23).withMinute(54))).isInstanceOf(ItemStatusException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + verify(itemService, times(1)).checkItemType(any(), any()); + verify(itemService, times(1)).checkItemOwner(any(), any()); + } + + @Test + @DisplayName("ReceiptNotFoundException") + void receiptNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + Assertions.assertThatThrownBy( + () -> megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(23).withMinute(54))).isInstanceOf(ReceiptNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("MegaphoneTimeException") + void megaphoneTimeException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + // when, then + Assertions.assertThatThrownBy( + () -> megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(23).withMinute(56))).isInstanceOf(MegaphoneTimeException.class); + Assertions.assertThatThrownBy( + () -> megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(0).withMinute(3))).isInstanceOf(MegaphoneTimeException.class); + verify(userRepository, times(2)).findById(any(Long.class)); + } + + @Test + @DisplayName("UserNotFoundException") + void userNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + Assertions.assertThatThrownBy( + () -> megaphoneService.useMegaphone(megaphoneUseRequestDto, UserDto.from(user), + LocalTime.now().withHour(23).withMinute(56))).isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("setMegaphoneList ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class SetMegaphoneListUnitTest { + List usingList = new ArrayList<>(); + List waitList = new ArrayList<>(); + + @BeforeEach + void beforeEach() { + waitList.add(new Megaphone(user, receipt, "test", LocalDate.now().plusDays(1))); + Receipt receiptUsing = new Receipt(item, "", "testUser", + ItemStatus.USING, LocalDateTime.now()); + usingList.add(new Megaphone(user, receiptUsing, "test", LocalDate.now())); + } + + @Test + @DisplayName("success") + void success() { + // given + given(megaphoneRepository.findAllByUsedAtAndReceiptStatus(LocalDate.now(), ItemStatus.USING)) + .willReturn(usingList); + given(megaphoneRepository.findAllByUsedAtAndReceiptStatus( + LocalDate.now().plusDays(1), ItemStatus.WAITING)) + .willReturn(waitList); + // when, then + megaphoneService.setMegaphoneList(LocalDate.now()); + assertThat(usingList.get(0).getReceipt().getStatus()).isEqualTo(ItemStatus.USED); + assertThat(waitList.get(0).getReceipt().getStatus()).isEqualTo(ItemStatus.USING); + verify(megaphoneRepository, times(1)) + .findAllByUsedAtAndReceiptStatus(LocalDate.now(), ItemStatus.USING); + verify(megaphoneRedisRepository, times(1)).deleteAllMegaphone(); + verify(megaphoneRepository, times(1)) + .findAllByUsedAtAndReceiptStatus(LocalDate.now().plusDays(1), ItemStatus.WAITING); + verify(megaphoneRedisRepository, times(waitList.size())).addMegaphone(any()); + } + } + + @Nested + @DisplayName("deleteMegaphone ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class DeleteMegaphoneUnitTest { + Megaphone megaphone; + + @BeforeEach + void beforeEach() { + megaphone = new Megaphone(user, receipt, "test", LocalDate.now()); + } + + @Test + @DisplayName("success") + void success() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(megaphoneRepository.findById(any(Long.class))).willReturn(Optional.of(megaphone)); + // when deleted by user + megaphoneService.deleteMegaphone(1L, UserDto.from(user)); + // when deleted by admin, using megaphone + setFieldWithReflection(user, "roleType", RoleType.ADMIN); + megaphoneService.deleteMegaphone(1L, UserDto.from(user)); + // when deleting using megaphone + setFieldWithReflection(receipt, "status", ItemStatus.USING); + megaphoneService.deleteMegaphone(1L, UserDto.from(user)); + // then + assertThat(receipt.getStatus()).isEqualTo(ItemStatus.DELETED); + verify(userRepository, times(3)).findById(any(Long.class)); + verify(megaphoneRepository, times(3)).findById(any(Long.class)); + verify(itemService, times(1)).checkItemOwner(any(), any()); + verify(itemService, times(3)).checkItemStatus(any()); + verify(megaphoneRedisRepository, times(1)).deleteMegaphoneById(any()); + } + + @Test + @DisplayName("MegaphoneNotFoundException") + void megaphoneNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(megaphoneRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> megaphoneService.deleteMegaphone(1L, UserDto.from(user))) + .isInstanceOf(MegaphoneNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(megaphoneRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("UserNotFoundException") + void userNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> megaphoneService.deleteMegaphone(1L, UserDto.from(user))) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("getMegaphoneDetail ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetMegaphoneDetailUnitTest { + Megaphone megaphone; + + @BeforeEach + void beforeEach() { + megaphone = new Megaphone(user, receipt, "test", LocalDate.now()); + } + + @Test + @DisplayName("success") + void success() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.of(receipt)); + given(megaphoneRepository.findByReceipt(any(Receipt.class))).willReturn(Optional.of(megaphone)); + // when, then + megaphoneService.getMegaphoneDetail(1L, UserDto.from(user)); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + verify(itemService, times(1)).checkItemType(any(), any()); + verify(itemService, times(1)).checkItemOwner(any(), any()); + verify(itemService, times(1)).checkItemStatus(any()); + verify(megaphoneRepository, times(1)).findByReceipt(any(Receipt.class)); + + } + + @Test + @DisplayName("MegaphoneNotFoundException") + void megaphoneNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.of(receipt)); + given(megaphoneRepository.findByReceipt(any(Receipt.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> megaphoneService.getMegaphoneDetail(1L, UserDto.from(user))) + .isInstanceOf(MegaphoneNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + verify(itemService, times(1)).checkItemType(any(), any()); + verify(itemService, times(1)).checkItemOwner(any(), any()); + verify(itemService, times(1)).checkItemStatus(any()); + verify(megaphoneRepository, times(1)).findByReceipt(any(Receipt.class)); + } + + @Test + @DisplayName("ReceiptNotFoundException") + void receiptNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(user)); + given(receiptRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> megaphoneService.getMegaphoneDetail(1L, UserDto.from(user))) + .isInstanceOf(ReceiptNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(receiptRepository, times(1)).findById(any(Long.class)); + } + + @Test + @DisplayName("UserNotFoundException") + void userNotFoundException() { + // given + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + // when, then + assertThatThrownBy(() -> megaphoneService.getMegaphoneDetail(1L, UserDto.from(user))) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + } + } + + @Nested + @DisplayName("getMegaphoneTodayList ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetMegaphoneTodayListUnitTest { + @Test + @DisplayName("success") + void success() { + // given + given(megaphoneRedisRepository.getAllMegaphone()).willReturn(new ArrayList<>()); + // when, then + megaphoneService.getMegaphoneTodayList(); + verify(megaphoneRedisRepository, times(1)).getAllMegaphone(); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/controller/NotiControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/controller/NotiControllerTest.java new file mode 100644 index 000000000..b6f3c805a --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/controller/NotiControllerTest.java @@ -0,0 +1,126 @@ +package gg.pingpong.api.user.noti.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.noti.controller.response.NotiListResponseDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.noti.NotiRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +class NotiControllerTest { + + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + UserRepository userRepository; + @Autowired + NotiRepository notiRepository; + @Autowired + private NotiService notiService; + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("GET /pingpong/notifications") + @Transactional + public void notiFindByUserTest() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications"; + + UserDto userDto = UserDto.from(userRepository.getById(userId)); + NotiListResponseDto expectedResponse = new NotiListResponseDto(notiService.findNotiByUser(userDto)); + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + NotiListResponseDto actureResponse = objectMapper.readValue(contentAsString, NotiListResponseDto.class); + + //then + assertThat(actureResponse).isEqualTo(expectedResponse); + } + + @Test + @DisplayName("PUT /pingpong/notifications/check") + @Transactional + public void checkNotiByUserTest() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications/check"; + User user = userRepository.findById(userId).get(); + + notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); + notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); + notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); + //when + String contentAsString = mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + List notiList = notiRepository.findByUser(user); + for (Noti noti : notiList) { + assertThat(noti.getIsChecked()).isTrue(); + } + } + + @Test + @DisplayName("DELETE /notifications") + @Transactional + public void notiRemoveAll() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/notifications"; + User user = userRepository.findById(userId).get(); + + notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); + notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); + notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); + notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); + + //when + String contentAsString = mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + List notiList = notiRepository.findByUser(user); + assertThat(notiList.size()).isEqualTo(0); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceTest.java new file mode 100644 index 000000000..0a4fbbeb8 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceTest.java @@ -0,0 +1,74 @@ +package gg.pingpong.api.user.noti.service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +import javax.transaction.Transactional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.noti.NotiRepository; +import gg.repo.user.UserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RequiredArgsConstructor +@IntegrationTest +@Slf4j +class NotiServiceTest { + + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + NotiService notiService; + @Autowired + NotiRepository notiRepository; + @Autowired + UserRepository userRepository; + + @Test + @DisplayName("NotiService ์œ ์ €๋งค์นญ์•Œ๋ฆผ ์ „์†ก ํ…Œ์ŠคํŠธ") + @Transactional + public void userMatingNotSend() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + UserDto userDto = UserDto.from(user); + LocalDateTime now = LocalDateTime.now(); + String expectedMatchedNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; + String expectedMatchCancelNotiMessage = + now.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์ƒ๋Œ€์— ์˜ํ•ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; + + //when + notiService.createMatched(user, now); + notiService.createMatchCancel(user, now); + List actureNotiList = notiRepository.findAllByUser(user); + + //then + Assertions.assertThat(actureNotiList.size()).isEqualTo(2); + for (Noti noti : actureNotiList) { + if (noti.getType() == NotiType.MATCHED) { + Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchedNotiMessage); + log.info("Matched Message : " + noti.getMessage()); + } else if (noti.getType() == NotiType.CANCELEDBYMAN) { + Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchCancelNotiMessage); + log.info("MatchCancel Message : " + noti.getMessage()); + } + Assertions.assertThat(noti.getIsChecked()).isFalse(); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceUnitTest.java new file mode 100644 index 000000000..c498b707f --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/NotiServiceUnitTest.java @@ -0,0 +1,326 @@ +package gg.pingpong.api.user.noti.service; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.noti.NotiRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.custom.NotExistException; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("NotiServiceUnitTest") +class NotiServiceUnitTest { + @Mock + NotiRepository notiRepository; + @Mock + UserRepository userRepository; + @InjectMocks + NotiService notiService; + + @Nested + @DisplayName("findNotiByUser ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class FindNotiByUserTest { + @Test + @DisplayName("success") + void success() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + User user = new User("username", "email@example.com", "password", RacketType.NONE, + RoleType.USER, 0, SnsType.NONE, userId); + when(userRepository.findById(userId)).thenReturn(Optional.of(user)); + when(notiRepository.findAllByUserOrderByIdDesc(user)).thenReturn(List.of(new Noti())); + //when + notiService.findNotiByUser(userDto); + //then + verify(userRepository, times(1)).findById(userId); + verify(notiRepository, times(1)).findAllByUserOrderByIdDesc(user); + } + + @Test + @DisplayName("userNotFoundException") + void userNotFoundException() { + //given + UserDto userDto = mock(UserDto.class); + when(userRepository.findById(any(Long.class))).thenReturn(Optional.empty()); + //when, then + assertThatThrownBy(() -> notiService.findNotiByUser(userDto)) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, never()).findAllByUserOrderByIdDesc(any(User.class)); + + } + } + + @Nested + @DisplayName("findNotiByIdAndUser ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class FindNotiByIdAndUserTest { + @Test + @DisplayName("success") + void success() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + given(userRepository.findById(any(long.class))).willReturn(Optional.of(mock(User.class))); + given(notiRepository.findByIdAndUser(any(Long.class), any(User.class))).willReturn( + Optional.of(mock(Noti.class))); + //when + notiService.findNotiByIdAndUser(userDto, 1L); + //then + verify(userRepository, times(1)).findById(userId); + verify(notiRepository, times(1)).findByIdAndUser(any(Long.class), any(User.class)); + } + + @Test + @DisplayName("userNotFoundException") + void userNotFoundException() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + given(userRepository.findById(any(long.class))).willReturn(Optional.empty()); + //when, then + assertThatThrownBy(() -> notiService.findNotiByIdAndUser(userDto, 1L)) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, never()).findByIdAndUser(any(Long.class), any(User.class)); + } + + @Test + @DisplayName("notExistException") + void notExistException() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + User user = new User("username", "email@example.com", "password", RacketType.NONE, RoleType.USER, + 0, SnsType.NONE, userId); + given(userRepository.findById(any(long.class))).willReturn(Optional.of(mock(User.class))); + given(notiRepository.findByIdAndUser(any(Long.class), any(User.class))).willReturn(Optional.empty()); + //when, then + assertThatThrownBy(() -> notiService.findNotiByIdAndUser(userDto, 1L)) + .isInstanceOf(NotExistException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, times(1)).findByIdAndUser(any(Long.class), any(User.class)); + } + } + + @Nested + @DisplayName("modifyNotiCheckedByUser ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class ModifyNotiCheckedByUserTest { + @Test + @DisplayName("success") + void success() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + User user = new User("username", "email@example.com", "password", + RacketType.NONE, RoleType.USER, 0, SnsType.NONE, userId); + List notis = List.of(new Noti()); + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(mock(User.class))); + given(notiRepository.findAllByUser(any(User.class))).willReturn(notis); + //when + notiService.modifyNotiCheckedByUser(userDto); + //then + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, times(1)).findAllByUser(any(User.class)); + } + + @Test + @DisplayName("userNotFoundException") + void userNotFoundException() { + //given + Long userId = 1L; + UserDto userDto = mock(UserDto.class); + when(userDto.getId()).thenReturn(userId); + given(userRepository.findById(any(long.class))).willReturn(Optional.empty()); + //when, then + assertThatThrownBy(() -> notiService.modifyNotiCheckedByUser(userDto)) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, never()).findAllByUser(any(User.class)); + } + } + + @Nested + @DisplayName("removeNotiById ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class RemoveNotiByIdTest { + @Test + @DisplayName("success") + void success() { + //when + notiService.removeNotiById(1L); + //then + verify(notiRepository, times(1)).deleteById(any(Long.class)); + } + } + + @Nested + @DisplayName("removeAllNotisByUser ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class RemoveAllNotisByUserTest { + @Test + @DisplayName("success") + void success() { + //given + given(userRepository.findById(any(Long.class))).willReturn(Optional.of(mock(User.class))); + //when + notiService.removeAllNotisByUser(mock(UserDto.class)); + //then + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, times(1)).deleteAllByUser(any(User.class)); + } + + @Test + @DisplayName("userNotFoundException") + void userNotFoundException() { + //given + given(userRepository.findById(any(Long.class))).willReturn(Optional.empty()); + //when, then + assertThatThrownBy(() -> notiService.removeAllNotisByUser(mock(UserDto.class))) + .isInstanceOf(UserNotFoundException.class); + verify(userRepository, times(1)).findById(any(Long.class)); + verify(notiRepository, never()).deleteAllByUser(any(User.class)); + } + } + + @Nested + @DisplayName("createMatched ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class CreateMatchedTest { + @Test + @DisplayName("success") + void success() { + //given + User user = mock(User.class); + LocalDateTime startTime = LocalDateTime.now(); + //when + Noti result = notiService.createMatched(user, startTime); + //then + verify(notiRepository, times(1)).save(any(Noti.class)); + assertThat(result.getUser()).isEqualTo(user); + assertThat(result.getType()).isEqualTo(NotiType.MATCHED); + assertThat(result.getMessage()).isEqualTo( + startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."); + assertThat(result.getIsChecked()).isEqualTo(false); + } + } + + @Nested + @DisplayName("createMatchCancel ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class CreateMatchCancelTest { + @Test + @DisplayName("success") + void success() { + //given + User user = mock(User.class); + LocalDateTime startTime = LocalDateTime.now(); + //when + Noti result = notiService.createMatchCancel(user, startTime); + //then + verify(notiRepository, times(1)).save(any(Noti.class)); + assertThat(result.getUser()).isEqualTo(user); + assertThat(result.getType()).isEqualTo(NotiType.CANCELEDBYMAN); + assertThat(result.getMessage()).isEqualTo( + startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์ƒ๋Œ€์— ์˜ํ•ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."); + assertThat(result.getIsChecked()).isEqualTo(false); + } + } + + @Nested + @DisplayName("createGiftNoti ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class CreateGiftNotiTest { + @Test + @DisplayName("success") + void success() { + //given + User ownerUser = mock(User.class); + User payUser = mock(User.class); + String itemName = "ํ…Œ์ŠคํŠธ ์•„์ดํ…œ"; + //when + Noti result = notiService.createGiftNoti(ownerUser, payUser, itemName); + //then + verify(notiRepository, times(1)).save(any(Noti.class)); + assertThat(result.getType()).isEqualTo(NotiType.GIFT); + assertThat(result.getMessage()).isEqualTo( + "เฌ˜(เฉญหŠแต•ห‹)เฉญ* เฉˆโœฉ " + payUser.getIntraId() + "๋‹˜์—๊ฒŒ " + itemName + " ์•„์ดํ…œ์„ ์„ ๋ฌผ๋ฐ›์•˜์–ด์š”!"); + assertThat(result.getIsChecked()).isEqualTo(false); + } + } + + @Nested + @DisplayName("createImminentNoti ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class CreateImminentNotiTest { + @Test + @DisplayName("success") + void success() { + //given + String enemyIntra = "testEnemyIntra"; + NotiType notiType = NotiType.IMMINENT; + Integer gameOpenMinute = 15; + given(notiRepository.save(any(Noti.class))).willReturn(mock(Noti.class)); + //when + Noti result = notiService.createImminentNoti(mock(User.class), enemyIntra, notiType, gameOpenMinute); + //then + verify(notiRepository, times(1)).save(any(Noti.class)); + assertThat(result).isNotNull(); + } + } + + // @MockitoSettings(strictness = Strictness.LENIENT) + @Nested + @DisplayName("getMessage ๋ฉ”์„œ๋“œ ํ…Œ์ŠคํŠธ") + class GetMessageTest { + @Test + @DisplayName("๊ณต์ง€์‚ฌํ•ญ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€") + void announce() { + //given + Noti noti = mock(Noti.class); + when(noti.getType()).thenReturn(NotiType.ANNOUNCE); + when(noti.getMessage()).thenReturn("testMessage"); + //when + String message = notiService.getMessage(noti); + //then + assertThat(message).contains("์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘", "testMessage", "๊ณต์ง€์‚ฌํ•ญ", "42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ", + "$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"); + } + + @Test + @DisplayName("๊ณต์ง€์‚ฌํ•ญ ์™ธ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€") + void nonannounce() { + //given + Noti noti = mock(Noti.class); + when(noti.getType()).thenReturn(NotiType.MATCHED); + //when + String message = notiService.getMessage(noti); + //then + assertThat(message).doesNotContain("๊ณต์ง€์‚ฌํ•ญ"); + assertThat(message).contains("์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘", "42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ", + "$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/SnsNotiServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/SnsNotiServiceUnitTest.java new file mode 100644 index 000000000..bb49f754d --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/SnsNotiServiceUnitTest.java @@ -0,0 +1,107 @@ +package gg.pingpong.api.user.noti.service; + +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.noti.Noti; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.sns.NotiMailSender; +import gg.pingpong.api.user.noti.service.sns.SlackbotService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.out.GameUser; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("SnsNotiServiceTest") +class SnsNotiServiceUnitTest { + @Mock + NotiMailSender notiMailSender; + @Mock + SlackbotService slackbotService; + @InjectMocks + SnsNotiService snsNotiService; + + @Nested + @DisplayName("sendSnsNotification ๋ฉ”์„œ๋“œ Test") + class SendSnsNotificationTest { + @Test + @DisplayName("Email") + void sendSnsNotificationWithEmail() { + //given + Noti noti = new Noti(); + UserDto userDto = mock(UserDto.class); + when(userDto.getSnsNotiOpt()).thenReturn(SnsType.EMAIL); + //when + snsNotiService.sendSnsNotification(noti, userDto); + //then + verify(slackbotService, never()).send(any(UserDto.class), any(Noti.class)); + verify(notiMailSender, times(1)).send(any(UserDto.class), any(Noti.class)); + } + + @Test + @DisplayName("Slack") + void sendSnsNotificationWithSlack() { + //given + Noti noti = new Noti(); + UserDto userDto = mock(UserDto.class); + when(userDto.getSnsNotiOpt()).thenReturn(SnsType.SLACK); + //when + snsNotiService.sendSnsNotification(noti, userDto); + //then + verify(notiMailSender, never()).send(any(UserDto.class), any(Noti.class)); + verify(slackbotService, times(1)).send(any(UserDto.class), any(Noti.class)); + } + + @Test + @DisplayName("Both") + void sendSnsNotificationWithBoth() { + //given + Noti noti = new Noti(); + UserDto userDto = mock(UserDto.class); + when(userDto.getSnsNotiOpt()).thenReturn(SnsType.BOTH); + //when + snsNotiService.sendSnsNotification(noti, userDto); + //then + verify(notiMailSender, times(1)).send(any(UserDto.class), any(Noti.class)); + verify(slackbotService, times(1)).send(any(UserDto.class), any(Noti.class)); + } + + @Test + @DisplayName("None") + void sendSnsNotificationWithNone() { + //given + Noti noti = new Noti(); + UserDto userDto = mock(UserDto.class); + when(userDto.getSnsNotiOpt()).thenReturn(SnsType.NONE); + //when + snsNotiService.sendSnsNotification(noti, userDto); + //then + verify(notiMailSender, never()).send(any(UserDto.class), any(Noti.class)); + verify(slackbotService, never()).send(any(UserDto.class), any(Noti.class)); + } + + @Test + @DisplayName("sendSnsNotificationWithUserNotiDto") + void sendSnsNotificationWithUserNotiDto() { + //given + Noti noti = new Noti(); + GameUser gameUser = mock(GameUser.class); + when(gameUser.getSnsNotiOpt()).thenReturn(SnsType.EMAIL); + UserNotiDto user = new UserNotiDto(gameUser); + //when + snsNotiService.sendSnsNotification(noti, user); + //then + verify(notiMailSender, times(1)).send(user, noti); + verify(slackbotService, never()).send(any(UserNotiDto.class), any(Noti.class)); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/sns/NotiMailSenderUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/sns/NotiMailSenderUnitTest.java new file mode 100644 index 000000000..4161564b2 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/noti/service/sns/NotiMailSenderUnitTest.java @@ -0,0 +1,67 @@ +package gg.pingpong.api.user.noti.service.sns; + +import static org.mockito.Mockito.*; + +import javax.mail.internet.MimeMessage; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mail.javamail.JavaMailSender; + +import gg.data.noti.Noti; +import gg.pingpong.api.global.utils.AsyncMailSender; +import gg.pingpong.api.user.noti.dto.UserNotiDto; +import gg.pingpong.api.user.noti.service.NotiService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.game.out.GameUser; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +@DisplayName("NotiMailSenderUnitTest") +class NotiMailSenderUnitTest { + @Mock + JavaMailSender javaMailSender; + @Mock + AsyncMailSender asyncMailSender; + @Mock + NotiService notiService; + @InjectMocks + NotiMailSender notiMailSender; + + @Test + @DisplayName("UserNotiDto๋ฅผ ์ด์šฉํ•˜์—ฌ ์œ ์ € ์ด๋ฉ”์ผ๋กœ ๋ฉ”์ผ ๋ณด๋‚ด๊ธฐ") + void sendToUserEmailByUserNotiDto() { + // given + GameUser gameUser = mock(GameUser.class); + MimeMessage mimeMessage = mock(MimeMessage.class); + when(gameUser.getEmail()).thenReturn("testEmail"); + when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage); + when(notiService.getMessage(any(Noti.class))).thenReturn("Test message"); + // when + notiMailSender.send(new UserNotiDto(gameUser), new Noti()); + // then + verify(javaMailSender).createMimeMessage(); + verify(asyncMailSender).send(mimeMessage); + } + + @Test + @DisplayName("UserDto๋ฅผ ์ด์šฉํ•˜์—ฌ ์œ ์ € ์ด๋ฉ”์ผ๋กœ ๋ฉ”์ผ ๋ณด๋‚ด๊ธฐ") + void sendToUserEmailByUserDto() { + // given + UserDto userDto = mock(UserDto.class); + MimeMessage mimeMessage = mock(MimeMessage.class); + when(userDto.getEMail()).thenReturn("testEmail"); + when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage); + when(notiService.getMessage(any(Noti.class))).thenReturn("Test message"); + // when + notiMailSender.send(userDto, new Noti()); + // then + verify(javaMailSender).createMimeMessage(); + verify(asyncMailSender).send(mimeMessage); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/pchange/service/PChangeServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/pchange/service/PChangeServiceTest.java new file mode 100644 index 000000000..b396d297e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/pchange/service/PChangeServiceTest.java @@ -0,0 +1,140 @@ +package gg.pingpong.api.user.pchange.service; + +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.user.game.service.PChangeService; +import gg.pingpong.api.utils.ReflectionUtilsForUnitTest; +import gg.repo.game.PChangeRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.pchange.PChangeNotExistException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class PChangeServiceTest { + @Mock + private PChangeRepository pChangeRepository; + + @InjectMocks + private PChangeService pChangeService; + + @Test + @DisplayName("addPChange Success Test") + public void testAddPChange() { + Game game = new Game(); + User user = new User("intra", "email", "image", RacketType.PENHOLDER, + RoleType.USER, 1000, SnsType.NONE, 4242L); + Integer pppResult = 42; + Boolean isChecked = true; + + // given + PChange pchange = new PChange(game, user, 4242, true); + given(pChangeRepository.save(any(PChange.class))).willReturn(pchange); + + // when + pChangeService.addPChange(game, user, pppResult, isChecked); + + // then + verify(pChangeRepository, times(1)).save(any(PChange.class)); + } + + @Nested + @DisplayName("FindExpChangeHistory Test") + class TestFindExpChangeHistory { + + @Test + @DisplayName("์„ฑ๊ณต") + public void successFindExpChangeHistory() { + PChange pChange = new PChange(); + ReflectionUtilsForUnitTest.setFieldWithReflection(pChange, "game", mock(Game.class)); + ReflectionUtilsForUnitTest.setFieldWithReflection(pChange, "user", mock(User.class)); + + // given + List lst = new ArrayList<>(); + lst.add(pChange); + when(pChangeRepository.findExpHistory(any(Long.class), any(Long.class))).thenReturn(lst); + + // when + pChangeService.findExpChangeHistory(1L, 1L); + + // then + verify(pChangeRepository, times(1)).findExpHistory(1L, 1L); + } + + @Test + @DisplayName("์‹คํŒจ : nowExistGameId") + public void pchangeNotExistExceptionTest() { + Long gameId = 1L; + Long userId = 1L; + + // given + when(pChangeRepository.findExpHistory(userId, gameId)).thenReturn(new ArrayList<>()); + + // when, then + assertThrows(PChangeNotExistException.class, () -> pChangeService.findExpChangeHistory(gameId, userId)); + + } + + } + + @Nested + @DisplayName("FindPPPChangeHistory Test") + class TestFindPPPChangeHistory { + + @Test + @DisplayName("์„ฑ๊ณต") + public void success() { + Long gameId = 1L; + Long userId = 1L; + Long seasonId = 1L; + + PChange pChange = new PChange(); + ReflectionUtilsForUnitTest.setFieldWithReflection(pChange, "game", mock(Game.class)); + ReflectionUtilsForUnitTest.setFieldWithReflection(pChange, "user", mock(User.class)); + + List pChangeList = new ArrayList<>(); + pChangeList.add(pChange); + // given + when(pChangeRepository.findPPPHistory(userId, gameId, seasonId)).thenReturn(pChangeList); + + // when + pChangeService.findPPPChangeHistory(gameId, userId, seasonId); + + // then + verify(pChangeRepository, times(1)).findPPPHistory(userId, gameId, seasonId); + } + + @Test + @DisplayName("์‹คํŒจ : notExist") + public void notExist() { + Long gameId = 1L; + Long userId = 1L; + Long seasonId = 1L; + + // given + when(pChangeRepository.findPPPHistory(userId, gameId, seasonId)).thenReturn(new ArrayList<>()); + + // when, then + assertThrows(PChangeNotExistException.class, () -> { + pChangeService.findPPPChangeHistory(gameId, userId, seasonId); + }); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankControllerTest.java new file mode 100644 index 000000000..99e9e8e6d --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankControllerTest.java @@ -0,0 +1,165 @@ +package gg.pingpong.api.user.rank.controller; + +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.Comparator; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.rank.dto.RankDto; +import gg.pingpong.api.user.rank.redis.RedisUploadService; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@Transactional +@AutoConfigureMockMvc +class RankControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + SeasonRepository seasonRepository; + + @Autowired + RankRedisRepository redisRepository; + + @Autowired + RedisUploadService redisUploadService; + + @BeforeEach + public void flushRedis() { + redisRepository.deleteAll(); + testDataUtils.createTierSystem("pingpong"); + } + + @AfterEach + public void flushRedisAfter() { + redisRepository.deleteAll(); + } + + @Test + @DisplayName("/exp") + void getExpRankPage() throws Exception { + + // given + Season season = testDataUtils.createSeason(); + int myTotalExp = 1000; + User myUser = testDataUtils.createNewUser(myTotalExp); + testDataUtils.createUserRank(myUser, "1", season); + + int otherTotalExp = 2000; + User user1 = testDataUtils.createNewUser(otherTotalExp); + testDataUtils.createUserRank(user1, "2", season); + int otherTotalExp2 = 3000; + User user2 = testDataUtils.createNewUser(otherTotalExp2); + testDataUtils.createUserRank(user2, "3", season); + int otherTotalExp3 = 4000; + User user3 = testDataUtils.createNewUser(otherTotalExp3); + testDataUtils.createUserRank(user3, "4", season); + + int page = 1; + int size = 3; + String url = "/pingpong/exp?page=" + page + "&size=" + size; + String accessToken = tokenProvider.createToken(myUser.getId()); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + ExpRankPageResponseDto response = objectMapper.readValue(contentAsString, ExpRankPageResponseDto.class); + + //then + Assertions.assertThat(response.getMyRank()).isEqualTo(4); + Assertions.assertThat(response.getCurrentPage()).isEqualTo(page); + Assertions.assertThat(response.getTotalPage()).isEqualTo(2); + Assertions.assertThat(response.getRankList().size()).isEqualTo(3); + } + + @Test + @DisplayName("/pingpong/ranks/{gameType}") + public void getRankPage() throws Exception { + //given + Season season = testDataUtils.createSeason(); + User myUser = testDataUtils.createNewUser(); + testDataUtils.createUserRank(myUser, "1", season, 1000); + + User user2 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user2, "2", season, 1500); + + User user3 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user3, "3", season, 2000); + + User user4 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user4, "4", season, 2500); + + User user5 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user5, "5", season, 3000); + + User user6 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user6, "6", season, 3500); + + User user7 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user7, "7", season, 4000); + + User user8 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user8, "8", season, 4500); + + User user9 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user9, "9", season, 5000); + + User user10 = testDataUtils.createNewUser(); + testDataUtils.createUserRank(user10, "10", season, 5500); + + String accessToken = tokenProvider.createToken(myUser.getId()); + + int page = 4; + int size = 3; + String url = "/pingpong/ranks/single?page=" + page + "&size=" + size; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + RankPageResponseDto resp = objectMapper.readValue(contentAsString, RankPageResponseDto.class); + + //then + List rankList = resp.getRankList(); + Assertions.assertThat(resp.getCurrentPage()).isEqualTo(4); + Assertions.assertThat(resp.getTotalPage()).isEqualTo(4); + Assertions.assertThat(resp.getMyRank()).isEqualTo(10); + Assertions.assertThat(rankList.size()).isEqualTo(1); + Assertions.assertThat(rankList).isSortedAccordingTo(Comparator.comparing(RankDto::getPpp).reversed()); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankV2ControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankV2ControllerTest.java new file mode 100644 index 000000000..01f676b0a --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/controller/RankV2ControllerTest.java @@ -0,0 +1,96 @@ +package gg.pingpong.api.user.rank.controller; + +import static org.mockito.BDDMockito.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.ArrayList; +import java.util.Optional; + +import org.junit.jupiter.api.Test; +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.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.data.domain.PageRequest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; + +import gg.data.user.User; +import gg.pingpong.api.global.config.WebConfig; +import gg.pingpong.api.global.security.config.SecurityConfig; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.security.jwt.utils.TokenAuthenticationFilter; +import gg.pingpong.api.global.utils.querytracker.LoggingInterceptor; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.rank.service.RankService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.user.UserRepository; + +@WebMvcTest(value = RankV2Controller.class, + excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = WebConfig.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TokenAuthenticationFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = LoggingInterceptor.class) + } +) +@ExtendWith(MockitoExtension.class) +class RankV2ControllerTest { + + @Autowired + private MockMvc mockMvc; + @MockBean + private RankService rankService; + @MockBean + private UserRepository userRepository; + @MockBean + private AuthTokenProvider authTokenProvider; + + @Test + @WithMockUser(username = "TestUser") + void getExpRankPage() throws Exception { + given(userRepository.findById(0L)) + .willReturn(Optional.of(User.builder().intraId("TestUser").build())); + given(rankService.getExpRankPage(PageRequest.of(1, 10), + UserDto + .builder() + .intraId("TestUser") + .id(1L) + .build()) + ).willReturn(new ExpRankPageResponseDto( + -1, + 1, + 1, + new ArrayList<>() + )); + mockMvc.perform(get("/pingpong/v2/exp") + .queryParam("size", "10") + .queryParam("page", "1")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser(username = "TestUser") + void getRankPage() throws Exception { + given(userRepository.findById(0L)) + .willReturn(Optional.of(User.builder().intraId("TestUser").build())); + given(rankService.getRankPageV2(PageRequest.of(1, 10), + UserDto + .builder() + .intraId("TestUser") + .id(1L) + .build(), 1L) + ).willReturn(new RankPageResponseDto(-1, 1, 1, new ArrayList<>())); + mockMvc.perform(get("/pingpong/v2/ranks/single") + .queryParam("size", "10") + .queryParam("page", "1") + .queryParam("season", "1")) + .andExpect(status().isOk()); + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RankRedisRepositoryTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RankRedisRepositoryTest.java new file mode 100644 index 000000000..c048a5f26 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RankRedisRepositoryTest.java @@ -0,0 +1,279 @@ +package gg.pingpong.api.user.rank.redis; + +import java.util.List; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import gg.data.rank.redis.RankRedis; +import gg.repo.rank.redis.RankRedisRepository; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.rank.RedisDataNotFoundException; + +@IntegrationTest +class RankRedisRepositoryTest { + + @Autowired + RankRedisRepository redisRepository; + + static String zSetKey = "test:ZSet"; + static String hashKey = "test:hash"; + + @AfterEach + void deleteAll() { + redisRepository.deleteZSetKey(zSetKey); + redisRepository.deleteHashKey(hashKey); + } + + @Test + void addToZSet() { + //given + Long userId = 1L; + int ppp = 100; + + //when + redisRepository.addToZSet(zSetKey, userId, ppp); + + //then + Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); + Assertions.assertThat(scoreInZSet).isEqualTo(ppp); + } + + @Test + void incrementScoreInZSet() { + //given + Long userId = 1L; + int ppp = 100; + int incrementPpp = 50; + redisRepository.addToZSet(zSetKey, userId, ppp); + + //when + redisRepository.incrementScoreInZSet(zSetKey, userId, incrementPpp); + + //then + Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); + Assertions.assertThat(scoreInZSet).isEqualTo(ppp + incrementPpp); + } + + @Test + void decrementScoreInZSet() { + //given + Long userId = 1L; + int ppp = 100; + int decrementPpp = 50; + redisRepository.addToZSet(zSetKey, userId, ppp); + + //when + redisRepository.decrementScoreInZSet(zSetKey, userId, decrementPpp); + + //then + Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); + Assertions.assertThat(scoreInZSet).isEqualTo(ppp - decrementPpp); + } + + @Test + void add() { + Long userId = 1L; + Long userId2 = 2L; + Long userId3 = 3L; + int ppp = 100; + int ppp2 = 200; + int ppp3 = 300; + redisRepository.addToZSet(zSetKey, userId, ppp); + redisRepository.addToZSet(zSetKey, userId2, ppp2); + redisRepository.addToZSet(zSetKey, userId3, ppp3); + } + + @Test + void getRankInZSet() { + // given + Long userId = 1L; + Long userId2 = 2L; + Long userId3 = 3L; + int ppp = 100; + int ppp2 = 200; + int ppp3 = 300; + redisRepository.addToZSet(zSetKey, userId, ppp); + redisRepository.addToZSet(zSetKey, userId2, ppp2); + redisRepository.addToZSet(zSetKey, userId3, ppp3); + + //when + Long rankInZSet = redisRepository.getRankInZSet(zSetKey, userId); + + //then + Assertions.assertThat(rankInZSet).isEqualTo(2); + } + + @Test + void getScoreInZSet() { + //given + Long userId = 1L; + int ppp = 100; + redisRepository.addToZSet(zSetKey, userId, ppp); + + //when + Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); + + //then + Assertions.assertThat(scoreInZSet).isEqualTo(ppp); + } + + @Test + public void getUserIdsByRange() throws Exception { + //given + Long userId = 1L; + Long userId2 = 2L; + Long userId3 = 3L; + int ppp = 100; + int ppp2 = 200; + int ppp3 = 300; + redisRepository.addToZSet(zSetKey, userId, ppp); + redisRepository.addToZSet(zSetKey, userId2, ppp2); + redisRepository.addToZSet(zSetKey, userId3, ppp3); + + //when + List userIdsSorted = redisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 1); + + //then + Assertions.assertThat(userIdsSorted).containsExactly(userId3, userId2); + Assertions.assertThat(userIdsSorted.get(0)).isEqualTo(userId3); + Assertions.assertThat(userIdsSorted.get(1)).isEqualTo(userId2); + } + + @Test + @DisplayName("ZSet์—์„œ ์œ ์ € ์‚ญ์ œ") + public void deleteZSetTest() throws Exception { + //given + Long userId = 1L; + int ppp = 100; + redisRepository.addToZSet(zSetKey, userId, ppp); + + //when + redisRepository.deleteFromZSet(zSetKey, userId); + + //then + Assertions.assertThatThrownBy(() -> { + redisRepository.getRankInZSet(zSetKey, userId); + }).isInstanceOf(RedisDataNotFoundException.class); + } + + @Test + @DisplayName("Redis์— ๋žญํ‚น ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€, ๊ฒ€์ƒ‰ํ•œ๋‹ค.") + public void rankCreateSearch() throws Exception { + //given + Long userId = 1L; + int ppp = 100; + int win = 3; + int lose = 4; + String statusMessage = "statusMessage"; + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, + "https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/hand.svg", "#000000"); + + //when + redisRepository.addRankData(hashKey, userId, ranking); + RankRedis findRanking = redisRepository.findRankByUserId(hashKey, userId); + + //then + Assertions.assertThat(findRanking.getUserId()).isEqualTo(userId); + Assertions.assertThat(findRanking.getPpp()).isEqualTo(ppp); + Assertions.assertThat(findRanking.getWins()).isEqualTo(win); + Assertions.assertThat(findRanking.getLosses()).isEqualTo(lose); + Assertions.assertThat(findRanking.getStatusMessage()).isEqualTo(statusMessage); + } + + @Test + @DisplayName("user rank์ •๋ณด ์—…๋ฐ์ดํŠธ") + public void updateRank() throws Exception { + //given + Long userId = 1L; + int ppp = 100; + int win = 3; + int lose = 4; + String statusMessage = "statusMessage"; + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + redisRepository.addRankData(hashKey, userId, ranking); + + //when + int newPpp = 200; + int newWin = 4; + int newLose = 5; + String newStatusMessage = "newStatusMessage"; + RankRedis newRanking = new RankRedis(userId, "aa", newPpp, newWin, newLose, newStatusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + + redisRepository.updateRankData(hashKey, userId, newRanking); + //then + RankRedis findRanking = redisRepository.findRankByUserId(hashKey, userId); + Assertions.assertThat(findRanking.getUserId()).isEqualTo(userId); + Assertions.assertThat(findRanking.getPpp()).isEqualTo(newPpp); + Assertions.assertThat(findRanking.getWins()).isEqualTo(newWin); + Assertions.assertThat(findRanking.getLosses()).isEqualTo(newLose); + Assertions.assertThat(findRanking.getStatusMessage()).isEqualTo(newStatusMessage); + } + + @Test + @DisplayName("์œ ์ € ๋žญํฌ๋ฅผ ์‚ญ์ œํ•œ๋‹ค") + public void deleteUserRank() throws Exception { + //given + Long userId = 3L; + int ppp = 100; + int win = 3; + int lose = 4; + String statusMessage = "statusMessage"; + RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + redisRepository.addRankData(hashKey, userId, ranking); + + //when + redisRepository.deleteRankData(hashKey, userId); + + //then + Assertions.assertThatThrownBy(() -> { + redisRepository.findRankByUserId(hashKey, userId); + }).isInstanceOf(RedisDataNotFoundException.class); + } + + @Test + void findRanksByUserIds() { + //given + Long userId = 1L; + Long userId2 = 2L; + Long userId3 = 3L; + Long userId4 = 4L; + int ppp = 100; + int ppp2 = 200; + int ppp3 = 300; + int ppp4 = 400; + + RankRedis rank1 = new RankRedis(userId, "aa", ppp, 0, 0, "statusMessage", + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank2 = new RankRedis(userId2, "aa", ppp2, 0, 0, "statusMessage", + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank3 = new RankRedis(userId3, "aa", ppp3, 0, 0, "statusMessage", + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + RankRedis rank4 = new RankRedis(userId4, "aa", ppp4, 0, 0, "statusMessage", + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); + redisRepository.addRankData(hashKey, userId, rank1); + redisRepository.addRankData(hashKey, userId2, rank2); + redisRepository.addRankData(hashKey, userId3, rank3); + redisRepository.addRankData(hashKey, userId4, rank4); + redisRepository.addToZSet(zSetKey, userId, ppp); + redisRepository.addToZSet(zSetKey, userId2, ppp2); + redisRepository.addToZSet(zSetKey, userId3, ppp3); + redisRepository.addToZSet(zSetKey, userId4, ppp4); + + //when + List sortedUserIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 3); + List ranks = redisRepository.findRanksByUserIds(hashKey, sortedUserIds); + + //then -> ๋žญํฌ ์ˆœ์„œ๋„ ์•Œ๋งž๊ฒŒ ๋ฐ˜ํ™˜๋˜๋Š”์ง€ ํ™•์ธ + Assertions.assertThat(ranks) + .usingElementComparatorIgnoringFields("userId") + .containsExactly(rank4, rank3, rank2, rank1); + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTestService.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTestService.java new file mode 100644 index 000000000..1341a67a3 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTestService.java @@ -0,0 +1,27 @@ +package gg.pingpong.api.user.rank.redis; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@Transactional +@RequiredArgsConstructor +public class RedisTestService { + private final RedisTemplate redisTemplate; + + public void addStringWithError(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + throw new RuntimeException(); + } + + public void addString(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + public Object getFromString(String key) { + return redisTemplate.opsForValue().get(key); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTransactionTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTransactionTest.java new file mode 100644 index 000000000..d1320a851 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/redis/RedisTransactionTest.java @@ -0,0 +1,74 @@ +package gg.pingpong.api.user.rank.redis; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.transaction.annotation.Transactional; + +import gg.utils.annotation.IntegrationTestWithRedisTransaction; + +@IntegrationTestWithRedisTransaction +public class RedisTransactionTest { + + @Autowired + RedisTestService redisTestService; + + @Autowired + RedisTemplate redisTemplate; + + @Test + @DisplayName("transaction์•ˆ์—์„œ exception์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ํ•ด๋‹น transaction์ด discord๋˜๋Š”์ง€ ํ™•์ธ") + public void rollbackTest() throws Exception { + String key = "hello"; + + Assertions.assertThatThrownBy(() -> { + redisTestService.addStringWithError(key, "aaa"); + }).isInstanceOf(RuntimeException.class); + + Object result = redisTemplate.opsForValue().get(key); + Assertions.assertThat(result).isNull(); + } + + @Test + @DisplayName("transaction์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ exec๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š”์ง€ ํ…Œ์ŠคํŠธ") + public void commitTest() throws Exception { + String key = "hello1"; + String value = "aaa"; + + redisTestService.addString(key, value); + + Object result = redisTemplate.opsForValue().get(key); + Assertions.assertThat(result).isNotNull(); + Assertions.assertThat(result.toString()).isEqualTo(value); + } + + @Test + @DisplayName("transaction์•ˆ์—์„œ ์ƒˆ๋กœ ์ง‘์–ด๋„ฃ์€ key์— ๋Œ€ํ•ด์„œ ์กฐํšŒ์‹œ null์กฐํšŒ test") + @Transactional + public void nullTest() throws Exception { + String key = "test"; + String value = "value"; + + redisTestService.addString(key, value); + + Object result = redisTestService.getFromString(key); + Assertions.assertThat(result).isNull(); + } + + @Test + @DisplayName("transaction์•ˆ์—์„œ ๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ key์— ๋Œ€ํ•ด์„œ ์กฐํšŒ์‹œ not null test") + public void nonNullTest() throws Exception { + String key = "test"; + String value = "value"; + + redisTestService.addString(key, value); + + Object result = redisTestService.getFromString(key); + Assertions.assertThat(result).isNotNull(); + Assertions.assertThat(result.toString()).isEqualTo(value); + } + +} + diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/service/RankServiceTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/service/RankServiceTest.java new file mode 100644 index 000000000..9e0afdb01 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/rank/service/RankServiceTest.java @@ -0,0 +1,176 @@ +package gg.pingpong.api.user.rank.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; + +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.rank.controller.response.ExpRankPageResponseDto; +import gg.pingpong.api.user.rank.controller.response.RankPageResponseDto; +import gg.pingpong.api.user.season.service.SeasonFindService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.repo.rank.RankRepository; +import gg.repo.rank.RankV2Dto; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.user.ExpRankV2Dto; +import gg.repo.user.UserRepository; + +@ExtendWith(MockitoExtension.class) +class RankServiceTest { + @Mock + private UserRepository userRepository; + @Mock + private RankRedisRepository redisRepository; + @Mock + private SeasonFindService seasonFindService; + @Mock + private RankRepository rankRepository; + @InjectMocks + private RankService rankService; + + @BeforeEach + void setUp() { + // ํ˜„์žฌ ์‹œ์ฆŒ ๊ฐ€์ ธ์˜ค๊ธฐ + given(seasonFindService.findCurrentSeason(any())) + .willReturn(Season.builder() + .seasonName("Test Season") + .build()); + } + + @AfterEach + void tearDown() { + } + + @Test + void getExpRankPage() { + PageRequest pageRequest = PageRequest.of(0, 10); + // exp ranking user list, total page size ์กฐํšŒ + given(userRepository.findAllByTotalExpGreaterThan(pageRequest, 0)) + .willReturn(new PageImpl<>(new ArrayList(), pageRequest, 1)); + + // exp ranking list ์กฐํšŒ + List expRankV2DtoList = expRankingSampleData(); + given(userRepository.findExpRank(pageRequest.getPageNumber(), pageRequest.getPageSize(), + null)) + .willReturn(expRankV2DtoList); + ExpRankPageResponseDto testRes = rankService.getExpRankPage(pageRequest, UserDto + .builder() + .intraId("TestUser") + .id(1L) + .totalExp(0) + .build()); + assertThat(testRes.getMyRank()).isEqualTo(-1); + assertThat(testRes.getRankList().get(0).getIntraId()).isEqualTo("Test User"); + } + + private static List expRankingSampleData() { + List expRankV2Dtos = new ArrayList<>(); + expRankV2Dtos.add(new ExpRankV2Dto() { + @Override + public String getIntraId() { + return "Test User"; + } + + @Override + public String getStatusMessage() { + return "status message"; + } + + @Override + public Integer getTotalExp() { + return 0; + } + + @Override + public String getImageUri() { + return "null"; + } + + @Override + public String getTextColor() { + return null; + } + + @Override + public Integer getRanking() { + return 1; + } + }); + return expRankV2Dtos; + } + + @Test + void getRankPageV2() { + PageRequest pageRequest = PageRequest.of(0, 10); + // ํ˜„์žฌ ์‹œ์ฆŒ id ์— ํ•ด๋‹นํ•˜๋Š” ๋žญํฌ ์œ ์ € ๋ฆฌ์ŠคํŠธ์˜ ํŽ˜์ด์ง€ ์ˆ˜ + given(rankRepository.countRankUserBySeasonId(any())) + .willReturn(1); + // ํ˜„์žฌ ์œ ์ € ranking + given(rankRepository.findRankByUserIdAndSeasonId(any(), any())) + .willReturn(Optional.of(1)); + // sample data + List rankV2DtoList = pppRankingSampleData(); + given(rankRepository.findPppRankBySeasonId(anyInt(), anyInt(), any())) + .willReturn(rankV2DtoList); + RankPageResponseDto result = rankService.getRankPageV2(pageRequest, + UserDto + .builder() + .intraId("TestUser") + .id(1L) + .totalExp(0) + .build(), + any()); + assertThat(result.getCurrentPage()).isEqualTo(pageRequest.getPageNumber() + 1); + assertThat(result.getRankList().size()).isEqualTo(rankV2DtoList.size()); + } + + private static List pppRankingSampleData() { + List rankV2DtoList = new ArrayList<>(); + rankV2DtoList.add(new RankV2Dto() { + @Override + public String getIntraId() { + return "TestUser"; + } + + @Override + public String getStatusMessage() { + return "status message"; + } + + @Override + public Integer getPpp() { + return 1150; + } + + @Override + public String getTierImageUri() { + return "null"; + } + + @Override + public String getTextColor() { + return null; + } + + @Override + public Integer getRanking() { + return 1; + } + }); + return rankV2DtoList; + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTestController.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTestController.java new file mode 100644 index 000000000..8b20a431e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTestController.java @@ -0,0 +1,83 @@ +package gg.pingpong.api.user.season; + +import static org.assertj.core.api.AssertionsForClassTypes.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.season.Season; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.season.controller.response.SeasonListResDto; +import gg.pingpong.api.user.season.controller.response.SeasonResDto; +import gg.pingpong.api.user.season.service.SeasonService; +import gg.repo.season.SeasonRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +public class SeasonTestController { + + @Autowired + MockMvc mvc; + @Autowired + private SeasonService seasonService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + ObjectMapper objectMapper; + + @Autowired + private SeasonRepository seasonRepository; + + @BeforeEach + public void init() { + System.out.println("before each"); + Season s1 = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now().withNano(0).minusMinutes(5), + LocalDateTime.now().plusMinutes(15), 1000, + 100); + seasonRepository.save(s1); + seasonRepository.save( + new Season("test2 season", LocalDateTime.now().withNano(0).minusMinutes(5), + LocalDateTime.now().plusMinutes(15), 1000, + 100)); + seasonRepository.flush(); + System.out.println(seasonRepository.findAll()); + } + + @Test + @DisplayName("์‹œ์ฆŒ ์กฐํšŒ Test") + @Transactional + void season_list_test() throws Exception { + //given + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String url = "/pingpong/seasons"; + List list = seasonService.seasonList(); + //when + String contentAsString = mvc.perform( + RestDocumentationRequestBuilders.get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + //then + SeasonListResDto result = objectMapper.readValue(contentAsString, SeasonListResDto.class); + assertThat(list.size()).isEqualTo(result.getSeasonList().size()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTriggerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTriggerTest.java new file mode 100644 index 000000000..1728f970d --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/SeasonTriggerTest.java @@ -0,0 +1,77 @@ +package gg.pingpong.api.user.season; + +import java.time.LocalDateTime; + +import javax.persistence.EntityManager; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.cglib.proxy.UndeclaredThrowableException; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.type.Mode; +import gg.data.season.Season; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.repo.season.SeasonRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RequiredArgsConstructor +@IntegrationTest +@AutoConfigureMockMvc +@Slf4j +public class SeasonTriggerTest { + + @Autowired + MockMvc mvc; + @Autowired + TestDataUtils testDataUtils; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + ObjectMapper objectMapper; + @Autowired + EntityManager em; + + @Autowired + private SeasonRepository seasonRepository; + + @BeforeEach + @Transactional + public void init() { + System.out.println("before each"); + Season s1 = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100); + seasonRepository.save(s1); + seasonRepository.save( + new Season("test2 season", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100)); + seasonRepository.flush(); + System.out.println(seasonRepository.findAll()); + } + + @Test + @DisplayName("์‹œ์ฆŒ ์‚ญ์ œ ๋ฐฉ์ง€ Test") + @Transactional + public void seasonDeleteImpossibleTest() { + Season season = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100); + seasonRepository.save(season); + Long id = season.getId(); + testDataUtils.createMockMatch(testDataUtils.createNewUser(), season, + LocalDateTime.now().minusMinutes(20), LocalDateTime.now().minusMinutes(5), Mode.RANK); + log.info("ID : " + id); + Throwable thrownException = Assertions.assertThrows(UndeclaredThrowableException.class, () -> { + seasonRepository.deleteById(id); + em.flush(); + }); + + log.info("์—๋Ÿฌ ๋ฉ”์‹œ์ง€: " + thrownException.getMessage()); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/service/SeasonServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/service/SeasonServiceUnitTest.java new file mode 100644 index 000000000..0a8b083fa --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/season/service/SeasonServiceUnitTest.java @@ -0,0 +1,65 @@ +package gg.pingpong.api.user.season.service; + +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.data.season.Season; +import gg.repo.season.SeasonRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.season.SeasonNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class SeasonServiceUnitTest { + @Mock + SeasonRepository seasonRepository; + @InjectMocks + SeasonService seasonService; + + @Nested + @DisplayName("seasonList ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class SeasonList { + @Test + @DisplayName("success") + void success() { + // given + given(seasonRepository.findActiveSeasonsDesc(any())).willReturn(new ArrayList<>()); + // when, then + seasonService.seasonList(); + } + } + + @Nested + @DisplayName("getCurSeason ๋ฉ”์„œ๋“œ ์œ ๋‹› ํ…Œ์ŠคํŠธ") + class GetCurSeason { + @Test + @DisplayName("success") + void success() { + // given + given(seasonRepository.findCurrentSeason(any())).willReturn(Optional.of(mock(Season.class))); + // when, then + seasonService.getCurSeason(); + } + + @Test + @DisplayName("SeasonNotFoundException") + void seasonNotFoundException() { + // given + given(seasonRepository.findCurrentSeason(any())).willReturn(Optional.empty()); + // when, then + Assertions.assertThatThrownBy(() -> seasonService.getCurSeason()) + .isInstanceOf(SeasonNotFoundException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tier/service/TierServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tier/service/TierServiceUnitTest.java new file mode 100644 index 000000000..46fa47aba --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tier/service/TierServiceUnitTest.java @@ -0,0 +1,173 @@ +package gg.pingpong.api.user.tier.service; + +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; +import org.springframework.data.domain.Sort; + +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.season.Season; +import gg.data.user.User; +import gg.pingpong.api.user.rank.service.TierService; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.utils.annotation.UnitTest; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class TierServiceUnitTest { + + @Mock + TierRepository tierRepository; + @Mock + RankRepository rankRepository; + @InjectMocks + TierService tierService; + + @Nested + @DisplayName("UpdateAllTier") + class UpdateAllTier { + List tiers; + + Season season; + + @BeforeEach + void init() { + tiers = IntStream.range(0, 7).mapToObj((i) -> mock(Tier.class)).collect(Collectors.toList()); + when(tierRepository.findAll(any(Sort.class))).thenReturn(tiers); + season = mock(Season.class); + when(season.getId()).thenReturn(1L); + } + + @ParameterizedTest + @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ๋ฏธ์ฐธ์—ฌ์‹œ 0๋ฒˆ ํ‹ฐ์–ด") + @ValueSource(ints = {1, 3, 5, 7}) + @MockitoSettings(strictness = Strictness.LENIENT) + void notParticipant(int size) { + //Arrange + List rankList = IntStream.range(0, size) + .mapToObj((i) -> new Rank(mock(User.class), season, 1000, 0, 0, "", mock(Tier.class))) + .collect(Collectors.toList()); + when(rankRepository.findAllBySeasonIdOrderByPppDesc(any())).thenReturn(rankList); + when(rankRepository.countRealRankPlayers(any())).thenReturn(0L); + + //Act + tierService.updateAllTier(season); + + //Assert + Assertions.assertThat(rankList).allMatch((rank) -> rank.getTier().equals(tiers.get(0))); + } + + @ParameterizedTest + @DisplayName("์ฐธ์—ฌํ•œ ์œ ์ € ์ค‘ ppp ์ตœ๋Œ€ 3๋ช… 6๋ฒˆ ํ‹ฐ์–ด") + @ValueSource(ints = {1, 3, 5, 7}) + @MockitoSettings(strictness = Strictness.LENIENT) + void top3(int size) { + //Arrange + List rankList = IntStream.range(0, size) + .mapToObj((i) -> new Rank(mock(User.class), season, 900 + 10 * i, 0, 1, "", mock(Tier.class))) + .sorted(Comparator.comparing(Rank::getPpp).reversed()) + .collect(Collectors.toList()); + when(rankRepository.findAllBySeasonIdOrderByPppDesc(any())).thenReturn(rankList); + when(rankRepository.countRealRankPlayers(any())).thenReturn((long)size); + + //Act + tierService.updateAllTier(season); + long cnt = rankList.stream().filter((rank) -> rank.getTier().equals(tiers.get(6))).count(); + + //Assert + Assertions.assertThat(cnt).isEqualTo(Math.min(3, size)); + } + + /** + * ๊ฐœ์„  ํ•„์š”: ์ตœ์ƒ์œ„ 3๋ช…์ด ๊ธฐ๋ณธ ppp๋ณด๋‹ค ๋‚ฎ์„ ๊ฒฝ์šฐ 6๋ฒˆ ํ‹ฐ์–ด๊ฐ€ 0๋ช…์ด ๋œ๋‹ค. + * ๊ฒŒ์ž„์ƒ ์žฌํ˜„์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ฝ”๋“œ์ƒ ๋ฒ„๊ทธ๋กœ ํŒ๋‹จ. + */ + @ParameterizedTest + @DisplayName("์ „์ฒด ํ‹ฐ์–ด ์กฐ๊ฑด ๊ฒ€์ฆ") + @ValueSource(ints = {100}) + @MockitoSettings(strictness = Strictness.LENIENT) + void allTierCondition(int size) { + //Arrange + ArrayList rankArrayList = IntStream.range(0, size) + .mapToObj((i) -> new Rank(mock(User.class), season, 900 + 10 * i, 1, 0, "", mock(Tier.class))) + .collect(Collectors.toCollection(ArrayList::new)); + when(rankRepository.countRealRankPlayers(any())).thenReturn((long)size); + + IntStream.range(0, 100) + .mapToObj((i) -> new Rank(mock(User.class), season, 1000, 0, 0, "", mock(Tier.class))) + .forEach(rankArrayList::add); + when(rankRepository.countRealRankPlayers(any())).thenReturn((long)size); + + List rankList = rankArrayList.stream() + .sorted(Comparator.comparing(Rank::getPpp).reversed()) + .collect(Collectors.toList()); + when(rankRepository.findAllBySeasonIdOrderByPppDesc(any())).thenReturn(rankList); + + //Act + tierService.updateAllTier(season); + + List tier0 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(0))) + .collect(Collectors.toList()); + + List tier1 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(1))) + .collect(Collectors.toList()); + + List tier2 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(2))) + .collect(Collectors.toList()); + + List tier3 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(3))) + .collect(Collectors.toList()); + + List tier4 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(4))) + .sorted(Comparator.comparing(Rank::getPpp)) + .collect(Collectors.toList()); + Integer tier4MinPPP = tier4.get(0).getPpp(); + + List tier5 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(5))) + .sorted(Comparator.comparing(Rank::getPpp)) + .collect(Collectors.toList()); + Integer tier5MinPPP = tier5.get(0).getPpp(); + + List tier6 = rankList.stream() + .filter((rank) -> rank.getTier().equals(tiers.get(6))) + .sorted(Comparator.comparing(Rank::getPpp)) + .collect(Collectors.toList()); + Integer tier6MinPPP = tier6.get(0).getPpp(); + + //Assert + Assertions.assertThat(tier0).allMatch((rank) -> rank.getWins() == 0 && rank.getLosses() == 0); + Assertions.assertThat(tier1).allMatch((rank) -> rank.getPpp() < 970); + Assertions.assertThat(tier2).allMatch((rank) -> rank.getPpp() < 1010); + Assertions.assertThat(tier3).allMatch((rank) -> rank.getPpp() < tier4MinPPP); + Assertions.assertThat(tier4).allMatch((rank) -> rank.getPpp() < tier5MinPPP); + Assertions.assertThat(tier5).allMatch((rank) -> rank.getPpp() <= tier6MinPPP); + Assertions.assertThat(tier6.size()).isEqualTo(Math.min(3, size)); + } + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentControllerMvcTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentControllerMvcTest.java new file mode 100644 index 000000000..33ffb76d7 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentControllerMvcTest.java @@ -0,0 +1,218 @@ +package gg.pingpong.api.user.tournament.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import javax.validation.ConstraintViolationException; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mockito; +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.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.web.servlet.MockMvc; + +import gg.pingpong.api.global.config.WebConfig; +import gg.pingpong.api.global.security.config.SecurityConfig; +import gg.pingpong.api.global.security.jwt.utils.TokenAuthenticationFilter; +import gg.pingpong.api.global.utils.querytracker.LoggingInterceptor; +import gg.pingpong.api.user.tournament.controller.request.TournamentFilterRequestDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserRegistrationResponseDto; +import gg.pingpong.api.user.tournament.service.TournamentService; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.utils.annotation.UnitTest; + +@UnitTest +@WebMvcTest(controllers = TournamentController.class, excludeFilters = { + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = WebConfig.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TokenAuthenticationFilter.class), + @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = LoggingInterceptor.class)}) +class TournamentControllerMvcTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private TournamentService tournamentService; + + @Autowired + private TournamentController tournamentController; + + @Nested + @DisplayName("getAllTournamentList") + class GetAllTournamentList { + + @DisplayName("ํŽ˜์ด์ง€๋ฒˆํ˜ธ๊ฐ€ 1๋ณด๋‹ค ์ž‘์„ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ") + @ParameterizedTest() + @ValueSource(ints = {-1, 0}) + void pageMustGreaterThanZero(Integer page) { + //Arrange + TournamentFilterRequestDto dto = new TournamentFilterRequestDto(page, 1, null, null); + + //Act, Assert + assertThatThrownBy(() -> tournamentController.getAllTournamentList(dto)) + .isInstanceOf(ConstraintViolationException.class); + } + + @DisplayName("์‚ฌ์ด์ฆˆ๊ฐ€ 1๊ณผ 30 ์‚ฌ์ด๊ฐ€ ์•„๋‹๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ") + @ParameterizedTest() + @ValueSource(ints = {-1, 0, 31}) + void sizeError(Integer size) { + //Arrange + TournamentFilterRequestDto dto = new TournamentFilterRequestDto(1, size, null, null); + + //Act, Assert + assertThatThrownBy(() -> tournamentController.getAllTournamentList(dto)) + .isInstanceOf(ConstraintViolationException.class); + } + + @DisplayName("Success") + @Test + void success() { + //Arrange + TournamentFilterRequestDto dto = new TournamentFilterRequestDto(1, 1, null, null); + TournamentListResponseDto resultDto = Mockito.mock(TournamentListResponseDto.class); + when(tournamentService.getAllTournamentList(any(), any(), any())).thenReturn(resultDto); + + //Act + ResponseEntity response = tournamentController.getAllTournamentList(dto); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } + + @Nested + @DisplayName("getUserStatusInTournament") + class GetUserStatusInTournament { + @DisplayName("Success") + @Test + void success() { + //Arrange + UserDto userDto = Mockito.mock(UserDto.class); + TournamentUserRegistrationResponseDto resultDto = Mockito.mock(TournamentUserRegistrationResponseDto.class); + when(tournamentService.getUserStatusInTournament(any(), any())).thenReturn(resultDto); + + //Act + ResponseEntity response = tournamentController + .getUserStatusInTournament(1L, userDto); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } + + @Nested + @DisplayName("getTournnament") + class GetTournnament { + @DisplayName("id๊ฐ€ ์–‘์ˆ˜๊ฐ€ ์•„๋‹๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ") + @ParameterizedTest() + @ValueSource(longs = {-1, 0}) + void idGreaterThanZero(Long id) { + //Act, Assert + assertThatThrownBy(() -> tournamentController.getTournnament(id)) + .isInstanceOf(ConstraintViolationException.class); + } + + @DisplayName("Success") + @Test + void success() { + //Arrange + TournamentResponseDto resultDto = Mockito.mock(TournamentResponseDto.class); + when(tournamentService.getTournament(anyLong())).thenReturn(resultDto); + + //Act + ResponseEntity response = tournamentController.getTournnament(1L); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } + + @Nested + @DisplayName("cancelTournamentUserRegistration") + class CancelTournamentUserRegistration { + + @DisplayName("Success") + @Test + void success() { + //Arrange + UserDto userDto = Mockito.mock(UserDto.class); + TournamentUserRegistrationResponseDto resultDto = Mockito.mock(TournamentUserRegistrationResponseDto.class); + when(tournamentService.cancelTournamentUserRegistration(anyLong(), any())).thenReturn(resultDto); + + //Act + ResponseEntity response; + response = tournamentController.cancelTournamentUserRegistration(1L, userDto); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } + + @Nested + @DisplayName("getTournamentGames") + class GetTournamentGames { + @DisplayName("id๊ฐ€ ์–‘์ˆ˜๊ฐ€ ์•„๋‹๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ") + @ParameterizedTest() + @ValueSource(longs = {-1, 0}) + void idGreaterThanZero(Long id) { + //Act, Assert + assertThatThrownBy(() -> tournamentController.getTournamentGames(id)) + .isInstanceOf(ConstraintViolationException.class); + } + + @DisplayName("Success") + @Test + void success() { + //Arrange + TournamentGameListResponseDto resultDto = Mockito.mock(TournamentGameListResponseDto.class); + when(tournamentService.getTournamentGames(anyLong())).thenReturn(resultDto); + + //Act + ResponseEntity response = tournamentController.getTournamentGames(1L); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } + + @Nested + @DisplayName("registerTournamentUser") + class RegisterTournamentUser { + + @DisplayName("Success") + @Test + void success() { + //Arrange + UserDto userDto = Mockito.mock(UserDto.class); + TournamentUserRegistrationResponseDto resultDto = Mockito.mock(TournamentUserRegistrationResponseDto.class); + when(tournamentService.registerTournamentUser(anyLong(), any())).thenReturn(resultDto); + + //Act + ResponseEntity response; + response = tournamentController.registerTournamentUser(1L, userDto); + + //Assert + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); + assertThat(response.getBody()).isEqualTo(resultDto); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentFindControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentFindControllerTest.java new file mode 100644 index 000000000..aaade00a1 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentFindControllerTest.java @@ -0,0 +1,565 @@ +package gg.pingpong.api.user.tournament.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.List; + +import org.apache.http.HttpHeaders; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.tournament.controller.response.TournamentListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.repo.tournarment.TournamentUserRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@RequiredArgsConstructor +@Slf4j +public class TournamentFindControllerTest { + + @Autowired + MockMvc mockMvc; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + @Autowired + TournamentUserRepository tournamentUserRepository; + + List tournamentList; + String accessToken; + + User tester; + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๋ฆฌ์ŠคํŠธ_์กฐํšŒ") + class FindTournamentListTest { + @BeforeEach + void beforeEach() { + tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + tournamentList = testDataUtils.makeTournamentList(); + } + + @Test + @DisplayName("์ „์ฒด_์กฐํšŒ") + public void getTournamentList() throws Exception { + // given + int page = 1; + int size = 20; + String url = "/pingpong/tournaments/?page=" + page + "&size=" + size; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); + + // then + List tournamentInfoList = resp.getTournaments(); + for (int i = 0; i < tournamentInfoList.size(); i++) { + Long tournamentId = tournamentInfoList.get(i).getTournamentId(); + TournamentResponseDto tournamentResponseDto = tournamentList.stream() + .filter(t -> t.getTournamentId().equals(tournamentId)) + .findFirst() + .orElse(null); + if (tournamentResponseDto != null) { + assertThat(tournamentInfoList.get(i).getTitle()).isEqualTo(tournamentResponseDto.getTitle()); + assertThat(tournamentInfoList.get(i).getContents()).isEqualTo(tournamentResponseDto.getContents()); + assertThat(tournamentInfoList.get(i).getType()).isEqualTo(tournamentResponseDto.getType()); + assertThat(tournamentInfoList.get(i).getStatus()).isEqualTo(tournamentResponseDto.getStatus()); + assertThat(tournamentInfoList.get(i).getWinnerIntraId()).isEqualTo( + tournamentResponseDto.getWinnerIntraId()); + assertThat(tournamentInfoList.get(i).getWinnerImageUrl()).isEqualTo( + tournamentResponseDto.getWinnerImageUrl()); + assertThat(tournamentInfoList.get(i).getPlayerCnt()).isEqualTo( + tournamentResponseDto.getPlayerCnt()); + } + if (i > 0) { + assertThat(tournamentInfoList.get(i).getStartTime()).isAfter( + tournamentInfoList.get(i - 1).getEndTime()); + } + } + } + + @Test + @DisplayName("status๋ณ„_์กฐํšŒ") + public void getTournamentListByStatus() throws Exception { + + // given + int page = 1; + int size = 10; + String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&status=" + TournamentStatus.BEFORE; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); + + // then + List tournamentInfoList = resp.getTournaments(); + for (TournamentResponseDto responseDto : tournamentInfoList) { + assertThat(responseDto.getStatus()).isEqualTo(TournamentStatus.BEFORE); + } + } + + @Test + @DisplayName("type๋ณ„_์กฐํšŒ") + public void getTournamentListByType() throws Exception { + + // given + int page = 1; + int size = 10; + String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); + + // then + List tournamentInfoList = resp.getTournaments(); + for (TournamentResponseDto responseDto : tournamentInfoList) { + assertThat(responseDto.getType()).isEqualTo(TournamentType.ROOKIE); + } + } + + @Test + @DisplayName("type๊ณผ status ๋ณ„ ์กฐํšŒ") + public void getTournamentListByTypeAndStatus() throws Exception { + // given + int page = 1; + int size = 10; + String url = + "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE + "&status=" + + TournamentStatus.BEFORE; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); + + // then + List tournamentInfoList = resp.getTournaments(); + for (TournamentResponseDto responseDto : tournamentInfoList) { + assertThat(responseDto.getType()).isEqualTo(TournamentType.ROOKIE); + assertThat(responseDto.getStatus()).isEqualTo(TournamentStatus.BEFORE); + } + } + + @Test + @DisplayName("์ž˜๋ชป๋œ type") + public void wrongType() throws Exception { + // given + int page = 1; + int size = 10; + String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + "rookie123" + "&status=" + + TournamentStatus.BEFORE.getCode(); + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + + // then + log.info(contentAsString); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ status") + public void wrongStatus() throws Exception { + // given + int page = 1; + int size = 10; + String url = + "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE.getCode() + + "&status=" + "wrongStatus"; + + // when + String contentAsString = mockMvc.perform( + get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isBadRequest()) + .andReturn().getResponse().getContentAsString(); + + // then + log.info(contentAsString); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‹ ์ฒญ_์ทจ์†Œ_ํ…Œ์ŠคํŠธ") + class CancelTournamentUserRegistrationTest { + @BeforeEach + void beforeEach() { + tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + } + + @Test + @DisplayName("์œ ์ €_์‹ ์ฒญ_์ทจ์†Œ_์„ฑ๊ณต") + void success() throws Exception { + // given + int maxTournamentUser = 8; + Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + for (int i = 0; i < maxTournamentUser - 1; i++) { + testDataUtils.createTournamentUser(testDataUtils.createNewUser("testUser" + i), tournament, true); + } + testDataUtils.createTournamentUser(tester, tournament, true); + for (int i = maxTournamentUser; i < maxTournamentUser + 4; i++) { + testDataUtils.createTournamentUser(testDataUtils.createNewUser("testUser" + i), tournament, false); + } + String url = "/pingpong/tournaments/" + tournament.getId() + "/users"; + String expected = "{\"status\":\"BEFORE\"}"; + + // when + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + // then + System.out.println(contentAsString); + if (expected.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + tournamentUserRepository.findByTournamentIdAndUserId(tournament.getId(), tester.getId()).ifPresent( + a -> { + throw new CustomRuntimeException("", ErrorCode.BAD_REQUEST); + }); + List tournamentUserList = tournament.getTournamentUsers(); + for (int i = 0; i < maxTournamentUser; i++) { + if (!tournamentUserList.get(i).getIsJoined()) { + throw new CustomRuntimeException("์ฐธ๊ฐ€์ž ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + } + for (int i = maxTournamentUser; i < tournamentUserList.size(); i++) { + if (tournamentUserList.get(i).getIsJoined()) { + throw new CustomRuntimeException("๋Œ€๊ธฐ์ž ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + } + } + + @Test + @DisplayName("์œ ์ €_์—†์Œ") + void userNotFound() throws Exception { + // given + Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + String url = "/pingpong/tournaments/" + tournament.getId() + "/users"; + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + void tournamentNotFound() throws Exception { + // given + String url = "/pingpong/tournaments/" + 9999 + "/users"; + + // when, then + String contentAsString = mockMvc.perform(delete(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๋‹จ์ผ_์กฐํšŒ") + class FindTournamentTest { + @BeforeEach + void beforeEach() { + tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + } + + @Test + @DisplayName("์กฐํšŒ_์„ฑ๊ณต") + public void success() throws Exception { + //given + Tournament tournament = testDataUtils.createTournament("string1", "string", + LocalDateTime.now().plusDays(2).plusHours(1), LocalDateTime.now().plusDays(2).plusHours(3), + TournamentType.ROOKIE, TournamentStatus.BEFORE); + User user = testDataUtils.createNewUser("test"); + testDataUtils.createTournamentUser(user, tournament, true); + tournament.updateWinner(user); + + Long tournamentId = tournament.getId(); + String url = "/pingpong/tournaments/" + tournamentId; + + //when + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + TournamentResponseDto responseDto = objectMapper.readValue(contentAsString, TournamentResponseDto.class); + + //then + assertThat(tournament.getTitle()).isEqualTo(responseDto.getTitle()); + assertThat(tournament.getContents()).isEqualTo(responseDto.getContents()); + assertThat(tournament.getType()).isEqualTo(responseDto.getType()); + assertThat(tournament.getStatus()).isEqualTo(responseDto.getStatus()); + if (tournament.getWinner() == null) { + assertThat(responseDto.getWinnerIntraId()).isEqualTo(null); + assertThat(responseDto.getWinnerImageUrl()).isEqualTo(null); + } else { + assertThat(tournament.getWinner().getIntraId()).isEqualTo(responseDto.getWinnerIntraId()); + assertThat(tournament.getWinner().getImageUri()).isEqualTo(responseDto.getWinnerImageUrl()); + } + assertThat(tournament.getTournamentUsers().size()).isEqualTo(responseDto.getPlayerCnt()); + } + + @Test + @DisplayName("์ž˜๋ชป๋œ_ํ† ๋„ˆ๋จผํŠธ_ID") + public void tournamentNotExist() throws Exception { + //given + Long tournamentId = 1L; + String url = "/pingpong/tournaments/" + tournamentId; + + //when + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + //then + System.out.println(contentAsString); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ฐธ๊ฐ€_์ƒํƒœ_์กฐํšŒ") + class UserStatusInTournamentTest { + @BeforeEach + void beforeEach() { + tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + } + + @Test + @DisplayName("์œ ์ €_์ƒํƒœ_์กฐํšŒ_์„ฑ๊ณต") + void success() throws Exception { + // given 1 + Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + String url = "/pingpong/tournaments/" + tournament.getId() + "/users"; + String expected1 = "{\"status\":\"BEFORE\"}"; + + // when 1 + String contentAsString = mockMvc.perform(get(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + // then 1 + if (expected1.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + + // given 2 + testDataUtils.createTournamentUser(tester, tournament, false); + String expected2 = "{\"status\":\"WAIT\"}"; + + // when 2 + contentAsString = mockMvc.perform(get(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + // then 2 + if (expected2.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + + // given 3 + tournamentUserRepository.findByTournamentIdAndUserId(tournament.getId(), tester.getId()) + .get().updateIsJoined(true); + String expected3 = "{\"status\":\"PLAYER\"}"; + + // when 3 + contentAsString = mockMvc.perform(get(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + // then 3 + if (expected3.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + void tournamentNotFound() throws Exception { + // given + String url = "/pingpong/tournaments/" + 9999 + "/users"; + + // when, then + String contentAsString = mockMvc.perform(get(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ฐธ๊ฐ€_์‹ ์ฒญ") + class RegisterTournamentUserTest { + @BeforeEach + void beforeEach() { + tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + } + + @Test + @DisplayName("์œ ์ €_์ฐธ๊ฐ€_์‹ ์ฒญ(์ฐธ๊ฐ€์ž)_์„ฑ๊ณต") + void successPlayer() throws Exception { + // given + Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + String url = "/pingpong/tournaments/" + tournament.getId() + "/users"; + String expected = "{\"status\":\"PLAYER\"}"; + + // when + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + // then + if (expected.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + } + + @Test + @DisplayName("์œ ์ €_์ฐธ๊ฐ€_์‹ ์ฒญ(๋Œ€๊ธฐ์ž)_์„ฑ๊ณต") + void successWait() throws Exception { + // given + int maxTournamentUser = 8; + Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + for (int i = 0; i < maxTournamentUser; i++) { + testDataUtils.createTournamentUser(testDataUtils.createNewUser("testUser" + i), tournament, true); + } + String url = "/pingpong/tournaments/" + tournament.getId() + "/users"; + String expected = "{\"status\":\"WAIT\"}"; + + // when + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(); + + // then + if (expected.compareTo(contentAsString) != 0) { + throw new CustomRuntimeException("์ƒํƒœ ์˜ค๋ฅ˜", ErrorCode.BAD_REQUEST); + } + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") + void tournamentNotFound() throws Exception { + // given + String url = "/pingpong/tournaments/" + 9999 + "/users"; + + // when, then + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNotFound()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + @Test + @DisplayName("์ด๋ฏธ_์‹ ์ฒญํ•œ_ํ† ๋„ˆ๋จผํŠธ_์กด์žฌ") + void conflictRegisteration() throws Exception { + // given + Tournament tournament1 = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + Tournament tournament2 = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), + TournamentStatus.BEFORE); + testDataUtils.createTournamentUser(tester, tournament1, false); + String url = "/pingpong/tournaments/" + tournament2.getId() + "/users"; + + // when, then + String contentAsString = mockMvc.perform(post(url) + .contentType(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isConflict()) + .andReturn().getResponse().getContentAsString(); + + System.out.println(contentAsString); + } + + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentGameControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentGameControllerTest.java new file mode 100644 index 000000000..b98c27d0e --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentGameControllerTest.java @@ -0,0 +1,108 @@ +package gg.pingpong.api.user.tournament.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.Objects; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.type.Mode; +import gg.data.season.Season; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameResDto; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.dto.GameInfoDto; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@RequiredArgsConstructor +@Slf4j +public class TournamentGameControllerTest { + + @Autowired + MockMvc mockMvc; + @Autowired + TestDataUtils testDataUtils; + @Autowired + ObjectMapper objectMapper; + @Autowired + AuthTokenProvider tokenProvider; + + String accessToken; + Tournament testTournament; + String tournamentUrl = "/pingpong/tournaments/"; + + @BeforeEach + void beforeEach() { + User tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, + SnsType.SLACK, RoleType.ADMIN); + accessToken = tokenProvider.createToken(tester.getId()); + + Season season = testDataUtils.createSeason(); + testTournament = testDataUtils.createTournament("Test Tournament", LocalDateTime.now(), + LocalDateTime.now().plusHours(2), TournamentStatus.LIVE); + int idx = 0; + for (TournamentRound round : TournamentRound.values()) { + User gamer = testDataUtils.createNewUser("gamer" + idx++); + GameInfoDto gameInfoDto = testDataUtils.createGame(gamer, LocalDateTime.now().minusDays(10), + LocalDateTime.now().minusDays(10).plusMinutes(20), season, Mode.TOURNAMENT); + TournamentGame tournamentGame = testDataUtils.createTournamentGame(testTournament, round, gameInfoDto); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ฒŒ์ž„_๋ฆฌ์ŠคํŠธ_์กฐํšŒ") + class FindTournamentGameTest { + + @Test + @DisplayName("[Get] pingpong/tournaments/{tournamentId}/games") + public void getTournamentGames() throws Exception { + + // given + String url = tournamentUrl + testTournament.getId() + "/games"; + + // when + String contentAsString = mockMvc.perform(get(url).header("Authorization", "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + TournamentGameListResponseDto resp = objectMapper.readValue(contentAsString, + TournamentGameListResponseDto.class); + + // then + assertThat(resp.getTournamentId()).isEqualTo(testTournament.getId()); + assertThat(resp.getGames().size()).isEqualTo(TournamentRound.values().length); + for (TournamentGameResDto tournamentGameResDto : resp.getGames()) { + assertThat(tournamentGameResDto.getTournamentGameId()).isNotNull(); + assertThat(tournamentGameResDto.getTournamentRound()).isNotNull(); + if (!Objects.equals(tournamentGameResDto.getTournamentRound(), TournamentRound.THE_FINAL)) { + assertThat(tournamentGameResDto.getNextTournamentGameId()).isNotNull(); + } + } + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentSchedulerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentSchedulerTest.java new file mode 100644 index 000000000..7b8d45ccc --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/controller/TournamentSchedulerTest.java @@ -0,0 +1,111 @@ +package gg.pingpong.api.user.tournament.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.transaction.annotation.Transactional; + +import gg.data.manage.SlotManagement; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentStatus; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.tournament.service.TournamentService; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; + +@IntegrationTest +@Transactional +public class TournamentSchedulerTest { + @Autowired + TournamentService tournamentService; + @Autowired + TestDataUtils testDataUtils; + @Autowired + SlotManagementRepository slotManagementRepository; + @Autowired + TournamentGameRepository tournamentGameRepository; + @MockBean + NotiAdminService notiAdminService; + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์Šค์ผ€์ค„๋Ÿฌ ํ…Œ์ŠคํŠธ") + class TournamentSchedulerTests { + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์„ฑ๊ณต") + public void startTournamentTest() { + // given + testDataUtils.createSeason(); + // BEFORE๋กœ ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ + Tournament tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "test"); + List tournamentGameList = testDataUtils.createTournamentGameList(tournament, 7); + SlotManagement slotManagement = SlotManagement.builder() + .pastSlotTime(0) + .futureSlotTime(0) + .openMinute(0) + .gameInterval(15) + .startTime(LocalDateTime.now().minusHours(1)) + .build(); + slotManagementRepository.save(slotManagement); + + // when + tournamentService.startTournament(); + + // then + // ํ† ๋„ˆ๋จผํŠธ์˜ ์ƒํƒœ๊ฐ€ LIVE๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + assertThat(tournament.getStatus()) + .isEqualTo(TournamentStatus.LIVE); + + // game์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + List tournamentGames = tournamentGameRepository.findAllByTournamentId(tournament.getId()) + .stream() + .filter(o -> o.getGame() != null) + .collect(Collectors.toList()); + assertThat(tournamentGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 2); + for (TournamentGame tournamentGame : tournamentGames) { + assertThat(tournamentGame.getGame()).isNotNull(); + } + //์ฐธ๊ฐ€์ž์—๊ฒŒ ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ๋ฐ ๋งค์นญ ์•Œ๋ฆผ์ด ์ „์†ก๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + verify(notiAdminService, times(Tournament.ALLOWED_JOINED_NUMBER)).sendAnnounceNotiToUser( + Mockito.any(SendNotiAdminRequestDto.class)); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ทจ์†Œ ์„ฑ๊ณต") + public void cancelTournamentTest() { + // given + testDataUtils.createSeason(); + // BEFORE๋กœ ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ + Tournament tournament = testDataUtils.createTournamentWithUser(7, 0, "test"); + SlotManagement slotManagement = SlotManagement.builder() + .pastSlotTime(0) + .futureSlotTime(0) + .openMinute(0) + .gameInterval(15) + .startTime(LocalDateTime.now().minusHours(1)) + .build(); + slotManagementRepository.save(slotManagement); + + // when + tournamentService.startTournament(); + + // then + //์ฐธ๊ฐ€์ž์—๊ฒŒ ์ทจ์†Œ ์•Œ๋ฆผ์ด ์ „์†ก๋˜์—ˆ๋Š”์ง€ ํ™•์ธ + verify(notiAdminService, times(7)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); + } + } + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/service/TournamentServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/service/TournamentServiceUnitTest.java new file mode 100644 index 000000000..f639df29f --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/tournament/service/TournamentServiceUnitTest.java @@ -0,0 +1,618 @@ +package gg.pingpong.api.user.tournament.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.IntStream; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +import gg.data.game.Game; +import gg.data.game.type.StatusType; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.tournament.type.TournamentUserStatus; +import gg.data.user.User; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.noti.controller.request.SendNotiAdminRequestDto; +import gg.pingpong.api.admin.noti.service.NotiAdminService; +import gg.pingpong.api.user.match.service.MatchTournamentService; +import gg.pingpong.api.user.tournament.controller.response.TournamentGameListResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.pingpong.api.user.tournament.controller.response.TournamentUserRegistrationResponseDto; +import gg.pingpong.api.user.user.dto.UserDto; +import gg.pingpong.api.utils.ReflectionUtilsForUnitTest; +import gg.repo.game.GameRepository; +import gg.repo.game.out.GameTeamUser; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.repo.user.UserRepository; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.tournament.TournamentConflictException; +import gg.utils.exception.tournament.TournamentNotFoundException; +import gg.utils.exception.user.UserNotFoundException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class TournamentServiceUnitTest { + @Mock + TournamentRepository tournamentRepository; + @Mock + TournamentGameRepository tournamentGameRepository; + @Mock + TournamentUserRepository tournamentUserRepository; + @Mock + UserRepository userRepository; + @Mock + MatchTournamentService matchTournamentService; + @Mock + NotiAdminService notiAdminService; + @Mock + GameRepository gameRepository; + @InjectMocks + TournamentService tournamentService; + + @Nested + @DisplayName("getAllTournamentList") + class GetAllTournamentList { + Pageable pageRequest; + Page page; + Page responseDto; + + @BeforeEach + void init() { + pageRequest = PageRequest.of(1, 10); + page = mock(Page.class); + responseDto = mock(Page.class); + + when(page.map(any(Function.class))).thenReturn(responseDto); + when(responseDto.getContent()).thenReturn(mock(List.class)); + when(responseDto.getTotalPages()).thenReturn(10); + } + + @Test + @DisplayName("type == null && status == null") + void typeAndStatusNull() { + //Arrange + TournamentType type = null; + TournamentStatus status = null; + when(tournamentRepository.findAll(pageRequest)).thenReturn(page); + + //Act + tournamentService.getAllTournamentList(pageRequest, type, status); + + //Assert + verify(tournamentRepository, times(1)).findAll(pageRequest); + } + + @Test + @DisplayName("type == null") + void typeNull() { + //Arrange + TournamentType type = null; + TournamentStatus status = TournamentStatus.LIVE; + when(tournamentRepository.findAllByStatus(status, pageRequest)).thenReturn(page); + + //Act + tournamentService.getAllTournamentList(pageRequest, type, status); + + //Assert + verify(tournamentRepository, times(1)) + .findAllByStatus(status, pageRequest); + } + + @Test + @DisplayName("status == null") + void statusNull() { + //Arrange + TournamentType type = TournamentType.ROOKIE; + TournamentStatus status = null; + when(tournamentRepository.findAllByType(type, pageRequest)).thenReturn(page); + + //Act + tournamentService.getAllTournamentList(pageRequest, type, status); + + //Assert + verify(tournamentRepository, times(1)) + .findAllByType(type, pageRequest); + } + + @Test + @DisplayName("statusAndTypeNotNull") + void statusAndTypeNotNull() { + //Arrange + TournamentType type = TournamentType.ROOKIE; + TournamentStatus status = TournamentStatus.LIVE; + when(tournamentRepository + .findAllByTypeAndStatus(type, status, pageRequest)) + .thenReturn(page); + + //Act + tournamentService.getAllTournamentList(pageRequest, type, status); + + //Assert + verify(tournamentRepository, times(1)) + .findAllByTypeAndStatus(type, status, pageRequest); + } + + } + + @Nested + @DisplayName("getTournament") + class GetTournament { + @Test + @DisplayName("success") + void success() { + //Arrange + Long id = 1L; + Tournament tournament = mock(Tournament.class); + when(tournamentRepository.findById(id)).thenReturn(Optional.of(tournament)); + + //Act + TournamentResponseDto dto = tournamentService.getTournament(id); + + //Assert + verify(tournamentRepository, times(1)).findById(id); + Assertions.assertThat(dto).isNotNull(); + } + + @Test + @DisplayName("TournamentNotFound") + void tournamentNotFound() { + //Arrange + Long id = 1L; + when(tournamentRepository.findById(id)).thenReturn(Optional.empty()); + + //Act, Assert + assertThatThrownBy(() -> tournamentService.getTournament(id)) + .isInstanceOf(TournamentNotFoundException.class); + } + } + + @Nested + @DisplayName("getUserStatusInTournament") + class GetUserStatusInTournament { + Tournament tournament; + TournamentUser tournamentUser; + UserDto requestDto; + + @BeforeEach + void init() { + tournament = mock(Tournament.class); + tournamentUser = mock(TournamentUser.class); + requestDto = mock(UserDto.class); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") + void tournamentNotFound() { + // given + Long tournamentId = 1L; + given(tournamentRepository.findById(tournamentId)).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy(() -> tournamentService + .getUserStatusInTournament(tournamentId, requestDto)) + .isInstanceOf(TournamentNotFoundException.class); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ค‘์ธ ์œ ์ €") + void player() { + // given + given(tournamentRepository.findById(tournament.getId())) + .willReturn(Optional.of(tournament)); + + given(tournament.findTournamentUserByUserId(requestDto.getId())) + .willReturn(Optional.of(tournamentUser)); + + given(tournamentUser.getIsJoined()) + .willReturn(true); + + // when + TournamentUserRegistrationResponseDto responseDto = + tournamentService.getUserStatusInTournament(tournament.getId(), requestDto); + + // then + Assertions.assertThat(responseDto.getStatus()).isEqualTo(TournamentUserStatus.PLAYER); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๋Œ€๊ธฐ์ค‘์ธ ์œ ์ €") + void waitPlayer() { + // given + given(tournamentRepository.findById(tournament.getId())) + .willReturn(Optional.of(tournament)); + + given(tournament.findTournamentUserByUserId(requestDto.getId())) + .willReturn(Optional.of(tournamentUser)); + + given(tournamentUser.getIsJoined()) + .willReturn(false); + + // when + TournamentUserRegistrationResponseDto responseDto = + tournamentService.getUserStatusInTournament(tournament.getId(), requestDto); + + // then + Assertions.assertThat(responseDto.getStatus()).isEqualTo(TournamentUserStatus.WAIT); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญํ•˜์ง€ ์•Š์€ ์œ ์ €") + void beforePlayer() { + // given + given(tournamentRepository.findById(tournament.getId())) + .willReturn(Optional.of(tournament)); + + given(tournament.findTournamentUserByUserId(requestDto.getId())) + .willReturn(Optional.empty()); + + // when + TournamentUserRegistrationResponseDto responseDto = + tournamentService.getUserStatusInTournament(tournament.getId(), requestDto); + + // then + Assertions.assertThat(responseDto.getStatus()).isEqualTo(TournamentUserStatus.BEFORE); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‹ ์ฒญ_ํ…Œ์ŠคํŠธ") + class RegisterTournamentUserTest { + @Test + @DisplayName("์œ ์ €_์ƒํƒœ_์ถ”๊ฐ€_์„ฑ๊ณต") + void success() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + LocalDateTime.now(), LocalDateTime.now().plusHours(2)); + User user = createUser("testUser"); + List tournamentUserList = new ArrayList<>(); + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); + given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); + given(tournamentUserRepository.findAllByUser(any(User.class))).willReturn(tournamentUserList); + + // when, then + TournamentUserRegistrationResponseDto responseDto = + tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user)); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") + void tournamentNotFound() { + // given + User user = createUser("testUser"); + given(tournamentRepository.findById(any(Long.class))).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy(() -> tournamentService.registerTournamentUser(1L, UserDto.from(user))) + .isInstanceOf(TournamentNotFoundException.class); + } + + @Test + @DisplayName("db์—_์—†๋Š”_์œ ์ €") + void userNotFound() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + LocalDateTime.now(), LocalDateTime.now().plusHours(2)); + User user = createUser("testUser"); + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); + given(userRepository.findById(null)).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy(() -> tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user))) + .isInstanceOf(UserNotFoundException.class); + } + + @Test + @DisplayName("์ด๋ฏธ_์‹ ์ฒญํ•œ_ํ† ๋„ˆ๋จผํŠธ_์กด์žฌ") + void conflictedRegistration() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + LocalDateTime.now(), LocalDateTime.now().plusHours(2)); + User user = createUser("testUser"); + List tournamentUserList = new ArrayList<>(); + tournamentUserList.add(new TournamentUser(user, tournament, true, LocalDateTime.now())); + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); + given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); + given(tournamentUserRepository.findAllByUser(any(User.class))).willReturn(tournamentUserList); + + // when, then + assertThatThrownBy(() -> tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user))) + .isInstanceOf(TournamentConflictException.class); + } + } + + @Nested + @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ฐธ๊ฐ€_์ทจ์†Œ_ํ…Œ์ŠคํŠธ") + class CancelTournamentUserRegistration { + @Test + @DisplayName("์œ ์ €_์ฐธ๊ฐ€_์ทจ์†Œ_์„ฑ๊ณต") + void success() { + // given + Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, + LocalDateTime.now(), LocalDateTime.now().plusHours(2)); + User user = createUser("testUser"); + ReflectionUtilsForUnitTest.setFieldWithReflection(user, "id", 1L); + TournamentUser tournamentUser = new TournamentUser(user, tournament, true, LocalDateTime.now()); + given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); + + // when, then + tournamentService.cancelTournamentUserRegistration(tournament.getId(), UserDto.from(user)); + } + + @Test + @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") + void tournamentNotFound() { + // given + Long tournamentId = 1L; + User user = createUser("testUser"); + given(tournamentRepository.findById(tournamentId)).willReturn(Optional.empty()); + + // when, then + assertThatThrownBy( + () -> tournamentService.cancelTournamentUserRegistration(tournamentId, UserDto.from(user))) + .isInstanceOf(TournamentNotFoundException.class); + } + } + + @Nested + @DisplayName("startTournament") + class StartTournament { + @Test + @DisplayName("๊ธˆ์ผ ์ง„ํ–‰ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์—†์Œ") + void tournamentNotFound() { + //Arrange + List tournaments = new ArrayList<>(); + IntStream.range(0, 2).forEach((i) -> tournaments.add(i, mock(Tournament.class))); + + when(tournaments.get(0).getStartTime()).thenReturn(LocalDateTime.now().minusDays(1)); + when(tournaments.get(1).getStartTime()).thenReturn(LocalDateTime.now().plusDays(1)); + + when(tournamentRepository.findAllByStatus((TournamentStatus.BEFORE))).thenReturn(tournaments); + + //Act + tournamentService.startTournament(); + + //Assert + verify(tournaments.get(0), times(1)).getStartTime(); + verify(tournaments.get(1), times(1)).getStartTime(); + verify(tournaments.get(0), times(0)).updateStatus(TournamentStatus.LIVE); + verify(tournaments.get(1), times(0)).updateStatus(TournamentStatus.LIVE); + verify(notiAdminService, times(0)).sendAnnounceNotiToUser(any(SendNotiAdminRequestDto.class)); + verify(matchTournamentService, times(0)).matchGames(any(), any()); + } + + @Test + @DisplayName("๊ธˆ์ผ ์ง„ํ–‰ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ ๋ชจ๋‘ ์ธ์›์ˆ˜ ๋ฏธ๋‹ฌ") + void everyTournamentNotFull() { + //Arrange + User user = mock(User.class); + List tournaments = new ArrayList<>(); + List tournamentUsers = new ArrayList<>(); + IntStream.range(0, 2).forEach((i) -> tournaments.add(i, mock(Tournament.class))); + IntStream.range(0, 7).forEach((i) -> tournamentUsers.add(i, mock(TournamentUser.class))); + + when(user.getIntraId()).thenReturn("testUser"); + when(tournaments.get(0).getStartTime()).thenReturn(LocalDateTime.now()); + when(tournaments.get(1).getStartTime()).thenReturn(LocalDateTime.now()); + when(tournamentRepository.findAllByStatus((TournamentStatus.BEFORE))).thenReturn(tournaments); + + tournaments.stream().forEach((t) -> when(t.getTournamentUsers()).thenReturn(tournamentUsers)); + + tournamentUsers.stream().forEach((t) -> when(t.getIsJoined()).thenReturn(true)); + tournamentUsers.stream().forEach((t) -> when(t.getUser()).thenReturn(user)); + + //Act + tournamentService.startTournament(); + + //Assert + verify(tournaments.get(0), times(1)) + .getStartTime(); + verify(tournaments.get(1), times(1)) + .getStartTime(); + verify(tournaments.get(0), times(0)) + .updateStatus(TournamentStatus.LIVE); + verify(tournaments.get(1), times(0)) + .updateStatus(TournamentStatus.LIVE); + verify(notiAdminService, times(14)) + .sendAnnounceNotiToUser(any(SendNotiAdminRequestDto.class)); + verify(matchTournamentService, times(0)) + .matchGames(any(), any()); + } + + @Test + @DisplayName("ํ•˜๋‚˜๋งŒ ์ธ์›์ˆ˜ ๋ฏธ๋‹ฌ") + void oneTournamentNotFull() { + //Arrange + User user = mock(User.class); + List tournaments = new ArrayList<>(); + List notFullTournamentUsers = new ArrayList<>(); + List fullTournamentUsers = new ArrayList<>(); + IntStream.range(0, 2).forEach((i) -> tournaments.add(i, mock(Tournament.class))); + IntStream.range(0, 7).forEach((i) -> notFullTournamentUsers.add(i, mock(TournamentUser.class))); + IntStream.range(0, 16).forEach((i) -> fullTournamentUsers.add(i, mock(TournamentUser.class))); + + when(user.getIntraId()).thenReturn("testUser"); + when(tournaments.get(0).getStartTime()).thenReturn(LocalDateTime.now()); + when(tournaments.get(1).getStartTime()).thenReturn(LocalDateTime.now()); + when(tournamentRepository.findAllByStatus((TournamentStatus.BEFORE))).thenReturn(tournaments); + + when(tournaments.get(0).getTournamentUsers()).thenReturn(notFullTournamentUsers); + when(tournaments.get(1).getTournamentUsers()).thenReturn(fullTournamentUsers); + + IntStream.range(0, 4).forEach((i) -> when(notFullTournamentUsers.get(i).getIsJoined()).thenReturn(true)); + IntStream.range(0, 4).forEach((i) -> when(notFullTournamentUsers.get(i).getUser()).thenReturn(user)); + IntStream.range(4, 7).forEach((i) -> when(notFullTournamentUsers.get(i).getIsJoined()).thenReturn(false)); + + //Act + tournamentService.startTournament(); + + //Assert + verify(tournaments.get(0), times(1)) + .getStartTime(); + verify(tournaments.get(1), times(1)) + .getStartTime(); + verify(tournaments.get(0), times(0)) + .updateStatus(TournamentStatus.LIVE); + verify(tournaments.get(1), times(1)) + .updateStatus(TournamentStatus.LIVE); + verify(notiAdminService, times(4)) + .sendAnnounceNotiToUser(any(SendNotiAdminRequestDto.class)); + verify(matchTournamentService, times(1)) + .matchGames(any(), any()); + } + } + + @Nested + @DisplayName("getTournamentGames") + class GetTournamentGames { + + List existTournamentGames; + + void init() { + existTournamentGames = new ArrayList<>(); + + IntStream.range(0, 7) + .forEach((i) -> existTournamentGames.add(i, mock(TournamentGame.class))); + when(existTournamentGames.get(0).getTournamentRound()).thenReturn( + TournamentRound.QUARTER_FINAL_4); + when(existTournamentGames.get(1).getTournamentRound()).thenReturn( + TournamentRound.QUARTER_FINAL_3); + when(existTournamentGames.get(2).getTournamentRound()).thenReturn( + TournamentRound.QUARTER_FINAL_2); + when(existTournamentGames.get(3).getTournamentRound()).thenReturn( + TournamentRound.QUARTER_FINAL_1); + when(existTournamentGames.get(4).getTournamentRound()).thenReturn( + TournamentRound.SEMI_FINAL_2); + when(existTournamentGames.get(5).getTournamentRound()).thenReturn( + TournamentRound.SEMI_FINAL_1); + when(existTournamentGames.get(6).getTournamentRound()).thenReturn( + TournamentRound.THE_FINAL); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์กด์žฌํ•˜์ง€ ์•Š์Œ") + void tournamentGameNotExist() { + // given + Long tournamentId = 1L; + List tournamentGames = new ArrayList<>(); + when(tournamentGameRepository.findAllByTournamentId(any(Long.class))).thenReturn( + tournamentGames); + + // when + TournamentGameListResponseDto result = tournamentService.getTournamentGames( + tournamentId); + + // then + Assertions.assertThat(result.getGames()).isEmpty(); + Assertions.assertThat(result.getTournamentId()).isEqualTo(tournamentId); + verify(tournamentGameRepository, times(1)).findAllByTournamentId(any(Long.class)); + verify(gameRepository, times(0)).findTeamsByGameId(any(Long.class)); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์กด์žฌํ•˜์ง€๋งŒ ๊ฒŒ์ž„ ์กด์žฌํ•˜์ง€ ์•Š์Œ") + void tournamentGameExistGameNotExist() { + // given + init(); + Long tournamentId = 1L; + when(tournamentGameRepository.findAllByTournamentId(any(Long.class))).thenReturn( + existTournamentGames); + + // when + TournamentGameListResponseDto result = tournamentService.getTournamentGames( + tournamentId); + + // then + Assertions.assertThat(result.getGames()).size().isEqualTo(7); + Assertions.assertThat(result.getTournamentId()).isEqualTo(tournamentId); + verify(tournamentGameRepository, times(1)).findAllByTournamentId(any(Long.class)); + verify(gameRepository, times(0)).findTeamsByGameId(any(Long.class)); + } + + @Test + @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„, ๊ฒŒ์ž„ ๋ชจ๋‘ ์กด์žฌ") + void tournamentGameAndGameExist() { + // given + init(); + Long tournamentId = 1L; + + GameTeamUser gameTeamUser = mock(GameTeamUser.class); + when(tournamentGameRepository.findAllByTournamentId(any(Long.class))).thenReturn( + existTournamentGames); + when(gameRepository.findTeamsByGameId(any(Long.class))).thenReturn( + Optional.of(gameTeamUser)); + when(gameTeamUser.getStatus()).thenReturn(StatusType.LIVE); + + IntStream.range(0, 7).forEach((i) -> { + when(existTournamentGames.get(i).getGame()).thenReturn(mock(Game.class)); + when(existTournamentGames.get(i).getGame().getId()).thenReturn((long)i); + }); + + // when + TournamentGameListResponseDto result = tournamentService.getTournamentGames( + tournamentId); + + // then + Assertions.assertThat(result.getGames()).size().isEqualTo(7); + Assertions.assertThat(result.getTournamentId()).isEqualTo(tournamentId); + verify(tournamentGameRepository, times(1)).findAllByTournamentId(any(Long.class)); + verify(gameRepository, times(7)).findTeamsByGameId(any(Long.class)); + } + } + + private Tournament createTournament(Long id, TournamentStatus status, LocalDateTime startTime, + LocalDateTime endTime) { + Tournament tournament = Tournament.builder() + .title(id + "st tournament") + .contents("") + .startTime(startTime) + .endTime(endTime) + .type(TournamentType.ROOKIE) + .status(status) + .build(); + ReflectionUtilsForUnitTest.setFieldWithReflection(tournament, "id", id); + return tournament; + } + + /** + * ์œ ์ € ์ƒ์„ฑ ๋งค์„œ๋“œ - intraId๋กœ๋งŒ ์ดˆ๊ธฐํ™” + * @param intraId + * @return + */ + private User createUser(String intraId) { + return User.builder() + .eMail("email") + .intraId(intraId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/controller/UserControllerTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/controller/UserControllerTest.java new file mode 100644 index 000000000..7553d1f94 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/controller/UserControllerTest.java @@ -0,0 +1,613 @@ +package gg.pingpong.api.user.user.controller; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Optional; + +import org.apache.http.HttpHeaders; +import org.assertj.core.api.Assertions; +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.store.Item; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.store.type.ItemType; +import gg.data.user.User; +import gg.data.user.type.BackgroundType; +import gg.data.user.type.EdgeType; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.global.utils.UserImageHandler; +import gg.pingpong.api.user.game.controller.request.RankResultReqDto; +import gg.pingpong.api.user.game.service.GameService; +import gg.pingpong.api.user.store.service.CoinHistoryService; +import gg.pingpong.api.user.user.controller.request.UserModifyRequestDto; +import gg.pingpong.api.user.user.controller.response.CoinHistoryResponseDto; +import gg.pingpong.api.user.user.controller.response.UserAttendanceResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinHistoryListResponseDto; +import gg.pingpong.api.user.user.controller.response.UserCoinResponseDto; +import gg.pingpong.api.user.user.controller.response.UserDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserHistoryResponseDto; +import gg.pingpong.api.user.user.controller.response.UserLiveResponseDto; +import gg.pingpong.api.user.user.controller.response.UserNormalDetailResponseDto; +import gg.pingpong.api.user.user.controller.response.UserRankResponseDto; +import gg.pingpong.api.user.user.controller.response.UserSearchResponseDto; +import gg.pingpong.api.user.user.dto.UserTextColorDto; +import gg.repo.game.GameRepository; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.repo.store.CoinHistoryRepository; +import gg.repo.store.CoinPolicyRepository; +import gg.repo.store.ReceiptRepository; +import gg.repo.user.UserRepository; +import gg.utils.ItemTestUtils; +import gg.utils.RedisKeyManager; +import gg.utils.TestDataUtils; +import gg.utils.annotation.IntegrationTest; +import gg.utils.dto.GameInfoDto; +import gg.utils.exception.user.UserNotFoundException; +import lombok.extern.slf4j.Slf4j; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@Slf4j +class UserControllerTest { + + @Autowired + TestDataUtils testDataUtils; + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Autowired + AuthTokenProvider tokenProvider; + + @Autowired + UserRepository userRepository; + + @Autowired + RankRedisRepository redisRepository; + + @Autowired + TierRepository tierRepository; + + @Autowired + RankRepository rankRepository; + + @Autowired + SeasonRepository seasonRepository; + + @Autowired + GameRepository gameRepository; + + @Autowired + GameService gameService; + + @Autowired + CoinPolicyRepository coinPolicyRepository; + + @Autowired + CoinHistoryRepository coinHistoryRepository; + + @Autowired + ReceiptRepository receiptRepository; + + @Autowired + CoinHistoryService coinHistoryService; + @Autowired + ItemTestUtils itemTestUtils; + @MockBean + UserImageHandler userImageHandler; + User admin; + + @BeforeEach + public void setUp() { + testDataUtils.createTierSystem("pingpong"); + testDataUtils.createSeason(); + admin = testDataUtils.createAdminUserForItem(); + } + + @AfterEach + public void flushRedis() { + redisRepository.deleteAll(); + } + + @Test + @DisplayName("live") + public void userLiveTest() throws Exception { + String accessToken = testDataUtils.getLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + String liveUrl = "/pingpong/users/live"; + String event = "game"; + int notiCnt = 2; + Mode currentMatchMode = Mode.RANK; + GameInfoDto gameInfo = testDataUtils.addMockDataUserLiveApi(event, notiCnt, currentMatchMode.getCode(), userId); + Game testGame = gameRepository.getById(gameInfo.getGameId()); + + // Rank Live ๊ฒŒ์ž„ ํ…Œ์ŠคํŠธ + String contentAsString1 = mockMvc.perform( + get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto1 = objectMapper.readValue(contentAsString1, UserLiveResponseDto.class); + assertThat(userLiveResponseDto1.getEvent()).isEqualTo(event); + assertThat(userLiveResponseDto1.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto1.getCurrentMatchMode()).isEqualTo(currentMatchMode); + assertThat(userLiveResponseDto1.getGameId()).isEqualTo(gameInfo.getGameId()); + + // Rank ์ ์ˆ˜ ์ž…๋ ฅ ํ…Œ์ŠคํŠธ + RankResultReqDto rankResultReqDto = new RankResultReqDto(gameInfo.getGameId(), + gameInfo.getEnemyTeamId(), 1, + gameInfo.getMyTeamId(), 2); + assertThat(testGame.getStatus()).isEqualTo(StatusType.LIVE); + gameService.createRankResult(rankResultReqDto, gameInfo.getEnemyUserId()); + assertThat(testGame.getStatus()).isEqualTo(StatusType.END); + + String contentAsString2 = mockMvc.perform( + get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto2 = objectMapper.readValue(contentAsString2, UserLiveResponseDto.class); + assertThat(userLiveResponseDto2.getEvent()).isEqualTo(event); + assertThat(userLiveResponseDto2.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto2.getCurrentMatchMode()).isEqualTo(currentMatchMode); + assertThat(userLiveResponseDto2.getGameId()).isEqualTo(gameInfo.getGameId()); + + // Rank PChange is_checked ํ…Œ์ŠคํŠธ + String contentAsString3 = mockMvc.perform( + get(liveUrl).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserLiveResponseDto userLiveResponseDto3 = objectMapper.readValue(contentAsString3, UserLiveResponseDto.class); + assertThat(userLiveResponseDto3.getEvent()).isEqualTo(null); + assertThat(userLiveResponseDto3.getNotiCount()).isEqualTo(notiCnt); + assertThat(userLiveResponseDto3.getCurrentMatchMode()).isEqualTo(null); + assertThat(userLiveResponseDto3.getGameId()).isEqualTo(null); + } + + @Test + @DisplayName("GET /pingpong/users") + public void userNormalDetail() throws Exception { + //given + String url = "/pingpong/users"; + String intraId = "intra"; + String email = "email"; + // String imageUrl = "imageUrl"; + + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.ADMIN); + Season season = testDataUtils.createSeason(); + + String accessToken = tokenProvider.createToken(newUser.getId()); + Tier tier = tierRepository.findStartTier().get(); + testDataUtils.createUserRank(newUser, "statusMessage", season, tier); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserNormalDetailResponseDto responseDto = objectMapper.readValue(contentAsString, + UserNormalDetailResponseDto.class); + + //then + assertThat(responseDto.getIntraId()).isEqualTo(intraId); + // assertThat(responseDto.getUserImageUri()).isEqualTo(imageUrl); + assertThat(responseDto.getIsAdmin()).isTrue(); + assertThat(responseDto.getIsAttended()); + } + + @Test + @DisplayName("searches?intraId=${IntraId}") + public void searchUser() throws Exception { + //given + String[] intraId = {"intraId", "2intra2", "2intra", "aaaa", "bbbb"}; + String email = "email"; + User user = null; + for (String intra : intraId) { + user = testDataUtils.createNewUser(intra, email, RacketType.PENHOLDER, + SnsType.BOTH, RoleType.ADMIN); + } + String accessToken = tokenProvider.createToken(user.getId()); + String keyWord = "intra"; + String url = "/pingpong/users/searches?intraId=" + keyWord; + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserSearchResponseDto userSearchResponseDto = objectMapper.readValue(contentAsString, + UserSearchResponseDto.class); + + //then + assertThat(userSearchResponseDto.getUsers().size()).isEqualTo(3); + } + + @Test + @DisplayName("[GET] {targetId}") + public void getUserDetail() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + String statusMessage = "statusMessage"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String accessToken = tokenProvider.createToken(newUser.getId()); + Tier tier = tierRepository.findStartTier().get(); + testDataUtils.createUserRank(newUser, statusMessage, season, tier); + String url = "/pingpong/users/" + newUser.getIntraId(); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserDetailResponseDto responseDto = objectMapper.readValue(contentAsString, UserDetailResponseDto.class); + + //then + Assertions.assertThat(responseDto.getIntraId()).isEqualTo(intraId); + Assertions.assertThat(responseDto.getStatusMessage()).isEqualTo(statusMessage); + Assertions.assertThat(responseDto.getLevel()).isEqualTo(1); + Assertions.assertThat(responseDto.getCurrentExp()).isEqualTo(0); + System.out.println(responseDto); + } + + @Test + @DisplayName("/{intraId}/rank?season={seasonId}") + public void userRankDetail() throws Exception { + //given + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + String accessToken = tokenProvider.createToken(newUser.getId()); + testDataUtils.createUserRank(newUser, "statusMessage", season); + + //when + String url = "/pingpong/users/" + newUser.getIntraId() + "/rank?season=" + season.getId(); + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserRankResponseDto responseDto = objectMapper.readValue(contentAsString, UserRankResponseDto.class); + + //then + Assertions.assertThat(responseDto.getRank()).isEqualTo(-1); + Assertions.assertThat(responseDto.getWins()).isEqualTo(0); + Assertions.assertThat(responseDto.getLosses()).isEqualTo(0); + Assertions.assertThat(responseDto.getPpp()).isEqualTo(season.getStartPpp()); + System.out.println(responseDto); + } + + @Test + @DisplayName("/{intraId}/historics?season={seasonId}") + public void getUserHistory() throws Exception { + //given + Season season = testDataUtils.createSeason(); + User newUser = testDataUtils.createNewUser(); + String accessToken = tokenProvider.createToken(newUser.getId()); + + LocalDateTime startTime = LocalDateTime.now().minusDays(1); + LocalDateTime endTime = startTime.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime, endTime); + + LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); + LocalDateTime endTime1 = startTime1.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); + + LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); + LocalDateTime endTime2 = startTime2.plusMinutes(15); + testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); + + String url = "/pingpong/users/" + newUser.getIntraId() + "/historics?season=" + season.getId(); + + //when + String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + UserHistoryResponseDto responseDto = objectMapper.readValue(contentAsString, UserHistoryResponseDto.class); + + //then + Assertions.assertThat(responseDto.getHistorics().size()).isEqualTo(3); + // List historics = responseDto.getHistorics(); + // findPChangesHistory ์—๋Š” ์ •๋ ฌํ•œ๋‹ค๋Š” ๋‚ด์šฉ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™์•„ ๋ณด๋ฅ˜ + // Assertions.assertThat(historics) + // .isSortedAccordingTo(Comparator.comparing(UserHistoryData::getDate)); + } + + @Test + @DisplayName("[put] {intraId}") + public void updateUser() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + String imageUrl = "imageUrl"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + String url = "/pingpong/users/" + newUser.getIntraId(); + + String newStatusMessage = "newStatusMessage"; + RacketType newRacketType = RacketType.SHAKEHAND; + SnsType newSnsType = SnsType.SLACK; + + //when + mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content( + objectMapper.writeValueAsString(new UserModifyRequestDto(newRacketType, newStatusMessage, + newSnsType)))) + .andExpect(status().isNoContent()); + //then + String hashKey = RedisKeyManager.getHashKey(season.getId()); + RankRedis rank = redisRepository.findRankByUserId(hashKey, newUser.getId()); + Optional rankOptional = rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()); + + if (rankOptional.isPresent()) { + Rank rank1 = rankOptional.get(); + Assertions.assertThat(rank1.getStatusMessage()).isEqualTo(newStatusMessage); + } else { + Assertions.fail("๋žญํฌ ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); + } + + Optional userOptional = userRepository.findById(newUser.getId()); + + if (userOptional.isPresent()) { + User user = userOptional.get(); + Assertions.assertThat(user.getRacketType()).isEqualTo(newRacketType); + Assertions.assertThat(user.getSnsNotiOpt()).isEqualTo(newSnsType); + Assertions.assertThat(rank.getStatusMessage()).isEqualTo(newStatusMessage); + } else { + Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); + } + + } + + @Test + @DisplayName("[post] /attendance") + public void attendUserTest() throws Exception { + //given + testDataUtils.createCoinPolicy(admin, 1, 0, 0, 0); + String accessToken = testDataUtils.getLoginAccessToken(); + String url = "/pingpong/users/attendance"; + + //when + String contentAsString = mockMvc.perform( + post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + UserAttendanceResponseDto result = objectMapper.readValue(contentAsString, UserAttendanceResponseDto.class); + + //then + System.out.println(result.getAfterCoin()); + Assertions.assertThat(result.getAfterCoin() - result.getBeforeCoin()).isEqualTo(result.getCoinIncrement()); + } + + @Test + @DisplayName("[patch] text-color") + public void updateTextColorTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, + RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + String url = "/pingpong/users/text-color"; + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", + "subContent", 100, 50, ItemType.TEXT_COLOR); + Item item = itemTestUtils.createItem(admin, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + // Receipt receipt = receiptRepository.findById(4L).get(); + String newTextColor = "#FFFFFF"; + + //when + mockMvc.perform(patch(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new UserTextColorDto(receipt.getId(), newTextColor)))) + .andExpect(status().is2xxSuccessful()); + //then + Optional userOptional = userRepository.findById(newUser.getId()); + + if (userOptional.isPresent()) { + User user = userOptional.get(); + Assertions.assertThat(user.getTextColor()).isEqualTo(newTextColor); + } else { + Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); + } + + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[patch] edge") + public void updateEdgeTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, + RoleType.USER); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", + "subContent", 100, 50, ItemType.EDGE); + Item item = itemTestUtils.createItem(admin, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + // Receipt receipt = receiptRepository.findById(3L).get(); + String url = "/pingpong/users/edge"; + + //when + mockMvc.perform(patch(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(objectMapper.writeValueAsString(receipt.getId())) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + log.info("user.getEdge() : {}", newUser.getEdge()); + Optional userOptional = userRepository.findById(newUser.getId()); + + if (userOptional.isPresent()) { + User user = userOptional.get(); + boolean isEdgeTypeValid = Arrays.stream(EdgeType.values()).anyMatch(v -> v.equals(user.getEdge())); + Assertions.assertThat(isEdgeTypeValid).isEqualTo(true); + } else { + Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); + } + + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[get]/pingpong/users/coin") + public void getUserCoin() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + + String url = "/pingpong/users/coin"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + UserCoinResponseDto result = objectMapper.readValue(contentAsString, UserCoinResponseDto.class); + int userCoin = userRepository.findById(userId).orElseThrow(UserNotFoundException::new).getGgCoin(); + assertThat(result.getCoin()).isEqualTo(userCoin); + System.out.println(userCoin); + } + + @Test + @DisplayName("[patch] background") + public void updateBackgroundTest() throws Exception { + //given + Season season = testDataUtils.createSeason(); + String intraId = "intraId"; + String email = "email"; + User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, + RoleType.USER); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", + "subContent", 100, 50, ItemType.BACKGROUND); + Item item = itemTestUtils.createItem(admin, dto); + Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); + String statusMessage = "statusMessage"; + testDataUtils.createUserRank(newUser, statusMessage, season); + String accessToken = tokenProvider.createToken(newUser.getId()); + + // Receipt receipt = receiptRepository.findById(2L).get(); + String uri = "/pingpong/users/background"; + + //when + mockMvc.perform(patch(uri) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .content(objectMapper.writeValueAsString(receipt.getId())) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + //then + log.info("user.getBackground() : {}", newUser.getBackground()); + Optional userOptional = userRepository.findById(newUser.getId()); + + if (userOptional.isPresent()) { + User user = userOptional.get(); + boolean isBackgroundTypeValid = Arrays + .stream(BackgroundType.values()).anyMatch(v -> v.equals(user.getBackground())); + Assertions.assertThat(isBackgroundTypeValid).isEqualTo(true); + } else { + Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); + } + + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } + + @Test + @DisplayName("[get]/pingpong/users/coinhistory") + public void getUserCoinHistory() throws Exception { + String accessToken = testDataUtils.getAdminLoginAccessToken(); + Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); + User user = userRepository.getById(userId); + testDataUtils.createCoinPolicy(admin, 0, 1, 3, 2); + + coinHistoryService.addNormalCoin(user); + coinHistoryService.addRankWinCoin(user); + coinHistoryService.addNormalCoin(user); + String url = "/pingpong/users/coinhistory?page=1&size=5"; + + String contentAsString = mockMvc.perform(get(url) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + + UserCoinHistoryListResponseDto result = objectMapper.readValue(contentAsString, + UserCoinHistoryListResponseDto.class); + + System.out.println(result.getTotalPage()); + for (CoinHistoryResponseDto temp : result.getUseCoinList()) { + System.out.println(temp.getHistory() + " " + temp.getAmount() + " " + temp.getCreatedAt()); + } + } + + @Test + @DisplayName("[post]/pingpong/users/profile-image") + public void getUserImage() throws Exception { + String mockS3Path = "mockS3Path"; + Mockito.when(userImageHandler + .uploadToS3(Mockito.any(MultipartFile.class), Mockito.any(String.class))) + .thenReturn(mockS3Path); + // String accessToken = testDataUtils.getLoginAccessToken(); + ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", + "subContent", 100, 50, ItemType.PROFILE_IMAGE); + Item item = itemTestUtils.createItem(admin, dto); + User user = testDataUtils.createNewUser(); + testDataUtils.createUserImage(user); + String accessToken = testDataUtils.getLoginAccessTokenFromUser(user); + Receipt receipt = itemTestUtils.purchaseItem(user, user, item); + // Receipt receipt = receiptRepository.findById(7L).orElseThrow(ReceiptNotFoundException::new); + MockMultipartFile image = new MockMultipartFile("profileImage", "imagefile.jpeg", "image/jpeg", + "<>".getBytes()); + MockMultipartFile jsonFile = new MockMultipartFile("userProfileImageRequestDto", "", "application/json", + ("{\"receiptId\": " + receipt.getId() + "}").getBytes()); + + String contentAsString = mockMvc.perform(multipart("/pingpong/users/profile-image") + .file(image) + .file(jsonFile) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) + .andExpect(status().isNoContent()) + .andReturn().getResponse().getContentAsString(); + AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserAuthenticationServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserAuthenticationServiceUnitTest.java new file mode 100644 index 000000000..7a24f2f2c --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserAuthenticationServiceUnitTest.java @@ -0,0 +1,65 @@ +package gg.pingpong.api.user.user.service; + +import static org.mockito.Mockito.*; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import gg.pingpong.api.global.security.jwt.repository.JwtRedisRepository; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.utils.annotation.UnitTest; +import gg.utils.exception.user.TokenNotValidException; + +@UnitTest +@ExtendWith(MockitoExtension.class) +class UserAuthenticationServiceUnitTest { + @Mock + JwtRedisRepository jwtRedisRepository; + + @Mock + AuthTokenProvider tokenProvider; + + @InjectMocks + UserAuthenticationService userAuthenticationService; + + @Nested + @DisplayName("regenerate") + class Regenerate { + @Test + @DisplayName("์ƒˆ๋กœ์šด access token ๋ฐ˜ํ™˜") + void generateNewAccessToken() { + //Arrange + String refreshToken = "valid token"; + String newAccessToken = "new_access_token"; + Long userId = 1L; + + when(jwtRedisRepository.getUserIdFromRefToken(refreshToken)).thenReturn(userId); + when(tokenProvider.createToken(userId)).thenReturn(newAccessToken); + + //Act + String accessToken = userAuthenticationService.regenerate(refreshToken); + + //Assert + Assertions.assertThat(accessToken).isEqualTo(newAccessToken); + } + + @Test + @DisplayName("์œ ํšจํ•˜์ง€ ์•Š์€ refreshToken TokenNotValidException ๋ฐœ์ƒ") + void refreshTokenInvalid() { + //Arrange + String refreshToken = "invalid token"; + + when(jwtRedisRepository.getUserIdFromRefToken(refreshToken)).thenReturn(null); + + //Act, Assert + Assertions.assertThatThrownBy(() -> userAuthenticationService.regenerate(refreshToken)) + .isInstanceOf(TokenNotValidException.class); + } + } +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserFindServiceUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserFindServiceUnitTest.java new file mode 100644 index 000000000..470676fcd --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/user/user/service/UserFindServiceUnitTest.java @@ -0,0 +1,8 @@ +package gg.pingpong.api.user.user.service; + +import gg.utils.annotation.UnitTest; + +@UnitTest +class UserFindServiceUnitTest { + +} diff --git a/gg-pingpong-api/src/test/java/gg/pingpong/api/utils/ReflectionUtilsForUnitTest.java b/gg-pingpong-api/src/test/java/gg/pingpong/api/utils/ReflectionUtilsForUnitTest.java new file mode 100644 index 000000000..2d1664ee9 --- /dev/null +++ b/gg-pingpong-api/src/test/java/gg/pingpong/api/utils/ReflectionUtilsForUnitTest.java @@ -0,0 +1,30 @@ +package gg.pingpong.api.utils; + +import java.lang.reflect.Field; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +/** + * ReflectionUtilsForUnitTest. + * + *

+ * ์œ ๋‹› ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋ฆฌํ”Œ๋ ‰์…˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ + *

+ * + */ +public class ReflectionUtilsForUnitTest { + + /** + * ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด์„œ ํ•„๋“œ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค. + */ + public static void setFieldWithReflection(Object object, String fieldName, Object value) { + try { + Field field = object.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(object, value); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new BusinessException(ErrorCode.BAD_REQUEST); + } + } +} diff --git a/src/test/resources/application.yml b/gg-pingpong-api/src/test/resources/application.yml similarity index 99% rename from src/test/resources/application.yml rename to gg-pingpong-api/src/test/resources/application.yml index 4bad41a72..f28374ce9 100644 --- a/src/test/resources/application.yml +++ b/gg-pingpong-api/src/test/resources/application.yml @@ -155,6 +155,7 @@ cors: logging-level: org.hibernate.SQL: debug + org.hibernate.type: trace slack: xoxbToken: "dummy" diff --git a/gg-repo/build.gradle b/gg-repo/build.gradle new file mode 100644 index 000000000..d268dd7ee --- /dev/null +++ b/gg-repo/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' +} + +group 'gg.pingpong.repo' +version '42gg' + +repositories { + mavenCentral() +} + +dependencies { + /* database */ + runtimeOnly 'mysql:mysql-connector-java' + /* flyway */ + implementation 'org.flywaydb:flyway-core' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + testImplementation testFixtures(project(':gg-utils')) +} + +test { + useJUnitPlatform() +} diff --git a/gg-repo/src/main/java/gg/repo/game/GameRepository.java b/gg-repo/src/main/java/gg/repo/game/GameRepository.java new file mode 100644 index 000000000..f27d5bc27 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/GameRepository.java @@ -0,0 +1,126 @@ +package gg.repo.game; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import javax.persistence.LockModeType; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.game.Game; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.repo.game.out.GameTeamUser; +import gg.repo.game.out.GameTeamUserInfo; +import gg.repo.game.out.GameUser; + +public interface GameRepository extends JpaRepository, GameRepositoryCustom { + Slice findAllByModeAndStatus(Mode mode, StatusType status, Pageable pageable); + + // Slice findAllByStatus(StatusType status, Pageable pageable); + + // Slice findAllByStatusIn(List statusList, Pageable pageable); + + Slice findAllByModeAndStatusAndSeasonId(Mode mode, StatusType status, Long season, Pageable pageable); + + Slice findAllByModeInAndStatusIn(List modeList, List statusList, Pageable pageable); + + Slice findAllByModeInAndStatus(List modeList, StatusType status, Pageable pageable); + + @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + + "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, " + + "t1.wins t1Wins, t1.losses t1Losses, " + + "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.wins t2Wins, t2.losses t2Losses, " + + "t2.image t2Image, t2.total_exp t2Exp " + + "from v_rank_game_detail t1, v_rank_game_detail t2 " + + "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsIn(@Param("games") List games); + + @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + + "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, " + + "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.image t2Image, t2.total_exp t2Exp " + + "from v_teamuser t1, v_teamuser t2 " + + "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsInAndNormalMode(@Param("games") List games); + + @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + + "t1.intraId t1IntraId, t1.teamId t1TeamId, t1.win t1IsWin, t1.score t1Score, " + + "t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + + "t2.win t2IsWin, t2.teamId t2TeamId, t2.score t2Score, t2.intraId t2IntraId, " + + "t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + + "from v_rank_game_detail t1, v_rank_game_detail t2 " + + "where t1.gameId = (:gameId) and t1.teamId findTeamsByGameId(@Param("gameId") Long gameId); + + @Query(value = "SELECT teamId, gameId, score, startTime, status, mode, userId, intraId, image, total_exp exp" + + " FROM v_teamuser where gameId = :gameId", nativeQuery = true) + List findTeamGameUser(@Param("gameId") Long gameId); + + Optional findByStartTime(LocalDateTime startTime); + + @Query(value = "select g from Game g where g.startTime > :startTime and g.startTime < :endTime") + List findAllBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); + + @Query(value = "select g from Game g where (g.startTime between :startTime and :endTime) " + + "or (g.endTime between :startTime and :endTime) " + + "or (:startTime between g.startTime and g.endTime) " + + "or (:endTime between g.startTime and g.endTime)") + List findAllBetweenTournament(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + @Query(value = + "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.startTime > :startTime AND g.startTime < :endTime " + + "AND g.id = t.game.id AND t.id = tu.team.id AND tu.user.id = :userId") + Optional findByUserInSlots(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, @Param("userId") Long userId); + + @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.status = :status AND g.id = t.game.id" + + " AND t.id = tu.team.id AND tu.user.id = :userId") + Optional findByStatusTypeAndUserId(@Param("status") StatusType status, @Param("userId") Long userId); + + @Query(value = "select gameId " + + "from v_teamuser " + + "where intraId = :intra and mode in (:mode) and status in(:status)", nativeQuery = true) + Slice findGamesByUserAndModeInAndStatusIn(@Param("intra") String intra, @Param("mode") List mode, + @Param("status") List status, Pageable pageable); + + @Query(value = "select gameId " + + "from v_teamuser " + + "where intraId=:intra and mode=:mode and status=:status", nativeQuery = true) + Slice findGamesByUserAndModeAndStatus(@Param("intra") String intra, @Param("mode") String mode, + @Param("status") String status, Pageable pageable); + + @Query(value = "select gameId " + + "from v_teamuser " + + "where intraId = :intra and mode=:mode and seasonId = :seasonId and status = :status", nativeQuery = true) + Slice findGamesByUserAndModeAndSeason(@Param("intra") String intra, @Param("mode") String mode, + @Param("seasonId") Long seasonId, @Param("status") String status, Pageable pageable); + + List findAllByStatusAndStartTimeLessThanEqual(StatusType status, LocalDateTime startTime); + + List findAllByStatusAndEndTimeLessThanEqual(StatusType status, LocalDateTime endTime); + + @Query(value = "SELECT u.id userId, u.e_mail email, u.intra_id intraId, u.sns_noti_opt snsNotiOpt, g.id gameId " + + "FROM " + + "(SELECT id, status FROM game where start_time<=:time) g, " + + "team t, team_user tu, user u " + + "WHERE g.id=t.game_id AND t.id = tu.team_id AND tu.user_id=u.id AND g.status = 'BEFORE'", nativeQuery = true) + List findAllByStartTimeLessThanEqual(@Param("time") LocalDateTime time); + + @Lock(LockModeType.PESSIMISTIC_WRITE) + Optional findWithPessimisticLockById(Long gameId); + + @Override + @EntityGraph(attributePaths = {"season"}) + Optional findById(Long gameId); +} diff --git a/gg-repo/src/main/java/gg/repo/game/GameRepositoryCustom.java b/gg-repo/src/main/java/gg/repo/game/GameRepositoryCustom.java new file mode 100644 index 000000000..1b8b7b7dc --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/GameRepositoryCustom.java @@ -0,0 +1,9 @@ +package gg.repo.game; + +import java.util.Optional; + +import gg.data.game.Game; + +public interface GameRepositoryCustom { + Optional getLatestGameByUser(Long userId); +} diff --git a/gg-repo/src/main/java/gg/repo/game/GameRepositoryImpl.java b/gg-repo/src/main/java/gg/repo/game/GameRepositoryImpl.java new file mode 100644 index 000000000..d357d1600 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/GameRepositoryImpl.java @@ -0,0 +1,31 @@ +package gg.repo.game; + +import java.util.Optional; + +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; + +import gg.data.game.Game; +import gg.data.game.TeamUser; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class GameRepositoryImpl implements GameRepositoryCustom { + private final EntityManager em; + + @Override + public Optional getLatestGameByUser(Long userId) { + String sql = "select tu from TeamUser tu join fetch tu.user join fetch tu.team " + + "join tu.team.game g where tu.user.id =: userId order by g.startTime desc"; + + try { + TeamUser teamUser = em.createQuery(sql, TeamUser.class).setParameter("userId", userId) + .setFirstResult(0) + .setMaxResults(1) + .getSingleResult(); + return Optional.of(teamUser.getTeam().getGame()); + } catch (NoResultException e) { + return Optional.empty(); + } + } +} diff --git a/gg-repo/src/main/java/gg/repo/game/PChangeRepository.java b/gg-repo/src/main/java/gg/repo/game/PChangeRepository.java new file mode 100644 index 000000000..a31b85364 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/PChangeRepository.java @@ -0,0 +1,33 @@ +package gg.repo.game; + +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; + +import gg.data.game.PChange; +import gg.data.game.type.Mode; + +public interface PChangeRepository extends JpaRepository, PChangeRepositoryCustom { + + @Query(value = "SELECT pc FROM PChange pc join fetch pc.user " + + "WHERE pc.user.intraId LIKE %:intraId% " + + "order by pc.user.intraId asc, pc.id desc") + List findPChangesByUser_IntraId(@Param("intraId") String intraId); + + @Query(value = "SELECT pc FROM PChange pc join fetch pc.user WHERE pc.user.id =:userId order by pc.id desc") + List findAllByUserId(@Param("userId") Long userId); + + @Query(value = "SELECT pc FROM PChange pc join fetch pc.user join fetch pc.game " + + "WHERE pc.user.id = :userId and pc.game.mode in :modes " + + "order by pc.id desc") + List findAllByUserIdGameModeIn(@Param("userId") Long userId, @Param("modes") List modes); + + Optional findByUserIdAndGameId(Long userId, Long gameId); + + Optional findPChangeByUserIdAndGameId(Long userId, Long gameId); + + List findPChangesByGameId(Long gameId); +} diff --git a/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryCustom.java b/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryCustom.java new file mode 100644 index 000000000..a6bb3b1f6 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryCustom.java @@ -0,0 +1,13 @@ +package gg.repo.game; + +import java.util.List; + +import gg.data.game.PChange; + +public interface PChangeRepositoryCustom { + List findPChangesHistory(String intraId, Long seasonId); + + List findExpHistory(Long userId, Long gameId); + + List findPPPHistory(Long userId, Long gameId, Long seasonId); +} diff --git a/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryImpl.java b/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryImpl.java new file mode 100644 index 000000000..21275f7b3 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/PChangeRepositoryImpl.java @@ -0,0 +1,58 @@ +package gg.repo.game; + +import java.util.List; + +import javax.persistence.EntityManager; + +import org.springframework.stereotype.Repository; + +import gg.data.game.PChange; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Repository +@RequiredArgsConstructor +@Slf4j +public class PChangeRepositoryImpl implements PChangeRepositoryCustom { + private final EntityManager em; + + @Override + public List findPChangesHistory(String intraId, Long seasonId) { + String sql = "select p from PChange p join p.game g join p.user u join g.season s where u.intraId = " + + ":intra_id and s.id = :season_id and g.mode = 'RANK' order by p.createdAt desc"; + return em.createQuery(sql, PChange.class) + .setParameter("intra_id", intraId) + .setParameter("season_id", seasonId) + .setFirstResult(0) + .setMaxResults(10) + .getResultList(); + } + + @Override + public List findExpHistory(Long userId, Long gameId) { + String sql = "select p from PChange p join p.game g where p.user.id = " + + ":userId and p.id <= (select p2.id from PChange p2 where p2.game.id = :gameId and p2.user.id = :userId) " + + "order by p.createdAt desc"; + return em.createQuery(sql, PChange.class) + .setParameter("userId", userId) + .setParameter("gameId", gameId) + .setFirstResult(0) + .setMaxResults(2) + .getResultList(); + } + + @Override + public List findPPPHistory(Long userId, Long gameId, Long seasonId) { + String sql = "select p from PChange p join p.game g join g.season s where p.user.id = " + + ":userId and p.id <= (select p2.id from PChange p2 where p2.game.id = :gameId and p2.user.id =:userId) " + + "and p.game.mode = 'RANK' and s.id = :season_id " + + "order by p.createdAt desc"; + return em.createQuery(sql, PChange.class) + .setParameter("userId", userId) + .setParameter("gameId", gameId) + .setParameter("season_id", seasonId) + .setFirstResult(0) + .setMaxResults(2) + .getResultList(); + } +} diff --git a/gg-repo/src/main/java/gg/repo/game/TeamRepository.java b/gg-repo/src/main/java/gg/repo/game/TeamRepository.java new file mode 100644 index 000000000..80e97a020 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/TeamRepository.java @@ -0,0 +1,14 @@ +package gg.repo.game; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.game.Team; + +public interface TeamRepository extends JpaRepository { + @Query("select t from Team t where t.game.id=:gameId") + List findAllBy(@Param("gameId") Long gameId); +} diff --git a/gg-repo/src/main/java/gg/repo/game/TeamUserRepository.java b/gg-repo/src/main/java/gg/repo/game/TeamUserRepository.java new file mode 100644 index 000000000..ecb568782 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/TeamUserRepository.java @@ -0,0 +1,22 @@ +package gg.repo.game; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.game.TeamUser; + +public interface TeamUserRepository extends JpaRepository { + @Query(value = "select team_user.id, team_user.team_id, team_user.user_id from team, team_user " + + "where team.game_id =:gid and team.id = team_user.team_id", nativeQuery = true) + List findAllByGameId(@Param("gid") Long gid); + + @Query(value = "select count(*) from game, team, team_user " + + "where game.start_time >= :today and team_user.team_id = team.id and team_user.user_id = :userId " + + "and team.game_id = game.id and game.status = 'END'", nativeQuery = true) + Integer findByDateAndUser(@Param("today") LocalDateTime today, @Param("userId") Long userId); + +} diff --git a/gg-repo/src/main/java/gg/repo/game/out/GameTeamUser.java b/gg-repo/src/main/java/gg/repo/game/out/GameTeamUser.java new file mode 100644 index 000000000..0d4f1a010 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/out/GameTeamUser.java @@ -0,0 +1,50 @@ +package gg.repo.game.out; + +import java.time.LocalDateTime; + +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; + +public interface GameTeamUser { + Long getGameId(); + + LocalDateTime getStartTime(); + + LocalDateTime getEndTime(); + + StatusType getStatus(); + + Mode getMode(); + + Long getT1TeamId(); + + Integer getT1Wins(); + + Integer getT1Losses(); + + String getT1IntraId(); + + String getT1Image(); + + Integer getT1Exp(); + + Integer getT1Score(); + + Boolean getT1IsWin(); + + Long getT2TeamId(); + + Integer getT2Wins(); + + Integer getT2Losses(); + + String getT2IntraId(); + + String getT2Image(); + + Integer getT2Exp(); + + Integer getT2Score(); + + Boolean getT2IsWin(); +} diff --git a/gg-repo/src/main/java/gg/repo/game/out/GameTeamUserInfo.java b/gg-repo/src/main/java/gg/repo/game/out/GameTeamUserInfo.java new file mode 100644 index 000000000..f12ff0c05 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/out/GameTeamUserInfo.java @@ -0,0 +1,29 @@ +package gg.repo.game.out; + +import java.time.LocalDateTime; + +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; + +public interface GameTeamUserInfo { + Long getGameId(); + + LocalDateTime getStartTime(); + + StatusType getStatus(); + + Mode getMode(); + + Long getTeamId(); + + Integer getScore(); + + Long getUserId(); + + String getIntraId(); + + Integer getExp(); + + String getImage(); + +} diff --git a/gg-repo/src/main/java/gg/repo/game/out/GameUser.java b/gg-repo/src/main/java/gg/repo/game/out/GameUser.java new file mode 100644 index 000000000..33f418b25 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/game/out/GameUser.java @@ -0,0 +1,15 @@ +package gg.repo.game.out; + +import gg.data.user.type.SnsType; + +public interface GameUser { + Long getGameId(); + + Long getUserId(); + + String getIntraId(); + + String getEmail(); + + SnsType getSnsNotiOpt(); +} diff --git a/gg-repo/src/main/java/gg/repo/manage/AnnouncementRepository.java b/gg-repo/src/main/java/gg/repo/manage/AnnouncementRepository.java new file mode 100644 index 000000000..be4cc237c --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/manage/AnnouncementRepository.java @@ -0,0 +1,11 @@ +package gg.repo.manage; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.manage.Announcement; + +public interface AnnouncementRepository extends JpaRepository { + Optional findFirstByOrderByIdDesc(); +} diff --git a/gg-repo/src/main/java/gg/repo/manage/FeedbackRepository.java b/gg-repo/src/main/java/gg/repo/manage/FeedbackRepository.java new file mode 100644 index 000000000..e01e01f8d --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/manage/FeedbackRepository.java @@ -0,0 +1,9 @@ +package gg.repo.manage; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.manage.Feedback; + +public interface FeedbackRepository extends JpaRepository { + Feedback findFirstByOrderByIdDesc(); +} diff --git a/gg-repo/src/main/java/gg/repo/manage/PenaltyRepository.java b/gg-repo/src/main/java/gg/repo/manage/PenaltyRepository.java new file mode 100644 index 000000000..c0c9aebb9 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/manage/PenaltyRepository.java @@ -0,0 +1,9 @@ +package gg.repo.manage; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.manage.Penalty; + +public interface PenaltyRepository extends JpaRepository { + +} diff --git a/gg-repo/src/main/java/gg/repo/manage/SlotManagementRepository.java b/gg-repo/src/main/java/gg/repo/manage/SlotManagementRepository.java new file mode 100644 index 000000000..56c72ee9a --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/manage/SlotManagementRepository.java @@ -0,0 +1,24 @@ +package gg.repo.manage; + +import java.time.LocalDateTime; +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; + +import gg.data.manage.SlotManagement; + +public interface SlotManagementRepository + extends JpaRepository { + @Query("select sm from SlotManagement sm where sm.endTime > :now or sm.endTime is null") + List findAfter(@Param("now") LocalDateTime now); + + @Query("select sm from SlotManagement sm where (sm.endTime is null" + + " or sm.endTime > :now) and sm.startTime <=:now") + Optional findCurrent(@Param("now") LocalDateTime now); + + SlotManagement findFirstByOrderByCreatedAtDesc(); + +} diff --git a/gg-repo/src/main/java/gg/repo/match/RedisMatchTimeRepository.java b/gg-repo/src/main/java/gg/repo/match/RedisMatchTimeRepository.java new file mode 100644 index 000000000..7a8d5d0e2 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/match/RedisMatchTimeRepository.java @@ -0,0 +1,53 @@ +package gg.repo.match; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import gg.data.match.RedisMatchUser; +import gg.data.match.type.MatchKey; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class RedisMatchTimeRepository { + private final RedisTemplate redisTemplate; + + public void addMatchUser(LocalDateTime startTime, RedisMatchUser redisMatchUser) { + redisTemplate.opsForList().rightPush(MatchKey.getTime(startTime), redisMatchUser); + } + + public List getAllMatchUsers(LocalDateTime startTime) { + ListOperations listOperations = redisTemplate.opsForList(); + return listOperations.range(MatchKey.getTime(startTime), 0, -1); + } + + public void setMatchTimeWithExpiry(LocalDateTime startTime) { + LocalDateTime now = LocalDateTime.now(); + Duration duration = Duration.between(now, startTime); + redisTemplate.expire(MatchKey.getTime(startTime), duration.getSeconds(), TimeUnit.SECONDS); + } + + public void deleteMatchTime(LocalDateTime startTime) { //๋งค์นญ์ด ๋˜๊ฑฐ๋‚˜ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด key๋ฅผ ์ง€์›Œ์ค€๋‹ค. + redisTemplate.delete(MatchKey.getTime(startTime)); + } + + public void deleteMatchUser(LocalDateTime startTime, RedisMatchUser matchUser) { + redisTemplate.opsForList().remove(MatchKey.getTime(startTime), 0, matchUser); + } + + public Set getAllEnrolledStartTimes() { + Set keys = redisTemplate.keys(MatchKey.getAllTime() + "*"); + Integer prefixIdx = MatchKey.getAllTime().length(); + return keys.stream().map(str -> LocalDateTime.parse(str.substring(prefixIdx))) + .collect(Collectors.toSet()); + } + +} diff --git a/gg-repo/src/main/java/gg/repo/match/RedisMatchUserRepository.java b/gg-repo/src/main/java/gg/repo/match/RedisMatchUserRepository.java new file mode 100644 index 000000000..c877c6622 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/match/RedisMatchUserRepository.java @@ -0,0 +1,60 @@ +package gg.repo.match; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import gg.data.match.RedisMatchTime; +import gg.data.match.type.MatchKey; +import gg.data.match.type.Option; +import gg.utils.exception.match.PastSlotException; +import lombok.RequiredArgsConstructor; + +@Repository +@RequiredArgsConstructor +public class RedisMatchUserRepository { + private final RedisTemplate redisTemplate; + + /** + * key : userId : startTime + * value : startTime + * slot์˜ startTime ๊ฐ๊ฐ์˜ ๋งŒ๋ฃŒ๊ธฐํ•œ ์„ค์ • + * **/ + public void addMatchTime(Long userId, LocalDateTime startTime, Option option) { + Duration duration = Duration.between(LocalDateTime.now(), startTime); + if (duration.isNegative()) { + throw new PastSlotException(); + } + redisTemplate.opsForValue().set(MatchKey.getUserTime(userId, startTime), + new RedisMatchTime(startTime, option), duration.getSeconds(), TimeUnit.SECONDS); + + } + + public void deleteMatchUser(Long userId) { + Set keys = redisTemplate.keys(MatchKey.getUser(userId) + "*"); + keys.stream().forEach(key -> redisTemplate.delete(key)); + } + + public void deleteMatchTime(Long userId, LocalDateTime startTime) { + redisTemplate.delete(MatchKey.getUserTime(userId, startTime)); + } + + public int countMatchTime(Long userId) { + return redisTemplate.keys(MatchKey.getUser(userId) + "*").size(); + } + + public Set getAllMatchTime(Long userId) { + Set keys = redisTemplate.keys(MatchKey.getUser(userId) + "*"); + return keys.stream().map(key -> redisTemplate.opsForValue().get(key)).collect(Collectors.toSet()); + } + + public Optional getUserTime(Long userId, LocalDateTime startTime) { + return Optional.ofNullable(redisTemplate.opsForValue().get(MatchKey.getUserTime(userId, startTime))); + } +} diff --git a/gg-repo/src/main/java/gg/repo/noti/NotiRepository.java b/gg-repo/src/main/java/gg/repo/noti/NotiRepository.java new file mode 100644 index 000000000..d5b78e5d3 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/noti/NotiRepository.java @@ -0,0 +1,21 @@ +package gg.repo.noti; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.noti.Noti; +import gg.data.user.User; + +public interface NotiRepository extends JpaRepository, NotiRepositoryCustom { + List findByUser(User user); + + Optional findByIdAndUser(Long notiId, User user); + + List findAllByUser(User user); + + List findAllByUserOrderByIdDesc(User user); + + void deleteAllByUser(User user); +} diff --git a/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryCustom.java b/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryCustom.java new file mode 100644 index 000000000..4b7d2b663 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryCustom.java @@ -0,0 +1,5 @@ +package gg.repo.noti; + +public interface NotiRepositoryCustom { + int countNotCheckedNotiByUser(Long userId); +} diff --git a/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryImpl.java b/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryImpl.java new file mode 100644 index 000000000..4d1ae7c25 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/noti/NotiRepositoryImpl.java @@ -0,0 +1,19 @@ +package gg.repo.noti; + +import javax.persistence.EntityManager; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class NotiRepositoryImpl implements NotiRepositoryCustom { + private final EntityManager em; + + @Override + public int countNotCheckedNotiByUser(Long userId) { + String sql = "select count(n) from Noti n where n.isChecked=false and user.id =: userId"; + Long cntNoti = em.createQuery(sql, Long.class) + .setParameter("userId", userId) + .getSingleResult(); + return cntNoti.intValue(); + } +} diff --git a/gg-repo/src/main/java/gg/repo/rank/RankRepository.java b/gg-repo/src/main/java/gg/repo/rank/RankRepository.java new file mode 100644 index 000000000..03861c4fa --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/rank/RankRepository.java @@ -0,0 +1,77 @@ +package gg.repo.rank; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +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 gg.data.rank.Rank; + +@Repository +public interface RankRepository extends JpaRepository { + Optional findByUserIdAndSeasonId(Long userId, Long seasonId); + + @Modifying(clearAutomatically = true) + @Query("delete from Rank r where r.season.id=:seasonId") + void deleteAllBySeasonId(@Param("seasonId") Long seasonId); + + Optional findFirstByOrderByCreatedAtDesc(); + + @EntityGraph(attributePaths = {"user", "tier"}) + List findAllBySeasonId(Long seasonId); + + List findAllBySeasonIdOrderByPppDesc(Long seasonId); + + @Query(value = "select count(r) from Rank r where r.season.id=:seasonId and not (r.wins = 0 and r.losses = 0)") + Long countRealRankPlayers(@Param("seasonId") Long seasonId); + + @Query(value = "SELECT u.intra_id intraId, r.status_message statusMessage, r.ppp, " + + "t.image_uri tierImageUri, u.text_color textColor, " + + "RANK() OVER(ORDER BY r.ppp DESC, pg.created_at ASC, u.total_exp DESC) AS ranking " + + "FROM Ranks r " + + "INNER JOIN Tier t " + + "ON r.tier_id = t.id " + + "INNER JOIN User u " + + "ON r.user_id = u.id " + + "INNER JOIN (SELECT MAX(p.created_at) created_at, p.user_id user_id " + + " FROM PChange p" + + " INNER JOIN Game g" + + " ON p.game_id = g.id" + + " WHERE g.season_id = :seasonId" + + " GROUP BY p.user_id) pg " + + "ON pg.user_id = u.id " + + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) " + + "LIMIT :limit OFFSET :offset ", nativeQuery = true) + List findPppRankBySeasonId(@Param("offset") int offset, @Param("limit") int limit, + @Param("seasonId") Long seasonId); + + @Query(value = "SELECT count(*) " + + "FROM Ranks r " + + "INNER JOIN User u " + + "ON r.user_id = u.id " + + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) ", nativeQuery = true) + int countRankUserBySeasonId(@Param("seasonId") Long seasonId); + + @Query(value = "SELECT ranked.ranking " + + "FROM (" + + "SELECT u.id userId, RANK() OVER(ORDER BY r.ppp DESC, pg.created_at ASC, u.total_exp DESC) AS ranking " + + "FROM Ranks r " + + "INNER JOIN User u " + + "ON r.user_id = u.id " + + "INNER JOIN (SELECT MAX(p.created_at) created_at, p.user_id user_id " + + " FROM PChange p" + + " INNER JOIN Game g" + + " ON p.game_id = g.id" + + " WHERE g.season_id = :seasonId" + + " GROUP BY p.user_id) pg " + + "ON pg.user_id = u.id " + + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) " + + ") ranked " + + "WHERE ranked.userId = :userId", nativeQuery = true) + Optional findRankByUserIdAndSeasonId(@Param("userId") Long userId, @Param("seasonId") Long seasonId); +} diff --git a/gg-repo/src/main/java/gg/repo/rank/RankV2Dto.java b/gg-repo/src/main/java/gg/repo/rank/RankV2Dto.java new file mode 100644 index 000000000..eb811eb57 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/rank/RankV2Dto.java @@ -0,0 +1,17 @@ +package gg.repo.rank; + +public interface RankV2Dto { + + String getIntraId(); + + String getStatusMessage(); + + Integer getPpp(); + + String getTierImageUri(); + + String getTextColor(); + + Integer getRanking(); + +} diff --git a/gg-repo/src/main/java/gg/repo/rank/TierRepository.java b/gg-repo/src/main/java/gg/repo/rank/TierRepository.java new file mode 100644 index 000000000..38ff04a7c --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/rank/TierRepository.java @@ -0,0 +1,16 @@ +package gg.repo.rank; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import gg.data.rank.Tier; + +public interface TierRepository extends JpaRepository { + + @Query("SELECT t FROM Tier t WHERE t.id = (SELECT MIN(t.id) FROM Tier t)") + Optional findStartTier(); + + Optional findByName(String name); +} diff --git a/gg-repo/src/main/java/gg/repo/rank/redis/RankRedisRepository.java b/gg-repo/src/main/java/gg/repo/rank/redis/RankRedisRepository.java new file mode 100644 index 000000000..3ded2f8a9 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/rank/redis/RankRedisRepository.java @@ -0,0 +1,225 @@ +package gg.repo.rank.redis; + +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Repository; + +import gg.data.rank.redis.RankRedis; +import gg.utils.exception.rank.RedisDataNotFoundException; + +@Repository +public class RankRedisRepository { + private final ZSetOperations zSetOps; + private final HashOperations hashOps; + private final RedisTemplate redisTemplate; + + public RankRedisRepository(RedisTemplate redisTemplate) { + this.zSetOps = redisTemplate.opsForZSet(); + this.hashOps = redisTemplate.opsForHash(); + this.redisTemplate = redisTemplate; + } + + /** + * + * @param key + * @param userId + * @param ppp + * + * ZSET์— user๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ + */ + public void addToZSet(String key, Long userId, int ppp) { + zSetOps.add(key, userId.toString(), ppp); + } + + /** + * + * @param key + * @param userId + * @param ppp + * + * ZSET์—์„œ user์˜ ppp ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ฉ”์„œ๋“œ + */ + public void incrementScoreInZSet(String key, Long userId, int ppp) { + zSetOps.incrementScore(key, userId.toString(), ppp); + + } + + /** + * + * @param key + * @param userId + * @param ppp + * + * ZSET์—์„œ user์˜ ppp๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ๋ฉ”์„œ๋“œ + */ + public void decrementScoreInZSet(String key, Long userId, int ppp) { + zSetOps.incrementScore(key, userId.toString(), -ppp); + } + + /** + * + * @param key + * @param userId + * + * ZSET์—์„œ user๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์„œ๋“œ + */ + public void deleteFromZSet(String key, Long userId) { + zSetOps.remove(key, userId.toString()); + } + + /** + * + * @param key + * @param userId + * @return 0 -> 1๋“ฑ + * + * ZSET์—์„œ user์˜ ์ˆœ์œ„(rank)๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ ppp๊ฐ€ ๋†’์€์ˆœ + */ + public Long getRankInZSet(String key, Long userId) { + Long result = zSetOps.reverseRank(key, userId.toString()); + if (result == null) { + throw new RedisDataNotFoundException(); + } + return result; + } + + /** + * + * @param key + * @param userId + * + * ZSET์—์„œ user์˜ ppp๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ + */ + public Long getScoreInZSet(String key, Long userId) { + Double result = zSetOps.score(key, userId.toString()); + if (result == null) { + throw new RedisDataNotFoundException(); + } + return result.longValue(); + } + + /** + * + * @param key + * @param startRank + * @param endRank + * + * Zset์—์„œ user์˜ ๋žญํ‚น ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ทธ ๋ฒ”์œ„ ๋‚ด์˜ userId๋“ค์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ + * startRank -> 0๋ถ€ํ„ฐ ์‹œ์ž‘ + */ + public List getUserIdsByRangeFromZSet(String key, long startRank, long endRank) { + Set result = zSetOps.reverseRange(key, startRank, endRank); + List stringList = result.stream().map(Object::toString).collect(Collectors.toList()); + if (result == null) { + throw new RedisDataNotFoundException(); + } + return stringList.stream() + .map(Long::parseLong).collect(Collectors.toList()); + } + + /** + * + * @param key + * @param userId + * @param userRank + * redis hash์— user rank๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์†Œ๋“œ + */ + public void addRankData(String key, Long userId, RankRedis userRank) { + hashOps.put(key, userId.toString(), userRank); + } + + /** + * + * @param key + * @param userId + * + * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์†Œ๋“œ + */ + public RankRedis findRankByUserId(String key, Long userId) { + Object result = hashOps.get(key, userId.toString()); + if (result == null) { + throw new RedisDataNotFoundException(); + } + return RankRedis.class.cast(result); + } + + /** + * + * @param key + * @param userId + * @param userRank + * + * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฉ”์†Œ๋“œ + */ + public void updateRankData(String key, Long userId, RankRedis userRank) { + hashOps.put(key, userId.toString(), userRank); + } + + /** + * + * @param key + * @param userId + * + * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์†Œ๋“œ + */ + public void deleteRankData(String key, Long userId) { + hashOps.delete(key, userId.toString()); + } + + /** + * + * @param key + * @param userIds + * + * ํ•ด๋‹น ์œ ์ €๋“ค์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์†Œ๋“œ + */ + public List findRanksByUserIds(String key, List userIds) { + List userIdsStr = userIds.stream().map(String::valueOf).collect(Collectors.toList()); + List objects = hashOps.multiGet(key, userIdsStr); + if (objects == null) { + throw new RedisDataNotFoundException(); + } + return objects.stream().map(RankRedis.class::cast).collect(Collectors.toList()); + } + + public List findAllRanksOrderByPppDesc(String key) { + List objects = hashOps.values(key); + if (objects == null) { + throw new RedisDataNotFoundException(); + } + return objects.stream() + .map(RankRedis.class::cast) + .sorted(Comparator.comparing(RankRedis::getPpp).reversed()) + .collect(Collectors.toList()); + } + + public Long countTotalRank(String zSetKey) { + Long result = zSetOps.size(zSetKey); + if (result == null) { + throw new RedisDataNotFoundException(); + } + return result; + } + + public void deleteAll() { + redisTemplate.delete(redisTemplate.keys("*")); + } + + public void deleteZSetKey(String key) { + redisTemplate.delete(key); + } + + public void deleteHashKey(String key) { + redisTemplate.delete(key); + } + + public Boolean isEmpty(String hashKey) { + return hashOps.size(hashKey) == 0; + } +} diff --git a/gg-repo/src/main/java/gg/repo/season/SeasonRepository.java b/gg-repo/src/main/java/gg/repo/season/SeasonRepository.java new file mode 100644 index 000000000..bae4dda42 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/season/SeasonRepository.java @@ -0,0 +1,26 @@ +package gg.repo.season; + +import java.time.LocalDateTime; +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; + +import gg.data.season.Season; + +public interface SeasonRepository extends JpaRepository { + @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now") + Optional findCurrentSeason(@Param("now") LocalDateTime now); + + @Query("select s from Season s where s.startTime <= :now") + List findActiveSeasons(@Param("now") LocalDateTime now); + + @Query("select s from Season s where s.startTime <= :now order by s.startTime desc") + List findActiveSeasonsDesc(@Param("now") LocalDateTime now); + + @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now or s.startTime > :now") + List findCurrentAndNewSeason(@Param("now") LocalDateTime now); + +} diff --git a/gg-repo/src/main/java/gg/repo/store/CoinHistoryRepository.java b/gg-repo/src/main/java/gg/repo/store/CoinHistoryRepository.java new file mode 100644 index 000000000..f287cf29e --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/CoinHistoryRepository.java @@ -0,0 +1,30 @@ +package gg.repo.store; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.store.CoinHistory; +import gg.data.user.User; + +public interface CoinHistoryRepository extends JpaRepository { + @Query("SELECT CASE WHEN COUNT(ch) > 0 THEN true ELSE false END FROM CoinHistory ch " + + "WHERE ch.user = :user " + + "AND ch.history = :history " + + "AND ch.createdAt >= :startOfDay " + + "AND ch.createdAt < :endOfDay") + boolean existsUserAttendedCheckToday(@Param("user") User user, @Param("history") String history, + @Param("startOfDay") LocalDateTime startOfDay, @Param("endOfDay") LocalDateTime endOfDay); + + Optional findFirstByOrderByIdDesc(); + + List findAllByUserOrderByIdDesc(User user); + + Page findAllByUserOrderByIdDesc(User user, Pageable pageable); +} diff --git a/gg-repo/src/main/java/gg/repo/store/CoinPolicyRepository.java b/gg-repo/src/main/java/gg/repo/store/CoinPolicyRepository.java new file mode 100644 index 000000000..217852559 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/CoinPolicyRepository.java @@ -0,0 +1,12 @@ +package gg.repo.store; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.CoinPolicy; + +public interface CoinPolicyRepository extends JpaRepository { + Optional findTopByOrderByCreatedAtDesc(); + +} diff --git a/gg-repo/src/main/java/gg/repo/store/ItemRepository.java b/gg-repo/src/main/java/gg/repo/store/ItemRepository.java new file mode 100644 index 000000000..74ace3772 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/ItemRepository.java @@ -0,0 +1,13 @@ +package gg.repo.store; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import gg.data.store.Item; + +public interface ItemRepository extends JpaRepository { + @Query("SELECT i FROM Item i WHERE i.isVisible = true ORDER BY i.createdAt DESC") + List findAllByCreatedAtDesc(); +} diff --git a/gg-repo/src/main/java/gg/repo/store/MegaphoneRepository.java b/gg-repo/src/main/java/gg/repo/store/MegaphoneRepository.java new file mode 100644 index 000000000..d54128bcb --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/MegaphoneRepository.java @@ -0,0 +1,19 @@ +package gg.repo.store; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.Megaphone; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; + +public interface MegaphoneRepository extends JpaRepository { + List findAllByUsedAtAndReceiptStatus(LocalDate date, ItemStatus itemStatus); + + Megaphone findFirstByOrderByIdDesc(); + + Optional findByReceipt(Receipt receipt); +} diff --git a/gg-repo/src/main/java/gg/repo/store/ReceiptRepository.java b/gg-repo/src/main/java/gg/repo/store/ReceiptRepository.java new file mode 100644 index 000000000..87f43cd60 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/ReceiptRepository.java @@ -0,0 +1,8 @@ +package gg.repo.store; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.store.Receipt; + +public interface ReceiptRepository extends JpaRepository { +} diff --git a/gg-repo/src/main/java/gg/repo/store/UserItemRepository.java b/gg-repo/src/main/java/gg/repo/store/UserItemRepository.java new file mode 100644 index 000000000..2d5a9830b --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/store/UserItemRepository.java @@ -0,0 +1,16 @@ +package gg.repo.store; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.store.Receipt; + +public interface UserItemRepository extends JpaRepository { + + @Query("select r from Receipt r where r.ownerIntraId = :intraId " + + "and (r.status = 'BEFORE' or r.status = 'USING' or r.status = 'WAITING') order by r.createdAt desc") + Page findByOwnerIntraId(@Param("intraId") String intraId, Pageable pageable); +} diff --git a/gg-repo/src/main/java/gg/repo/tournarment/TournamentGameRepository.java b/gg-repo/src/main/java/gg/repo/tournarment/TournamentGameRepository.java new file mode 100644 index 000000000..beb1da482 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/tournarment/TournamentGameRepository.java @@ -0,0 +1,19 @@ +package gg.repo.tournarment; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.tournament.TournamentGame; +import gg.data.tournament.type.TournamentRound; + +public interface TournamentGameRepository extends JpaRepository { + List findAllByTournamentId(Long tournamentId); + + Optional findByTournamentIdAndTournamentRound(Long id, TournamentRound tournamentRound); + + List findByTournamentIdAndTournamentRoundIn(Long id, List tournamentRounds); + + Optional findByGameId(Long gameId); +} diff --git a/gg-repo/src/main/java/gg/repo/tournarment/TournamentRepository.java b/gg-repo/src/main/java/gg/repo/tournarment/TournamentRepository.java new file mode 100644 index 000000000..852d3d1bd --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/tournarment/TournamentRepository.java @@ -0,0 +1,40 @@ +package gg.repo.tournarment; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import javax.validation.constraints.NotNull; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.tournament.Tournament; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; + +public interface TournamentRepository extends JpaRepository { + List findAllByStatusIsNot(TournamentStatus status); + + Optional findByTitle(String title); + + Page findAllByTypeAndStatus(@NotNull TournamentType type, @NotNull TournamentStatus status, + Pageable pageable); + + Page findAllByStatus(@NotNull TournamentStatus status, Pageable pageable); + + List findAllByStatus(@NotNull TournamentStatus status); + + Page findAllByType(@NotNull TournamentType type, Pageable pageable); + + @Query(value = "select t from Tournament t where (t.startTime between :startTime and :endTime) " + + "or (t.endTime between :startTime and :endTime) " + + "or (:startTime between t.startTime and t.endTime) " + + "or (:endTime between t.startTime and t.endTime)") + List findAllBetween(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + +} diff --git a/gg-repo/src/main/java/gg/repo/tournarment/TournamentUserRepository.java b/gg-repo/src/main/java/gg/repo/tournarment/TournamentUserRepository.java new file mode 100644 index 000000000..5482c2279 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/tournarment/TournamentUserRepository.java @@ -0,0 +1,25 @@ +package gg.repo.tournarment; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentUser; +import gg.data.user.User; + +public interface TournamentUserRepository extends JpaRepository { + + int countByTournamentAndIsJoined(Tournament tournament, boolean isJoined); + + List findAllByTournament(Tournament tournament); + + List findAllByTournamentAndIsJoined(Tournament tournament, boolean isJoined); + + List findAllByTournamentId(Long tournamentId); + + Optional findByTournamentIdAndUserId(Long tournamentId, Long userId); + + List findAllByUser(User user); +} diff --git a/gg-repo/src/main/java/gg/repo/user/ExpRankV2Dto.java b/gg-repo/src/main/java/gg/repo/user/ExpRankV2Dto.java new file mode 100644 index 000000000..ffe95bc83 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/user/ExpRankV2Dto.java @@ -0,0 +1,16 @@ +package gg.repo.user; + +public interface ExpRankV2Dto { + String getIntraId(); + + String getStatusMessage(); + + Integer getTotalExp(); + + String getImageUri(); + + String getTextColor(); + + Integer getRanking(); + +} diff --git a/gg-repo/src/main/java/gg/repo/user/UserImageRepository.java b/gg-repo/src/main/java/gg/repo/user/UserImageRepository.java new file mode 100644 index 000000000..e8bd67d87 --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/user/UserImageRepository.java @@ -0,0 +1,12 @@ +package gg.repo.user; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + +import gg.data.user.User; +import gg.data.user.UserImage; + +public interface UserImageRepository extends JpaRepository { + Optional findTopByUserAndIsCurrentIsTrueOrderByIdDesc(User user); +} diff --git a/gg-repo/src/main/java/gg/repo/user/UserRepository.java b/gg-repo/src/main/java/gg/repo/user/UserRepository.java new file mode 100644 index 000000000..446b14a9d --- /dev/null +++ b/gg-repo/src/main/java/gg/repo/user/UserRepository.java @@ -0,0 +1,56 @@ +package gg.repo.user; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import gg.data.user.User; + +public interface UserRepository extends JpaRepository { + Optional findByIntraId(String intraId); + + List findByIntraIdIn(List intraIds); + + Optional getUserByIntraId(String intraId); + + Page findByIntraIdContains(Pageable pageable, String intraId); + + Page findAllByTotalExpGreaterThan(Pageable pageable, Integer exp); + + Optional findByKakaoId(Long kakaoId); + + @Query(nativeQuery = true, value = "select ranking from " + + "(select intra_id, row_number() over (order by total_exp desc, intra_id asc) as ranking from user) ranked " + + "where intra_id=:intraId") + Long findExpRankingByIntraId(@Param("intraId") String intraId); + + Page findAll(Pageable pageable); + + @Query("select tu.user from User u, TeamUser tu, Team t, Game g" + + " where g.id=:gameId and t.game.id =g.id and tu.team.id = t.id " + + "and u.id = tu.user.id and u.id !=:userId") + List findEnemyByGameAndUser(@Param("gameId") Long gameId, @Param("userId") Long userId); + + List findUsersByIdIn(List userIds); + + @Modifying(clearAutomatically = true) + @Query("update User u set u.imageUri = :imageUri where u.id = :id") + void updateUserImage(Long id, String imageUri); + + @Query(value = "SELECT u.intra_id intraId, r.status_message statusMessage, u.total_exp totalExp, " + + "u.image_uri imageUri, u.text_color textColor, " + + "RANK() OVER(ORDER BY u.total_exp DESC, r.modified_at DESC, r.ppp DESC) ranking " + + "FROM User u LEFT JOIN Ranks r " + + "ON u.id = r.user_id " + + "WHERE r.season_id = :seasonId AND u.total_exp > 0 " + + "LIMIT :limit OFFSET :offset", nativeQuery = true) + List findExpRank(@Param("offset") int offset, @Param("limit") int limit, + @Param("seasonId") Long seasonId); + +} diff --git a/gg-utils/build.gradle b/gg-utils/build.gradle new file mode 100644 index 000000000..5f95eb653 --- /dev/null +++ b/gg-utils/build.gradle @@ -0,0 +1,103 @@ +plugins { + id 'java' + id 'java-test-fixtures' + id 'jacoco-report-aggregation' +} + +group 'gg.pingpong.utils' +version '42gg' + +repositories { + mavenCentral() +} + +reporting { + reports { + unitTestCoverageReport(JacocoCoverageReport) { + testType = TestSuiteType.UNIT_TEST + } + } +} + +reporting { + reports { + integrationTestCoverageReport(JacocoCoverageReport) { + testType = TestSuiteType.UNIT_TEST + } + } +} + +def jacocoExcludes = [ + '*Application*', + "**/config/*", + "**/security/*", + "**/dto/*", + "**/aws/*", + "*NotiMailSender*", + '*SlackbotService*', +] + + +integrationTestCoverageReport { + reports { + html.required = true + csv.required = false + xml.required = true + } + + getClassDirectories().setFrom(files( + [project(':gg-data'), project(':gg-admin-repo'), + project(':gg-repo'), project(':gg-pingpong-api')].collect { + it.fileTree(dir: "${it.buildDir}/classes/java/main", exclude: jacocoExcludes) + } + )) +} + + +unitTestCoverageReport { + reports { + html.required = true + csv.required = false + xml.required = true + } + + getClassDirectories().setFrom(files( + [project(':gg-data'), project(':gg-admin-repo'), + project(':gg-repo'), project(':gg-pingpong-api')].collect { + it.fileTree(dir: "${it.buildDir}/classes/java/main", exclude: jacocoExcludes) + } + )) +} + + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' + + testFixturesImplementation("org.junit.jupiter:junit-jupiter:5.8.1") + testFixturesImplementation('org.springframework.boot:spring-boot-starter-data-redis') + testFixturesImplementation('org.springframework.boot:spring-boot-starter-data-jpa') + testFixturesImplementation("org.springframework.boot:spring-boot-starter-test:2.5.5") + testFixturesImplementation("org.testcontainers:testcontainers:1.19.3") + testFixturesImplementation("org.testcontainers:junit-jupiter:1.19.3") + testFixturesImplementation("org.testcontainers:mysql:1.19.3") + testFixturesImplementation("com.redis:testcontainers-redis:2.0.1") + + testFixturesImplementation("org.projectlombok:lombok:1.18.26") + testFixturesCompileOnly("org.projectlombok:lombok") + testFixturesAnnotationProcessor("org.projectlombok:lombok") + + testFixturesImplementation project(":gg-data") + testFixturesImplementation project(":gg-repo") + testFixturesImplementation project(":gg-admin-repo") + testFixturesImplementation project(":gg-pingpong-api") + + jacocoAggregation(project(':gg-data')) + jacocoAggregation(project(':gg-repo')) + jacocoAggregation(project(':gg-admin-repo')) + jacocoAggregation(project(':gg-pingpong-api')) +} + +test { + useJUnitPlatform() +} diff --git a/gg-utils/src/main/java/gg/utils/RedisKeyManager.java b/gg-utils/src/main/java/gg/utils/RedisKeyManager.java new file mode 100644 index 000000000..d1b47aec2 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/RedisKeyManager.java @@ -0,0 +1,19 @@ +package gg.utils; + +public class RedisKeyManager { + private static final String ZSetKeyPrefix = "rank:ZSet:"; + private static final String HashKeyPrefix = "rank:hash:"; + private static final String RefKeyPrefix = "refresh:token:"; + + public static String getZSetKey(Long seasonId) { + return ZSetKeyPrefix + seasonId; + } + + public static String getHashKey(Long seasonId) { + return HashKeyPrefix + seasonId; + } + + public static String getRefKey(Long id) { + return RefKeyPrefix + id.toString(); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/BusinessChecker.java b/gg-utils/src/main/java/gg/utils/exception/BusinessChecker.java new file mode 100644 index 000000000..9b9ff8751 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/BusinessChecker.java @@ -0,0 +1,42 @@ +package gg.utils.exception; + +import java.util.Collection; + +import gg.utils.exception.custom.BusinessException; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * Checker. + * + *

+ * ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒดํฌ์šฉ check ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค + *

+ * + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class BusinessChecker { + public static void mustNotNull(Object object, ErrorCode errorCode) { + if (object == null) { + throw new BusinessException(errorCode); + } + } + + public static void mustContains(Object object, Collection collection, ErrorCode errorCode) { + if (!collection.contains(object)) { + throw new BusinessException(errorCode); + } + } + + public static void mustNotContains(Object object, Collection collection, ErrorCode errorCode) { + if (collection.contains(object)) { + throw new BusinessException(errorCode); + } + } + + public static void mustNotExceed(int size, Collection collection, ErrorCode errorCode) { + if (collection.size() > size) { + throw new BusinessException(errorCode); + } + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java new file mode 100644 index 000000000..72b0fa6d3 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/ErrorCode.java @@ -0,0 +1,162 @@ +package gg.utils.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum ErrorCode { + //common + NULL_POINT(500, "G100", "NULL POINT EXCEPTION"), + + //user + USER_NOT_FOUND(404, "UR100", "USER NOT FOUND"), + USER_IMAGE_NOT_FOUND(404, "UR200", "USER IMAGE NOT FOUND"), + USER_IMAGE_TOO_LARGE(413, "UR401", "USER IMAGE IS TOO LARGE"), + USER_IMAGE_WRONG_TYPE(415, "UR402", "USER IMAGE TYPE IS WRONG"), + KAKAO_OAUTH2_NOT_FOUND(404, "UR101", "KAKAO OAUTH2 NOT FOUND"), + KAKAO_OAUTH2_DUPLICATE(409, "UR300", "KAKAO OAUTH2 ALREADY EXIST"), + USER_TEXT_COLOR_WRONG_TYPE(401, "UR403", "USER TEXT COLOR CODE IS WRONG"), + USER_ALREADY_ATTENDANCE(409, "UR301", "USER ALREADY ATTENDANCE"), + + //announcement + ANNOUNCE_NOT_FOUND(404, "AN100", "ANNOUNCEMENT NOT FOUND"), + ANNOUNCE_DUPLICATE(409, "AN300", "ANNOUNCEMENT DUPLICATION"), + + //coinPolicy + CoinPolicy_NOT_FOUND(404, "CP100", "COINPOLICY NOT FOUND"), + + //coinHistory + COIN_HISTORY_NOT_FOUND(404, "CH100", "COIN HISTORY NOT FOUND"), + + //season + SEASON_NOT_FOUND(404, "SE100", "SEASON NOT FOUND"), + SEASON_FORBIDDEN(400, "SE500", "SEASON FORBIDDEN ERROR"), + SEASON_TIME_BEFORE(400, "SE501", "SEASON TIME BEFORE"), + + //slotmanagement + SLOTMANAGEMENT_NOT_FOUND(404, "SM100", "SLOTMANAGEMENT NOT FOUND"), + SLOTMANAGEMENT_FORBIDDEN(400, "SM500", "SLOTMANAGEMENT FORBIDDEN"), + + //rank + RANK_NOT_FOUND(404, "RK100", "RANK NOT FOUND"), + REDIS_RANK_NOT_FOUND(404, "RK101", "REDIS RANK NOT FOUND"), + RANK_UPDATE_FAIL(400, "RK200", "RANK UPDATE FAIL"), + + //tier + TIER_NOT_FOUND(404, "TR100", "TIER NOT FOUND"), + + //item + ITEM_NOT_FOUND(404, "IT100", "ITEM NOT FOUND"), + ITEM_TYPE_NOT_MATCHED(400, "IT200", "ITEM TYPE NOT MATCHED"), + ITEM_NOT_PURCHASABLE(400, "IT201", "ITEM NOT PURCHASABLE"), + INSUFFICIENT_GGCOIN(400, "IT202", "INSUFFICIENT GGCOIN"), + GUEST_ROLE_PURCHASE_FORBIDDEN(403, "IT203", "GUEST ROLE USERS CANNOT PURCHASE ITEMS."), + GUEST_ROLE_GIFT_FORBIDDEN(403, "IT204", "GUEST ROLE USERS CANNOT GIFT ITEMS."), + ITEM_NOT_AVAILABLE(400, "IT205", "ITEM NOT AVAILABLE"), + ITEM_IMAGE_TOO_LARGE(413, "IT401", "ITEM IMAGE IS TOO LARGE"), + ITEM_IMAGE_WRONG_TYPE(415, "IT402", "ITEM IMAGE TYPE IS WRONG"), + + //receipt + RECEIPT_NOT_FOUND(404, "RC100", "RECEIPT NOT FOUND"), + RECEIPT_NOT_OWNER(403, "RC500", "RECEIPT NOT OWNER"), + RECEIPT_STATUS_NOT_MATCHED(400, "RC200", "RECEIPT STATUS NOT MATCHED"), + + //megaphone + MEGAPHONE_NOT_FOUND(404, "ME100", "MEGAPHONE NOT FOUND"), + MEGAPHONE_TIME(400, "ME200", "MEGAPHONE TIME"), + MEGAPHONE_CONTENT(400, "ME201", "MEGAPHONE CONTENT IS EMPTY"), + + /** Penalty **/ + PENALTY_NOT_FOUND(404, "PE100", "PENALTY NOT FOUND"), + REDIS_PENALTY_USER_NOT_FOUND(404, "PE101", "REDIS PENALTY USER NOT FOUND"), + PENALTY_EXPIRED(400, "PE200", "PENALTY EXPIRED"), + + /** team **/ + TEAM_ID_NOT_MATCH(400, "TM201", "TEAM id ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + TEAM_DUPLICATION(409, "TM202", "์ค‘๋ณต๋œ Team ์ด ํ•œ Game ์— ์กด์žฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + TEAM_SIZE_EXCEED(500, "TM203", "๊ฒŒ์ž„ ์ตœ๋Œ€ Team ์˜ ์ˆ˜(2)๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค."), + TEAM_NOT_FOUND(404, "TM204", "TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + WINNING_TEAM_NOT_FOUND(404, "TM205", "WINNING TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + LOSING_TEAM_NOT_FOUND(404, "TM206", "LOSING TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + + /** + * team_user + */ + TEAM_USER_ALREADY_EXIST(409, "TU201", "์ค‘๋ณต๋œ TEAM_USER"), + TEAM_USER_EXCEED(500, "TU202", "TeamUser ์ตœ๋Œ€ ์ธ์›์˜ ์ˆ˜(2)๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค."), + TEAM_USER_NOT_FOUND(404, "TU203", "TeamUser๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."), + + /** game **/ + GAME_DB_NOT_VALID(500, "GM201", "GAME DB NOT CONSISTENCY"), + SCORE_NOT_MATCHED(400, "GM202", "score ์ž…๋ ฅ์ด ๊ธฐ์กด๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค."), + GAME_NOT_FOUND(404, "GM101", "GAME ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + GAME_NOT_RECENTLY(400, "GM203", "๊ฐ€์žฅ ์ตœ๊ทผ ๊ฒŒ์ž„์ด ์•„๋‹™๋‹ˆ๋‹ค."), + GAME_DUPLICATION_EXCEPTION(409, "GM204", "GAME ALREADY EXISTS"), + GAME_STATUS_NOT_MATCHED(400, "GM205", "๊ฒŒ์ž„ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค."), + SCORE_ALREADY_ENTERED(400, "GM206", "์ ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."), + SCORE_NOT_INVALID(400, "GM205", "score ์ž…๋ ฅ์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + GAME_NOT_TOURNAMENT(400, "GM206", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์•„๋‹™๋‹ˆ๋‹ค."), + + /** match **/ + SLOT_ENROLLED(400, "MA300", "SLOT ALREADY ENROLLED"), + SLOT_COUNT_EXCEEDED(400, "MA301", "SLOT COUNT MORE THAN THREE"), + SLOT_NOT_FOUND(404, "MA100", "SLOT NOT FOUND"), + PENALTY_USER_ENROLLED(400, "MA302", "PENALTY USER ENROLLED"), + SLOT_PAST(400, "MA303", "PAST SLOT ENROLLED"), + MODE_INVALID(400, "MA200", "MODE INVALID"), + + /** Common **/ + INTERNAL_SERVER_ERR(500, "CM001", "INTERNAL SERVER ERROR"), + NOT_FOUND(404, "CM002", "NOT FOUND"), + BAD_REQUEST(400, "CM003", "BAD REQUEST"), + UNAUTHORIZED(401, "CM004", "UNAUTHORIZED"), + METHOD_NOT_ALLOWED(405, "CM005", "METHOD NOT ALLOWED"), + PAGE_NOT_FOUND(404, "CM006", "PAGE NOT FOUND"), + VALID_FAILED(400, "CM007", "Valid Test Failed."), + BAD_ARGU(400, "ARGUMENT-ERR-400", "์ž˜๋ชป๋œ argument ์ž…๋‹ˆ๋‹ค."), + UNREADABLE_HTTP_MESSAGE(400, "CM008", "์œ ํšจํ•˜์ง€ ์•Š์€ HTTP ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค."), + + //Feedback + FEEDBACK_NOT_FOUND(404, "FB100", "FB NOT FOUND"), + + /** + * PChange + **/ + PCHANGE_NOT_FOUND(404, "PC100", "PChange ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), + + AWS_S3_ERR(500, "CL001", "AWS S3 Error"), + AWS_SERVER_ERR(500, "CL002", "AWS Error"), + + // SENDER + SLACK_USER_NOT_FOUND(404, "SL001", "fail to get slack user info"), + SLACK_CH_NOT_FOUND(404, "SL002", "fail to get user dm channel id"), + SLACK_JSON_PARSE_ERR(400, "SL002", "json parse error"), + SLACK_SEND_FAIL(400, "SL003", "fail to send notification"), + + // Tournament + TOURNAMENT_INVALID_TIME(400, "TN001", "์œ ํšจํ•œ ํ† ๋„ˆ๋จผํŠธ ๊ธฐ๊ฐ„์ด ์•„๋‹™๋‹ˆ๋‹ค."), + TOURNAMENT_CAN_NOT_UPDATE(403, "TN002", "ํ† ๋„ˆ๋จผํŠธ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ๊ธฐ๊ฐ„์ž…๋‹ˆ๋‹ค."), + TOURNAMENT_INVALID_SCORE(403, "TN003", "์Šค์ฝ”์–ด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + TOURNAMENT_NOT_BEFORE(403, "TN004", "tournament status is not before"), + TOURNAMENT_NOT_LIVE(403, "TN005", "tournament status is not live"), + TOURNAMENT_GAME_CAN_NOT_CANCELED(403, "TN006", "์ง„ํ–‰์ค‘์ธ ํ† ๋„ˆ๋จผํŠธ์˜ ๊ฒŒ์ž„์€ ์ทจ์†Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), + TOURNAMENT_NOT_FOUND(404, "TN007", "target tournament not found"), + TOURNAMENT_GAME_NOT_FOUND(404, "TN008", "tournament game not found"), + TOURNAMENT_NOT_PARTICIPANT(404, "TN009", "ํ† ๋„ˆ๋จผํŠธ์˜ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค."), + TOURNAMENT_USER_NOT_FOUND(404, "TN010", "target tournament user not found"), + TOURNAMENT_CONFLICT(409, "TN011", "tournament conflicted"), + TOURNAMENT_ALREADY_PARTICIPANT(409, "TN012", "์ด๋ฏธ ํ† ๋„ˆ๋จผํŠธ์˜ ์‹ ์ฒญ์ž ์ž…๋‹ˆ๋‹ค."), + TOURNAMENT_CONFLICT_GAME(409, "TN013", "ํ† ๋„ˆ๋จผํŠธ ๊ธฐ๊ฐ„ ๋‚ด ๋Œ€๊ธฐ์ค‘์ธ ๊ฒŒ์ž„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), + TOURNAMENT_GAME_DUPLICATION(409, "TN014", "์ค‘๋ณต๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ž…๋‹ˆ๋‹ค!"), + TOURNAMENT_USER_DUPLICATION(409, "TN015", "์ค‘๋ณต๋œ ํ† ๋„ˆ๋จผํŠธ ์œ ์ €์ž…๋‹ˆ๋‹ค!"), + TOURNAMENT_GAME_EXCEED(500, "TN016", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ตœ๋Œ€ ์‚ฌ์ด์ฆˆ๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค!"), + TOURNAMENT_IS_BEFORE(403, "TN017", "before์ธ ํ† ๋„ˆ๋จผํŠธ์—์„œ ์ ์ˆ˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + private final int status; + private final String errCode; + private String message; + + public void setMessage(String msg) { + this.message = msg; + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/ErrorResponse.java b/gg-utils/src/main/java/gg/utils/exception/ErrorResponse.java new file mode 100644 index 000000000..2bf551bb0 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/ErrorResponse.java @@ -0,0 +1,16 @@ +package gg.utils.exception; + +import lombok.Getter; + +@Getter +public class ErrorResponse { + private int status; + private String message; + private String code; + + public ErrorResponse(ErrorCode errorCode) { + this.status = errorCode.getStatus(); + this.message = errorCode.getMessage(); + this.code = errorCode.getErrCode(); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceDupException.java b/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceDupException.java new file mode 100644 index 000000000..14abdc92e --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceDupException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.announcement; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class AnnounceDupException extends DuplicationException { + public AnnounceDupException() { + super(ErrorCode.ANNOUNCE_DUPLICATE.getMessage(), ErrorCode.ANNOUNCE_DUPLICATE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceNotFoundException.java new file mode 100644 index 000000000..05b1dc2d8 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/announcement/AnnounceNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.announcement; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; + +public class AnnounceNotFoundException extends CustomRuntimeException { + public AnnounceNotFoundException() { + super(ErrorCode.ANNOUNCE_NOT_FOUND.getMessage(), ErrorCode.ANNOUNCE_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/coin/CoinHistoryNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/coin/CoinHistoryNotFoundException.java new file mode 100644 index 000000000..5cf7d49c1 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/coin/CoinHistoryNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.coin; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; + +public class CoinHistoryNotFoundException extends CustomRuntimeException { + public CoinHistoryNotFoundException() { + super(ErrorCode.COIN_HISTORY_NOT_FOUND.getMessage(), ErrorCode.COIN_HISTORY_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/coin/CoinPolicyNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/coin/CoinPolicyNotFoundException.java new file mode 100644 index 000000000..3e658f122 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/coin/CoinPolicyNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.coin; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; + +public class CoinPolicyNotFoundException extends CustomRuntimeException { + public CoinPolicyNotFoundException() { + super(ErrorCode.CoinPolicy_NOT_FOUND.getMessage(), ErrorCode.CoinPolicy_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/AuthenticationException.java b/gg-utils/src/main/java/gg/utils/exception/custom/AuthenticationException.java new file mode 100644 index 000000000..6fb9ac499 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/AuthenticationException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class AuthenticationException extends CustomRuntimeException { + private ErrorCode errorCode; + + public AuthenticationException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/BusinessException.java b/gg-utils/src/main/java/gg/utils/exception/custom/BusinessException.java new file mode 100644 index 000000000..eafb5fa95 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/BusinessException.java @@ -0,0 +1,13 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class BusinessException extends CustomRuntimeException { + public BusinessException(String message, ErrorCode errorCode) { + super(message, errorCode); + } + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMessage(), errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/CustomRuntimeException.java b/gg-utils/src/main/java/gg/utils/exception/custom/CustomRuntimeException.java new file mode 100644 index 000000000..fab407b85 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/CustomRuntimeException.java @@ -0,0 +1,20 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; +import lombok.Getter; + +@Getter +public class CustomRuntimeException extends RuntimeException { + private ErrorCode errorCode; + + public CustomRuntimeException(String message, ErrorCode errorCode) { + super(message); + this.errorCode = errorCode; + errorCode.setMessage(message); + } + + public CustomRuntimeException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/DBConsistencyException.java b/gg-utils/src/main/java/gg/utils/exception/custom/DBConsistencyException.java new file mode 100644 index 000000000..7e23c97f6 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/DBConsistencyException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; +import lombok.Getter; + +@Getter +public class DBConsistencyException extends CustomRuntimeException { + public DBConsistencyException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/DuplicationException.java b/gg-utils/src/main/java/gg/utils/exception/custom/DuplicationException.java new file mode 100644 index 000000000..7d3591af2 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/DuplicationException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class DuplicationException extends CustomRuntimeException { + public DuplicationException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/ExpiredException.java b/gg-utils/src/main/java/gg/utils/exception/custom/ExpiredException.java new file mode 100644 index 000000000..934c5ecc4 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/ExpiredException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class ExpiredException extends CustomRuntimeException { + public ExpiredException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/FileException.java b/gg-utils/src/main/java/gg/utils/exception/custom/FileException.java new file mode 100644 index 000000000..9d77bcffa --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/FileException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class FileException extends CustomRuntimeException { + + public FileException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/ForbiddenException.java b/gg-utils/src/main/java/gg/utils/exception/custom/ForbiddenException.java new file mode 100644 index 000000000..b9ff7b742 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/ForbiddenException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class ForbiddenException extends CustomRuntimeException { + public ForbiddenException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/InvalidParameterException.java b/gg-utils/src/main/java/gg/utils/exception/custom/InvalidParameterException.java new file mode 100644 index 000000000..d2f182ec5 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/InvalidParameterException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class InvalidParameterException extends CustomRuntimeException { + public InvalidParameterException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/NotExistException.java b/gg-utils/src/main/java/gg/utils/exception/custom/NotExistException.java new file mode 100644 index 000000000..efbf33b5e --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/NotExistException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class NotExistException extends CustomRuntimeException { + private ErrorCode errorCode; + + public NotExistException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/PageNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/custom/PageNotFoundException.java new file mode 100644 index 000000000..8481e315f --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/PageNotFoundException.java @@ -0,0 +1,13 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class PageNotFoundException extends CustomRuntimeException { + public PageNotFoundException(String message, ErrorCode errorCode) { + super(message, errorCode); + } + + public PageNotFoundException() { + super(ErrorCode.PAGE_NOT_FOUND.getMessage(), ErrorCode.PAGE_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/ParseException.java b/gg-utils/src/main/java/gg/utils/exception/custom/ParseException.java new file mode 100644 index 000000000..1924834ef --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/ParseException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class ParseException extends CustomRuntimeException { + public ParseException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/custom/SendException.java b/gg-utils/src/main/java/gg/utils/exception/custom/SendException.java new file mode 100644 index 000000000..e1580fb4d --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/custom/SendException.java @@ -0,0 +1,9 @@ +package gg.utils.exception.custom; + +import gg.utils.exception.ErrorCode; + +public class SendException extends CustomRuntimeException { + public SendException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/feedback/FeedbackNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/feedback/FeedbackNotFoundException.java new file mode 100644 index 000000000..1acdb2fb4 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/feedback/FeedbackNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.feedback; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; + +public class FeedbackNotFoundException extends CustomRuntimeException { + public FeedbackNotFoundException() { + super(ErrorCode.FEEDBACK_NOT_FOUND.getMessage(), ErrorCode.FEEDBACK_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/GameAlreadyExistException.java b/gg-utils/src/main/java/gg/utils/exception/game/GameAlreadyExistException.java new file mode 100644 index 000000000..cf3b76564 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/GameAlreadyExistException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class GameAlreadyExistException extends DuplicationException { + public GameAlreadyExistException() { + super("๊ฒŒ์ž„์ด ์ด๋ฏธ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_DUPLICATION_EXCEPTION); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/GameDataConsistencyException.java b/gg-utils/src/main/java/gg/utils/exception/game/GameDataConsistencyException.java new file mode 100644 index 000000000..5e1f950ad --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/GameDataConsistencyException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DBConsistencyException; + +public class GameDataConsistencyException extends DBConsistencyException { + public GameDataConsistencyException() { + super("game db ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_DB_NOT_VALID); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/GameNotExistException.java b/gg-utils/src/main/java/gg/utils/exception/game/GameNotExistException.java new file mode 100644 index 000000000..b15bbd8bb --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/GameNotExistException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class GameNotExistException extends NotExistException { + public GameNotExistException() { + super("game ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/GameStatusNotMatchedException.java b/gg-utils/src/main/java/gg/utils/exception/game/GameStatusNotMatchedException.java new file mode 100644 index 000000000..c78b11a22 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/GameStatusNotMatchedException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class GameStatusNotMatchedException extends BusinessException { + public GameStatusNotMatchedException() { + super("๊ฒŒ์ž„ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.GAME_STATUS_NOT_MATCHED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/NotRecentlyGameException.java b/gg-utils/src/main/java/gg/utils/exception/game/NotRecentlyGameException.java new file mode 100644 index 000000000..f4e7fabd8 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/NotRecentlyGameException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; + +public class NotRecentlyGameException extends InvalidParameterException { + public NotRecentlyGameException() { + super(ErrorCode.GAME_NOT_RECENTLY.getMessage(), ErrorCode.GAME_NOT_RECENTLY); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/ScoreAlreadyEnteredException.java b/gg-utils/src/main/java/gg/utils/exception/game/ScoreAlreadyEnteredException.java new file mode 100644 index 000000000..49020621b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/ScoreAlreadyEnteredException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class ScoreAlreadyEnteredException extends DuplicationException { + public ScoreAlreadyEnteredException(String message, ErrorCode errorCode) { + super(message, errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotInvalidException.java b/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotInvalidException.java new file mode 100644 index 000000000..a00805210 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotInvalidException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; + +public class ScoreNotInvalidException extends InvalidParameterException { + public ScoreNotInvalidException() { + super(ErrorCode.SCORE_NOT_INVALID.getMessage(), ErrorCode.SCORE_NOT_INVALID); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotMatchedException.java b/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotMatchedException.java new file mode 100644 index 000000000..4a14eb892 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/game/ScoreNotMatchedException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.game; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class ScoreNotMatchedException extends DuplicationException { + public ScoreNotMatchedException() { + super(ErrorCode.SCORE_NOT_MATCHED.getMessage(), ErrorCode.SCORE_NOT_MATCHED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/InsufficientGgcoinException.java b/gg-utils/src/main/java/gg/utils/exception/item/InsufficientGgcoinException.java new file mode 100644 index 000000000..89114a1e2 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/InsufficientGgcoinException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class InsufficientGgcoinException extends BusinessException { + public InsufficientGgcoinException() { + super("GGcoin์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.", ErrorCode.INSUFFICIENT_GGCOIN); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemImageLargeException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemImageLargeException.java new file mode 100644 index 000000000..2f40f7629 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemImageLargeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class ItemImageLargeException extends FileException { + public ItemImageLargeException() { + super("์ด๋ฏธ์ง€ ํŒŒ์ผ 50KB ์ดˆ๊ณผ", ErrorCode.USER_IMAGE_TOO_LARGE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemImageTypeException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemImageTypeException.java new file mode 100644 index 000000000..e33ca349c --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemImageTypeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class ItemImageTypeException extends FileException { + public ItemImageTypeException() { + super("์ด๋ฏธ์ง€ ํƒ€์ž…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค", ErrorCode.ITEM_IMAGE_WRONG_TYPE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemNotAvailableException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotAvailableException.java new file mode 100644 index 000000000..6f3215d29 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotAvailableException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class ItemNotAvailableException extends FileException { + public ItemNotAvailableException() { + super("์•„์ดํ…œ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค", ErrorCode.ITEM_NOT_AVAILABLE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotFoundException.java new file mode 100644 index 000000000..169a7092e --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class ItemNotFoundException extends NotExistException { + public ItemNotFoundException() { + super("์•„์ดํ…œ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.ITEM_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemNotPurchasableException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotPurchasableException.java new file mode 100644 index 000000000..35733742c --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemNotPurchasableException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class ItemNotPurchasableException extends BusinessException { + public ItemNotPurchasableException() { + super("์ง€๊ธˆ์€ ๊ตฌ๋งคํ•  ์ˆ˜ ์—†๋Š” ์•„์ดํ…œ ์ž…๋‹ˆ๋‹ค.", ErrorCode.ITEM_NOT_PURCHASABLE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/ItemTypeException.java b/gg-utils/src/main/java/gg/utils/exception/item/ItemTypeException.java new file mode 100644 index 000000000..0b4b71ba6 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/ItemTypeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class ItemTypeException extends BusinessException { + public ItemTypeException() { + super("์•„์ดํ…œ ํƒ€์ž… ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.ITEM_TYPE_NOT_MATCHED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/KakaoGiftException.java b/gg-utils/src/main/java/gg/utils/exception/item/KakaoGiftException.java new file mode 100644 index 000000000..dc9e3c848 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/KakaoGiftException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class KakaoGiftException extends BusinessException { + public KakaoGiftException() { + super("์นด์นด์˜ค ๊ฒŒ์ŠคํŠธ๋Š” ์„ ๋ฌผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.GUEST_ROLE_GIFT_FORBIDDEN); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/item/KakaoPurchaseException.java b/gg-utils/src/main/java/gg/utils/exception/item/KakaoPurchaseException.java new file mode 100644 index 000000000..ad95b4736 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/item/KakaoPurchaseException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.item; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class KakaoPurchaseException extends BusinessException { + public KakaoPurchaseException() { + super("์นด์นด์˜ค ๊ฒŒ์ŠคํŠธ๋Š” ๊ตฌ๋งคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.GUEST_ROLE_PURCHASE_FORBIDDEN); + } +} + diff --git a/gg-utils/src/main/java/gg/utils/exception/match/EnrolledSlotException.java b/gg-utils/src/main/java/gg/utils/exception/match/EnrolledSlotException.java new file mode 100644 index 000000000..c742a4836 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/EnrolledSlotException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class EnrolledSlotException extends DuplicationException { + public EnrolledSlotException() { + super("์ด๋ฏธ ๋“ฑ๋ก๋œ ์Šฌ๋กฏ์ž…๋‹ˆ๋‹ค.", ErrorCode.SLOT_ENROLLED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/LosingTeamNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/match/LosingTeamNotFoundException.java new file mode 100644 index 000000000..56d3694c7 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/LosingTeamNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class LosingTeamNotFoundException extends NotExistException { + public LosingTeamNotFoundException() { + super(ErrorCode.LOSING_TEAM_NOT_FOUND.getMessage(), ErrorCode.LOSING_TEAM_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/OptionInvalidException.java b/gg-utils/src/main/java/gg/utils/exception/match/OptionInvalidException.java new file mode 100644 index 000000000..8be54a9ed --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/OptionInvalidException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; + +public class OptionInvalidException extends InvalidParameterException { + public OptionInvalidException() { + super("์กด์žฌํ•˜์ง€ ์•Š์€ mode ์ž…๋‹ˆ๋‹ค", ErrorCode.MODE_INVALID); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/PastSlotException.java b/gg-utils/src/main/java/gg/utils/exception/match/PastSlotException.java new file mode 100644 index 000000000..42cc5105d --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/PastSlotException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ExpiredException; + +public class PastSlotException extends ExpiredException { + public PastSlotException() { + super("ํ˜„์žฌ ์‹œ๊ฐ ์ด์ „ ์Šฌ๋กฏ์€ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_PAST); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/PenaltyUserSlotException.java b/gg-utils/src/main/java/gg/utils/exception/match/PenaltyUserSlotException.java new file mode 100644 index 000000000..008b72545 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/PenaltyUserSlotException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class PenaltyUserSlotException extends BusinessException { + public PenaltyUserSlotException() { + super("ํŒจ๋„ํ‹ฐ ๋ฐ›์€ ์œ ์ €๋Š” ๊ฒŒ์ž„์„ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.PENALTY_USER_ENROLLED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/SlotCountException.java b/gg-utils/src/main/java/gg/utils/exception/match/SlotCountException.java new file mode 100644 index 000000000..44d51473d --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/SlotCountException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class SlotCountException extends BusinessException { + public SlotCountException() { + super("์Šฌ๋กฏ ๋“ฑ๋ก ํšŸ์ˆ˜ 3ํšŒ๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_COUNT_EXCEEDED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/SlotNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/match/SlotNotFoundException.java new file mode 100644 index 000000000..db6e3617f --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/SlotNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class SlotNotFoundException extends NotExistException { + public SlotNotFoundException() { + super("์œ ์ €๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/match/WinningTeamNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/match/WinningTeamNotFoundException.java new file mode 100644 index 000000000..cd018bb7d --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/match/WinningTeamNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.match; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class WinningTeamNotFoundException extends NotExistException { + public WinningTeamNotFoundException() { + super(ErrorCode.WINNING_TEAM_NOT_FOUND.getMessage(), ErrorCode.WINNING_TEAM_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneContentException.java b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneContentException.java new file mode 100644 index 000000000..e0a7fe332 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneContentException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.megaphone; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class MegaphoneContentException extends BusinessException { + public MegaphoneContentException() { + super("ํ™•์„ฑ๊ธฐ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_CONTENT); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneNotFoundException.java new file mode 100644 index 000000000..1cd7ebfd6 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.megaphone; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class MegaphoneNotFoundException extends NotExistException { + public MegaphoneNotFoundException() { + super("ํ™•์„ฑ๊ธฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_TIME); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneTimeException.java b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneTimeException.java new file mode 100644 index 000000000..29638bd25 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/megaphone/MegaphoneTimeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.megaphone; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class MegaphoneTimeException extends BusinessException { + public MegaphoneTimeException() { + super("ํ™•์„ฑ๊ธฐ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_TIME); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/noti/SlackJsonParseException.java b/gg-utils/src/main/java/gg/utils/exception/noti/SlackJsonParseException.java new file mode 100644 index 000000000..08e7ab4b8 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/noti/SlackJsonParseException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.noti; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ParseException; + +public class SlackJsonParseException extends ParseException { + public SlackJsonParseException() { + super("json parse error in getDmChannelId()", ErrorCode.SLACK_JSON_PARSE_ERR); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/noti/SlackSendException.java b/gg-utils/src/main/java/gg/utils/exception/noti/SlackSendException.java new file mode 100644 index 000000000..ecdedd880 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/noti/SlackSendException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.noti; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.SendException; + +public class SlackSendException extends SendException { + public SlackSendException() { + super("fail to send notification", ErrorCode.SLACK_SEND_FAIL); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/noti/SlackUserGetFailedException.java b/gg-utils/src/main/java/gg/utils/exception/noti/SlackUserGetFailedException.java new file mode 100644 index 000000000..ca437d365 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/noti/SlackUserGetFailedException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.noti; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class SlackUserGetFailedException extends NotExistException { + public SlackUserGetFailedException() { + super("fail to get slack user info", ErrorCode.SLACK_USER_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/pchange/PChangeNotExistException.java b/gg-utils/src/main/java/gg/utils/exception/pchange/PChangeNotExistException.java new file mode 100644 index 000000000..76803d01b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/pchange/PChangeNotExistException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.pchange; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class PChangeNotExistException extends NotExistException { + public PChangeNotExistException() { + super(ErrorCode.PCHANGE_NOT_FOUND.getMessage(), ErrorCode.PCHANGE_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyExpiredException.java b/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyExpiredException.java new file mode 100644 index 000000000..612ed0f82 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyExpiredException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.penalty; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ExpiredException; + +public class PenaltyExpiredException extends ExpiredException { + public PenaltyExpiredException() { + super("์ด๋ฏธ ๋งŒ๋ฃŒ๋œ ํŒจ๋„ํ‹ฐ์ž…๋‹ˆ๋‹ค.", ErrorCode.PENALTY_EXPIRED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyNotFoundException.java new file mode 100644 index 000000000..6ff0260f6 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/penalty/PenaltyNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.penalty; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class PenaltyNotFoundException extends NotExistException { + public PenaltyNotFoundException() { + super("ํ•ด๋‹น ํŒจ๋„ํ‹ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.PENALTY_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/penalty/RedisPenaltyUserNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/penalty/RedisPenaltyUserNotFoundException.java new file mode 100644 index 000000000..efaab7bc4 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/penalty/RedisPenaltyUserNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.penalty; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class RedisPenaltyUserNotFoundException extends NotExistException { + public RedisPenaltyUserNotFoundException() { + super("Redis์— Penalty User ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.REDIS_PENALTY_USER_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/rank/RankNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/rank/RankNotFoundException.java new file mode 100644 index 000000000..2d7889d27 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/rank/RankNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.rank; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class RankNotFoundException extends NotExistException { + public RankNotFoundException() { + super("๋žญํฌ ํ…Œ์ด๋ธ”์— ์—†๋Š” ์œ ์ €์ž…๋‹ˆ๋‹ค.", ErrorCode.RANK_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/rank/RankUpdateException.java b/gg-utils/src/main/java/gg/utils/exception/rank/RankUpdateException.java new file mode 100644 index 000000000..af866cec9 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/rank/RankUpdateException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.rank; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; + +public class RankUpdateException extends InvalidParameterException { + public RankUpdateException() { + super("Ppp๋ฅผ ์ˆ˜์ • ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค", ErrorCode.RANK_UPDATE_FAIL); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/rank/RedisDataNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/rank/RedisDataNotFoundException.java new file mode 100644 index 000000000..2795a5bf8 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/rank/RedisDataNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.rank; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class RedisDataNotFoundException extends NotExistException { + public RedisDataNotFoundException() { + super("Redis์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.REDIS_RANK_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/receipt/ItemStatusException.java b/gg-utils/src/main/java/gg/utils/exception/receipt/ItemStatusException.java new file mode 100644 index 000000000..f2c6195e3 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/receipt/ItemStatusException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.receipt; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.BusinessException; + +public class ItemStatusException extends BusinessException { + public ItemStatusException() { + super("์•„์ดํ…œ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_STATUS_NOT_MATCHED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotFoundException.java new file mode 100644 index 000000000..7bf1e361b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.receipt; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class ReceiptNotFoundException extends NotExistException { + public ReceiptNotFoundException() { + super("ํ•ด๋‹น ๊ฑฐ๋ž˜๋‚ด์—ญ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotOwnerException.java b/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotOwnerException.java new file mode 100644 index 000000000..22fd37ccb --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/receipt/ReceiptNotOwnerException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.receipt; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ForbiddenException; + +public class ReceiptNotOwnerException extends ForbiddenException { + public ReceiptNotOwnerException() { + super("์•„์ดํ…œ์˜ ์†Œ์œ ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_NOT_OWNER); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/season/SeasonForbiddenException.java b/gg-utils/src/main/java/gg/utils/exception/season/SeasonForbiddenException.java new file mode 100644 index 000000000..75b38f409 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/season/SeasonForbiddenException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.season; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ForbiddenException; + +public class SeasonForbiddenException extends ForbiddenException { + public SeasonForbiddenException() { + super(ErrorCode.SEASON_FORBIDDEN.getMessage(), ErrorCode.SEASON_FORBIDDEN); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/season/SeasonNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/season/SeasonNotFoundException.java new file mode 100644 index 000000000..f2deb06b5 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/season/SeasonNotFoundException.java @@ -0,0 +1,14 @@ +package gg.utils.exception.season; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class SeasonNotFoundException extends NotExistException { + public SeasonNotFoundException() { + super("์‹œ์ฆŒ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SEASON_NOT_FOUND); + } + + public SeasonNotFoundException(String message) { + super(message, ErrorCode.SEASON_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/season/SeasonTimeBeforeException.java b/gg-utils/src/main/java/gg/utils/exception/season/SeasonTimeBeforeException.java new file mode 100644 index 000000000..dae95b716 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/season/SeasonTimeBeforeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.season; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ForbiddenException; + +public class SeasonTimeBeforeException extends ForbiddenException { + public SeasonTimeBeforeException() { + super(ErrorCode.SEASON_TIME_BEFORE.getMessage(), ErrorCode.SEASON_TIME_BEFORE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementForbiddenException.java b/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementForbiddenException.java new file mode 100644 index 000000000..e6fd5b57b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementForbiddenException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.slotmanagement; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ForbiddenException; + +public class SlotManagementForbiddenException extends ForbiddenException { + public SlotManagementForbiddenException() { + super(ErrorCode.SLOTMANAGEMENT_FORBIDDEN.getMessage(), ErrorCode.SLOTMANAGEMENT_FORBIDDEN); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementNotFoundException.java new file mode 100644 index 000000000..46700252a --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/slotmanagement/SlotManagementNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.slotmanagement; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class SlotManagementNotFoundException extends NotExistException { + public SlotManagementNotFoundException() { + super(ErrorCode.SLOTMANAGEMENT_NOT_FOUND.getMessage(), ErrorCode.SLOTMANAGEMENT_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/team/TeamIdNotMatchException.java b/gg-utils/src/main/java/gg/utils/exception/team/TeamIdNotMatchException.java new file mode 100644 index 000000000..17b1247b7 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/team/TeamIdNotMatchException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.team; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class TeamIdNotMatchException extends NotExistException { + public TeamIdNotMatchException() { + super(ErrorCode.TEAM_ID_NOT_MATCH.getMessage(), ErrorCode.TEAM_ID_NOT_MATCH); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/team/TeamNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/team/TeamNotFoundException.java new file mode 100644 index 000000000..80c859c7d --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/team/TeamNotFoundException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.team; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class TeamNotFoundException extends NotExistException { + + public TeamNotFoundException() { + super(ErrorCode.TEAM_NOT_FOUND.getMessage(), ErrorCode.TEAM_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/tier/TierNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/tier/TierNotFoundException.java new file mode 100644 index 000000000..4b75d4609 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/tier/TierNotFoundException.java @@ -0,0 +1,11 @@ +package gg.utils.exception.tier; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class TierNotFoundException extends NotExistException { + public TierNotFoundException() { + super("ํ•ด๋‹น ํ‹ฐ์–ด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.TIER_NOT_FOUND); + } + +} diff --git a/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentConflictException.java b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentConflictException.java new file mode 100644 index 000000000..96f009d6b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentConflictException.java @@ -0,0 +1,14 @@ +package gg.utils.exception.tournament; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class TournamentConflictException extends DuplicationException { + public TournamentConflictException() { + super(ErrorCode.TOURNAMENT_CONFLICT.getMessage(), ErrorCode.TOURNAMENT_CONFLICT); + } + + public TournamentConflictException(ErrorCode errorCode) { + super(errorCode.getMessage(), errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentGameNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentGameNotFoundException.java new file mode 100644 index 000000000..547bfa3ed --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentGameNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.tournament; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class TournamentGameNotFoundException extends NotExistException { + public TournamentGameNotFoundException() { + super(ErrorCode.TOURNAMENT_GAME_NOT_FOUND.getMessage(), ErrorCode.TOURNAMENT_GAME_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentNotFoundException.java new file mode 100644 index 000000000..0b6f2169e --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentNotFoundException.java @@ -0,0 +1,14 @@ +package gg.utils.exception.tournament; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class TournamentNotFoundException extends NotExistException { + public TournamentNotFoundException() { + super(ErrorCode.TOURNAMENT_NOT_FOUND.getMessage(), ErrorCode.TOURNAMENT_NOT_FOUND); + } + + public TournamentNotFoundException(ErrorCode errorCode) { + super(errorCode.getMessage(), errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentUpdateException.java b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentUpdateException.java new file mode 100644 index 000000000..bb74f0bf2 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/tournament/TournamentUpdateException.java @@ -0,0 +1,14 @@ +package gg.utils.exception.tournament; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.ForbiddenException; + +public class TournamentUpdateException extends ForbiddenException { + public TournamentUpdateException() { + super(ErrorCode.TOURNAMENT_CAN_NOT_UPDATE.getMessage(), ErrorCode.TOURNAMENT_CAN_NOT_UPDATE); + } + + public TournamentUpdateException(ErrorCode errorCode) { + super(errorCode.getMessage(), errorCode); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2AlreadyExistException.java b/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2AlreadyExistException.java new file mode 100644 index 000000000..df1fb40c9 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2AlreadyExistException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.InvalidParameterException; + +public class KakaoOauth2AlreadyExistException extends InvalidParameterException { + public KakaoOauth2AlreadyExistException() { + super("kakao user already exists", ErrorCode.KAKAO_OAUTH2_DUPLICATE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2NotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2NotFoundException.java new file mode 100644 index 000000000..dc28347c4 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/KakaoOauth2NotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class KakaoOauth2NotFoundException extends NotExistException { + public KakaoOauth2NotFoundException() { + super("Kakao oauth2 is not found", ErrorCode.KAKAO_OAUTH2_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/TokenNotValidException.java b/gg-utils/src/main/java/gg/utils/exception/user/TokenNotValidException.java new file mode 100644 index 000000000..cbbfd9193 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/TokenNotValidException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.AuthenticationException; + +public class TokenNotValidException extends AuthenticationException { + public TokenNotValidException() { + super("Authentication error", ErrorCode.UNAUTHORIZED); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserAlreadyAttendanceException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserAlreadyAttendanceException.java new file mode 100644 index 000000000..f74c197fa --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserAlreadyAttendanceException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.DuplicationException; + +public class UserAlreadyAttendanceException extends DuplicationException { + public UserAlreadyAttendanceException() { + super("์ด๋ฏธ ์ถœ์„ํ•œ ์œ ์ €์ž…๋‹ˆ๋‹ค.", ErrorCode.USER_ALREADY_ATTENDANCE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserImageLargeException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserImageLargeException.java new file mode 100644 index 000000000..27ed0dd3c --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserImageLargeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class UserImageLargeException extends FileException { + public UserImageLargeException() { + super("์ด๋ฏธ์ง€ ํŒŒ์ผ 50KB ์ดˆ๊ณผ", ErrorCode.USER_IMAGE_TOO_LARGE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserImageNullException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserImageNullException.java new file mode 100644 index 000000000..9aec8e78f --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserImageNullException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class UserImageNullException extends FileException { + public UserImageNullException() { + super("์ด๋ฏธ์ง€ ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.USER_IMAGE_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserImageTypeException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserImageTypeException.java new file mode 100644 index 000000000..f91545dab --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserImageTypeException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.FileException; + +public class UserImageTypeException extends FileException { + public UserImageTypeException() { + super("์ด๋ฏธ์ง€ ํƒ€์ž…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค", ErrorCode.USER_IMAGE_WRONG_TYPE); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserNotFoundException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserNotFoundException.java new file mode 100644 index 000000000..3144512f6 --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserNotFoundException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.NotExistException; + +public class UserNotFoundException extends NotExistException { + public UserNotFoundException() { + super("ํ•ด๋‹น ์œ ์ €๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.USER_NOT_FOUND); + } +} diff --git a/gg-utils/src/main/java/gg/utils/exception/user/UserTextColorException.java b/gg-utils/src/main/java/gg/utils/exception/user/UserTextColorException.java new file mode 100644 index 000000000..1f9b1440b --- /dev/null +++ b/gg-utils/src/main/java/gg/utils/exception/user/UserTextColorException.java @@ -0,0 +1,10 @@ +package gg.utils.exception.user; + +import gg.utils.exception.ErrorCode; +import gg.utils.exception.custom.CustomRuntimeException; + +public class UserTextColorException extends CustomRuntimeException { + public UserTextColorException() { + super("user text color code is not valid", ErrorCode.USER_TEXT_COLOR_WRONG_TYPE); + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/ItemTestUtils.java b/gg-utils/src/testFixtures/java/gg/utils/ItemTestUtils.java new file mode 100644 index 000000000..68ea7dc0f --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/ItemTestUtils.java @@ -0,0 +1,68 @@ +package gg.utils; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import org.springframework.stereotype.Component; + +import gg.data.store.Item; +import gg.data.store.Megaphone; +import gg.data.store.Receipt; +import gg.data.store.type.ItemStatus; +import gg.data.user.User; +import gg.pingpong.api.admin.store.controller.request.ItemUpdateRequestDto; +import gg.repo.store.ItemRepository; +import gg.repo.store.MegaphoneRepository; +import gg.repo.store.ReceiptRepository; +import lombok.AllArgsConstructor; + +/** + * ItemTestUtils. + * + *

+ * + *

+ * + * @author : middlefitting + * @since : 2023/12/08 + */ +@Component +@AllArgsConstructor +public class ItemTestUtils { + + ItemRepository itemRepository; + + ReceiptRepository receiptRepository; + + MegaphoneRepository megaphoneRepository; + + /** + * ์•„์ดํ…œ์„ ๊ตฌ๋งคํ•œ๋‹ค.(์˜์ˆ˜์ฆ ์ƒ์„ฑ) + */ + public Receipt purchaseItem(User purchaser, User owner, Item item) { + Receipt receipt = new Receipt(item, purchaser.getIntraId(), owner.getIntraId(), + ItemStatus.BEFORE, LocalDateTime.now()); + return receiptRepository.save(receipt); + } + + /** + * ์•„์ดํ…œ์„ ์ƒ์„ฑํ•œ๋‹ค. + */ + public Item createItem(User creator, ItemUpdateRequestDto updateRequestDto) { + Item item = updateRequestDto.toItem("42gg-s3", creator.getIntraId()); + itemRepository.save(item); + return item; + } + + /** + * ๋ฉ”๊ฐ€ํฐ์„ ์ƒ์„ฑํ•œ๋‹ค. + * ํ˜„์žฌ ์„œ๋น„์Šค์— ๋งž๊ฒŒ WAITING ์ƒํƒœ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. + */ + public Megaphone createMegaPhone(User user, Receipt receipt, String content) { + Megaphone mega = new Megaphone(user, receipt, content, LocalDate.now().plusDays(1)); + receipt.updateStatus(ItemStatus.WAITING); + receiptRepository.save(receipt); + megaphoneRepository.save(mega); + return mega; + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/TestDataUtils.java b/gg-utils/src/testFixtures/java/gg/utils/TestDataUtils.java new file mode 100644 index 000000000..9de9768b6 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/TestDataUtils.java @@ -0,0 +1,769 @@ +package gg.utils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.springframework.stereotype.Component; + +import gg.data.game.Game; +import gg.data.game.PChange; +import gg.data.game.Team; +import gg.data.game.TeamUser; +import gg.data.game.type.Mode; +import gg.data.game.type.StatusType; +import gg.data.manage.Announcement; +import gg.data.manage.SlotManagement; +import gg.data.noti.Noti; +import gg.data.noti.type.NotiType; +import gg.data.rank.Rank; +import gg.data.rank.Tier; +import gg.data.rank.redis.RankRedis; +import gg.data.season.Season; +import gg.data.store.CoinPolicy; +import gg.data.tournament.Tournament; +import gg.data.tournament.TournamentGame; +import gg.data.tournament.TournamentUser; +import gg.data.tournament.type.TournamentRound; +import gg.data.tournament.type.TournamentStatus; +import gg.data.tournament.type.TournamentType; +import gg.data.user.User; +import gg.data.user.UserImage; +import gg.data.user.type.RacketType; +import gg.data.user.type.RoleType; +import gg.data.user.type.SnsType; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminCreateRequestDto; +import gg.pingpong.api.admin.tournament.controller.request.TournamentAdminUpdateRequestDto; +import gg.pingpong.api.global.security.jwt.utils.AuthTokenProvider; +import gg.pingpong.api.user.tournament.controller.response.TournamentResponseDto; +import gg.pingpong.api.user.user.dto.UserImageDto; +import gg.repo.game.GameRepository; +import gg.repo.game.PChangeRepository; +import gg.repo.game.TeamRepository; +import gg.repo.game.TeamUserRepository; +import gg.repo.manage.AnnouncementRepository; +import gg.repo.manage.SlotManagementRepository; +import gg.repo.noti.NotiRepository; +import gg.repo.rank.RankRepository; +import gg.repo.rank.TierRepository; +import gg.repo.rank.redis.RankRedisRepository; +import gg.repo.season.SeasonRepository; +import gg.repo.store.CoinPolicyRepository; +import gg.repo.tournarment.TournamentGameRepository; +import gg.repo.tournarment.TournamentRepository; +import gg.repo.tournarment.TournamentUserRepository; +import gg.repo.user.UserImageRepository; +import gg.repo.user.UserRepository; +import gg.utils.dto.GameInfoDto; +import gg.utils.exception.game.GameNotExistException; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class TestDataUtils { + private final UserRepository userRepository; + private final AuthTokenProvider tokenProvider; + private final NotiRepository notiRepository; + private final SeasonRepository seasonRepository; + private final GameRepository gameRepository; + private final TeamUserRepository teamUserRepository; + private final TeamRepository teamRepository; + private final RankRedisRepository redisRepository; + private final PChangeRepository pChangeRepository; + private final RankRepository rankRepository; + private final TierRepository tierRepository; + private final TournamentRepository tournamentRepository; + private final TournamentGameRepository tournamentGameRepository; + private final TournamentUserRepository tournamentUserRepository; + private final AnnouncementRepository announcementRepository; + private final CoinPolicyRepository coinPolicyRepository; + private final UserImageRepository userImageRepository; + private final SlotManagementRepository slotManagementRepository; + + public String getLoginAccessToken() { + User user = User.builder() + .eMail("email") + .intraId("intraId") + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return tokenProvider.createToken(user.getId()); + } + + public String getLoginAccessTokenFromUser(User user) { + return tokenProvider.createToken(user.getId()); + } + + public String getAdminLoginAccessToken() { + User user = User.builder() + .eMail("email") + .intraId("intraId") + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.ADMIN) + .totalExp(1000) + .build(); + userRepository.save(user); + return tokenProvider.createToken(user.getId()); + } + + public User createAdminUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.ADMIN) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + /** + * Item ์—๋Š” ์ธํŠธ๋ผ ID๊ฐ€ ํ˜„์žฌ 10์ž๋กœ ์ œํ•œ๋˜์–ด ์žˆ์Œ + */ + public User createAdminUserForItem() { + String randomId = UUID.randomUUID().toString().substring(0, 10); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.ADMIN) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser() { + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser(String intraId) { + User user = User.builder() + .eMail("email") + .intraId(intraId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(1000) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser(String intraId, String email, RacketType racketType, + SnsType snsType, RoleType roleType) { + User user = User.builder() + .eMail(email) + .intraId(intraId) + .racketType(racketType) + .snsNotiOpt(snsType) + .roleType(roleType) + .totalExp(0) + .build(); + userRepository.save(user); + return user; + } + + public User createNewUser(int totalExp) { + String randomId = UUID.randomUUID().toString().substring(0, 30); + User user = User.builder() + .eMail("email") + .intraId(randomId) + .racketType(RacketType.PENHOLDER) + .snsNotiOpt(SnsType.NONE) + .roleType(RoleType.USER) + .totalExp(totalExp) + .build(); + userRepository.save(user); + return user; + } + + public GameInfoDto addMockDataUserLiveApi(String event, int notiCnt, String currentMatchMode, Long userId) { + User curUser = userRepository.findById(userId).get(); + for (int i = 0; i < notiCnt; i++) { + Noti noti = new Noti(curUser, NotiType.ANNOUNCE, String.valueOf(i), false); + notiRepository.save(noti); + } + LocalDateTime startTime; + LocalDateTime endTime; + Season season = createSeason(); + createUserRank(curUser, "testUserMessage", season); + Mode mode = (currentMatchMode.equals(Mode.RANK.getCode())) ? Mode.RANK : Mode.NORMAL; + createGame(curUser, LocalDateTime.now().minusMinutes(100), LocalDateTime.now().minusMinutes(85), season, mode); + createGame(curUser, LocalDateTime.now().minusMinutes(50), LocalDateTime.now().minusMinutes(35), season, mode); + LocalDateTime now = LocalDateTime.now(); + if (event.equals("match")) { + startTime = now.plusMinutes(10); + endTime = startTime.plusMinutes(15); + return createGame(curUser, startTime, endTime, season, mode); + } else if (event.equals("game")) { + startTime = now.minusMinutes(5); + endTime = startTime.plusMinutes(15); + return createGame(curUser, startTime, endTime, season, mode); + } + return null; + } + + public GameInfoDto createGame(User curUser, LocalDateTime startTime, LocalDateTime endTime, Season season, + Mode mode) { + LocalDateTime now = LocalDateTime.now(); + Game game; + if (now.isBefore(startTime)) { + game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); + } else if (now.isAfter(startTime) && now.isBefore(endTime)) { + game = new Game(season, StatusType.LIVE, mode, startTime, endTime); + } else { + game = new Game(season, StatusType.END, mode, startTime, endTime); + } + Team myTeam = new Team(game, -1, false); + TeamUser teamUser = new TeamUser(myTeam, curUser); + User enemyUser = createNewUser(); + Team enemyTeam = new Team(game, -1, false); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + createUserRank(curUser, "statusMessage", season); + createUserRank(enemyUser, "enemyUserMeassage", season); + gameRepository.save(game); + return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), enemyUser.getId()); + } + + public Season createSeason() { + LocalDateTime startTime = LocalDateTime.now().minusMinutes(5); + LocalDateTime endTime = startTime.plusMonths(1); + Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()).orElse(null); + if (season == null) { + season = new Season("name", startTime.minusMinutes(1), endTime, 1000, 300); + } + seasonRepository.save(season); + return season; + } + + public void createUserRank(User newUser, String statusMessage, Season season) { + if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) { + return; + } + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(season.getStartPpp()) + .wins(0) + .losses(0) + .statusMessage(statusMessage) + .build(); + rankRepository.save(userRank); + } + + public void createUserRank(User newUser, String statusMessage, Season season, Tier tier) { + if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) { + return; + } + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(season.getStartPpp()) + .wins(0) + .losses(0) + .statusMessage(statusMessage) + .tier(tier) + .build(); + rankRepository.save(userRank); + } + + public void createUserRank(User newUser, String statusMessage, Season season, int ppp) { + String zSetKey = RedisKeyManager.getZSetKey(season.getId()); + String hashKey = RedisKeyManager.getHashKey(season.getId()); + Tier tier = tierRepository.findStartTier().get(); + redisRepository.addToZSet(zSetKey, newUser.getId(), ppp); + redisRepository.addRankData(hashKey, newUser.getId(), + new RankRedis(newUser.getId(), "aa", ppp, 1, 0, statusMessage, + "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); + Rank userRank = Rank.builder() + .user(newUser) + .season(season) + .ppp(ppp) + .wins(1) + .losses(0) + .statusMessage(statusMessage) + .tier(tier) + .build(); + rankRepository.save(userRank); + } + + public void createMockMatchWithMockRank(User newUser, Season season, LocalDateTime startTime, + LocalDateTime endTime) { + Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, 0, false); + TeamUser teamUser = new TeamUser(myTeam, newUser); + Team enemyTeam = new Team(game, 0, false); + User enemyUser = createNewUser(); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + createUserRank(enemyUser, "status message", season); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + PChange pChange1 = new PChange(game, newUser, 1100, true); + PChange pChange2 = new PChange(game, enemyUser, 900, true); + pChangeRepository.save(pChange1); + pChangeRepository.save(pChange2); + } + + public void createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime) { + Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, 0, false); + TeamUser teamUser = new TeamUser(myTeam, newUser); + Team enemyTeam = new Team(game, 0, false); + User enemyUser = createNewUser(); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + PChange pChange1 = new PChange(game, newUser, 1100, true); + PChange pChange2 = new PChange(game, enemyUser, 900, true); + + pChangeRepository.save(pChange1); + pChangeRepository.save(pChange2); + } + + public Game createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime, + Mode mode) { + Game game = new Game(season, StatusType.END, mode, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, 0, false); + TeamUser teamUser = new TeamUser(myTeam, newUser); + Team enemyTeam = new Team(game, 0, false); + User enemyUser = createNewUser(); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + PChange pChange1 = new PChange(game, newUser, 1100, true); + PChange pChange2 = new PChange(game, enemyUser, 900, true); + + pChangeRepository.save(pChange1); + pChangeRepository.save(pChange2); + return game; + } + + public Game createMockMatch(User newUser, Season season, LocalDateTime startTime, + LocalDateTime endTime, Mode mode, int myScore, int enemyScore) { + Game game = new Game(season, StatusType.END, mode, startTime, endTime); + gameRepository.save(game); + Team myTeam = new Team(game, myScore, myScore > enemyScore); + TeamUser teamUser = new TeamUser(myTeam, newUser); + Team enemyTeam = new Team(game, enemyScore, enemyScore > myScore); + User enemyUser = createNewUser(); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + PChange pChange1 = new PChange(game, newUser, 1100, true); + PChange pChange2 = new PChange(game, enemyUser, 900, true); + + pChangeRepository.save(pChange1); + pChangeRepository.save(pChange2); + return game; + } + + /** + *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

+ * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @param status ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ + * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ + */ + public Tournament createTournament(LocalDateTime startTime, LocalDateTime endTime, TournamentStatus status) { + Tournament tournament = Tournament.builder() + .title("title") + .contents("contents") + .startTime(startTime) + .endTime(endTime) + .type(TournamentType.ROOKIE) + .status(status).build(); + return tournamentRepository.save(tournament); + } + + /** + * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. + * @param title ์ œ๋ชฉ + * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @param status ์ƒํƒœ + * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ + */ + public Tournament createTournament(String title, LocalDateTime startTime, LocalDateTime endTime, + TournamentStatus status) { + Tournament tournament = Tournament.builder() + .title(title) + .contents("contents") + .startTime(startTime) + .endTime(endTime) + .type(TournamentType.ROOKIE) + .status(status).build(); + return tournamentRepository.save(tournament); + } + + /** + * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. + * @param title ์ œ๋ชฉ + * @param contents ๋‚ด์šฉ + * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @param type ํƒ€์ž… + * @param status ์ƒํƒœ + * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ + */ + public Tournament createTournament(String title, String contents, LocalDateTime startTime, LocalDateTime + endTime, + TournamentType type, TournamentStatus status) { + Tournament tournament = Tournament.builder() + .title(title) + .contents(contents) + .startTime(startTime) + .endTime(endTime) + .type(type) + .status(status).build(); + return tournamentRepository.save(tournament); + } + + /** + * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ RequestDto ๋ฐ˜ํ™˜. + * @param startTime + * @param endTime + * @param type + * @return + */ + public TournamentAdminCreateRequestDto createRequestDto(LocalDateTime startTime, LocalDateTime endTime, + TournamentType type) { + return new TournamentAdminCreateRequestDto( + "1st rookie tournament", + "welcome !", + startTime, + endTime, + type); + } + + /** + *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

+ * @param tournamentType + * @param tournamentStatus + * @return + */ + public Tournament createTournamentByEnum(TournamentType tournamentType, TournamentStatus tournamentStatus, + LocalDateTime startTime) { + Tournament tournament = Tournament.builder() + .title("testTournament") + .contents("contents") + .startTime(startTime) + .endTime(startTime.plusDays(1)) + .type(tournamentType) + .status(tournamentStatus).build(); + return tournamentRepository.save(tournament); + } + + /** + * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ RequestDto ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™” + * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ + * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ + * @param type ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜ + * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ RequestDto + */ + public TournamentAdminUpdateRequestDto createUpdateRequestDto(LocalDateTime startTime, LocalDateTime endTime, + TournamentType type) { + return new TournamentAdminUpdateRequestDto( + "title", + "contents", + startTime, + endTime, + type); + } + + /** + *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

+ * @param tournament ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์— ๋„ฃ์–ด ์ค„ ํ† ๋„ˆ๋จผํŠธ + * @param cnt ๋ฐ˜ํ™˜ ๋ฆฌ์ŠคํŠธ ํฌ๊ธฐ, 8๊ฐ•๊ธฐ์ค€ 7๊ฐœ + * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ + */ + public List createTournamentGameList(Tournament tournament, int cnt) { + List tournamentGameList = new ArrayList<>(); + TournamentRound[] values = TournamentRound.values(); + + while (--cnt >= 0) { + tournamentGameList.add(new TournamentGame(null, tournament, values[cnt])); + } + return tournamentGameRepository.saveAll(tournamentGameList); + } + + /** + *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์ƒ์„ฑ ๋ฐ ์ €์žฅ

+ * @param user ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ์œ ์ € + * @param tournament ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ + * @param isJoined ์ฐธ๊ฐ€์ž 1, ๋Œ€๊ธฐ์ž 0 + * @return + */ + public TournamentUser createTournamentUser(User user, Tournament tournament, boolean isJoined) { + TournamentUser tournamentUser = new TournamentUser(user, tournament, isJoined, LocalDateTime.now()); + return tournamentUserRepository.save(tournamentUser); + } + + public List makeTournamentList() { + int joinUserCnt = 8; + int notJoinUserCnt = 4; + List tournamentResponseDtos = new ArrayList<>(); + + User winner = createNewUser("winner_sgo", "winner@gmail.com", RacketType.PENHOLDER, SnsType.NONE, + RoleType.USER); + UserImageDto winnerImage = new UserImageDto(winner); + for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { + User newUser = createNewUser("42gg_tester" + i, "tester" + i + "@gmail.com", RacketType.PENHOLDER, + SnsType.NONE, RoleType.USER); + userRepository.save(newUser); + } + int day = 100; + for (TournamentType type : TournamentType.values()) { + for (TournamentStatus status : TournamentStatus.values()) { + for (int i = 0; i < 5; i++) { + Tournament tournament = createTournamentByEnum(type, status, + LocalDateTime.now().plusDays(day++)); + tournamentResponseDtos.add(new TournamentResponseDto(tournament, winnerImage, joinUserCnt)); + tournament.updateWinner(winner); + for (int j = 0; j < joinUserCnt; j++) { + TournamentUser tournamentUser = new TournamentUser( + userRepository.findByIntraId("42gg_tester" + j).get(), tournament, true, + LocalDateTime.now()); + tournamentUserRepository.save(tournamentUser); + // tournament.getTournamentUsers().add(tournamentUser); + } + for (int j = joinUserCnt; j < joinUserCnt + notJoinUserCnt; j++) { + TournamentUser tournamentUser = new TournamentUser( + userRepository.findByIntraId("42gg_tester" + j).get(), tournament, false, + LocalDateTime.now()); + tournamentUserRepository.save(tournamentUser); + // tournament.getTournamentUsers().add(tournamentUser); + } + tournamentRepository.save(tournament); + } + } + } + tournamentResponseDtos.sort((o1, o2) -> o2.getStartTime().compareTo(o1.getStartTime())); + return tournamentResponseDtos; + } + + public Tournament createTournamentWithUser(int joinUserCnt, int notJoinUserCnt, String testName) { + Tournament tournament = Tournament.builder() + .title("testTournament") + .contents("contents") + .startTime(LocalDateTime.now()) + .endTime(LocalDateTime.now().plusDays(1)) + .type(TournamentType.ROOKIE) + .status(TournamentStatus.BEFORE).build(); + for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { + User newUser = createNewUser(testName + i, "tester" + i + "@gmail.com", RacketType.PENHOLDER, + SnsType.NONE, + RoleType.USER); + userRepository.save(newUser); + } + for (int j = 0; j < joinUserCnt; j++) { + TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId(testName + j).get(), + tournament, true, LocalDateTime.now()); + } + for (int j = joinUserCnt; j < joinUserCnt + notJoinUserCnt; j++) { + TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId(testName + j).get(), + tournament, false, LocalDateTime.now()); + } + return tournamentRepository.save(tournament); + } + + public TournamentGame createTournamentGame(Tournament tournament, TournamentRound round, GameInfoDto + gameInfoDto) { + TournamentGame tournamentGame = new TournamentGame( + gameRepository.findById(gameInfoDto.getGameId()).orElseThrow(GameNotExistException::new), tournament, + round); + tournamentGameRepository.save(tournamentGame); + return tournamentGame; + } + + /** + * ํ‹ฐ์–ด ์ƒ์„ฑ + */ + public Tier createTier(String url) { + Tier tier = new Tier(url); + tierRepository.save(tier); + return tier; + } + + /** + * ํ˜„์žฌ ์‹œ์Šคํ…œ์— ๋งž๋Š” ํ‹ฐ์–ด 7๊ฐœ๋ฅผ ์ƒ์„ฑ + */ + public ArrayList createTierSystem(String url) { + ArrayList tiers = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + Tier tier = new Tier(url + i); + tierRepository.save(tier); + tiers.add(tier); + } + return tiers; + } + + public GameInfoDto createGameWithTierAndRank(User curUser, LocalDateTime startTime, LocalDateTime endTime, + Season season, Mode mode, Tier tier) { + LocalDateTime now = LocalDateTime.now(); + Game game; + if (now.isBefore(startTime)) { + game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); + } else if (now.isAfter(startTime) && now.isBefore(endTime)) { + game = new Game(season, StatusType.LIVE, mode, startTime, endTime); + } else { + game = new Game(season, StatusType.END, mode, startTime, endTime); + } + gameRepository.save(game); + + User enemyUser = createNewUser(); + Team myTeam = new Team(game, -1, false); + Team enemyTeam = new Team(game, -1, false); + TeamUser teamUser = new TeamUser(myTeam, curUser); + TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); + createUserRank(curUser, "statusMessage", season, tier); + createUserRank(enemyUser, "enemyUserMeassage", season, tier); + teamRepository.save(myTeam); + teamRepository.save(enemyTeam); + teamUserRepository.save(teamUser); + teamUserRepository.save(enemyTeamUser); + + return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), + enemyUser.getId()); + } + + public CoinPolicy createCoinPolicy(User user, int attendance, int normal, int rankWin, int rankLose) { + CoinPolicy coinPolicy = CoinPolicy.builder() + .user(user) + .attendance(attendance) + .normal(normal) + .rankWin(rankWin) + .rankLose(rankLose) + .build(); + coinPolicyRepository.save(coinPolicy); + return coinPolicy; + } + + public Announcement createAnnouncement(User creator, String content) { + Announcement announcement = Announcement.builder() + .creatorIntraId(creator.getIntraId()) + .content(content) + .build(); + announcementRepository.save(announcement); + return announcement; + } + + /** + * ๊ณต์ง€์‚ฌํ•ญ ์—ฌ๋Ÿฌ๊ฐœ ์ƒ์„ฑ. + * ๊ฐ€์žฅ ์ตœ์‹  ์ด์™ธ๋Š” ๊ฐฑ์‹ ์ฒ˜๋ฆฌ. + * + * @param creator + * @param cnt + * @return ์ƒ์„ฑ๋œ ๊ณต์ง€์‚ฌํ•ญ ๋ฆฌ์ŠคํŠธ + */ + public ArrayList createAnnouncements(User creator, int cnt) { + return IntStream.range(0, cnt) + .mapToObj(i -> { + Announcement announcement = createAnnouncement(creator, "content" + i); + if (i != cnt - 1) { + announcement.update(creator.getIntraId(), LocalDateTime.now()); + } + return announcement; + }) + .collect(Collectors.toCollection(ArrayList::new)); + } + + public UserImage createUserImage(User user) { + UserImage userImage = new UserImage(user, "testUrl", + LocalDateTime.now(), null, true); + userImageRepository.save(userImage); + return userImage; + } + + public ArrayList createUserImages(User user, int cnt) { + return IntStream.range(0, cnt) + .mapToObj(i -> { + UserImage userImage = createUserImage(user); + if (i != cnt - 1) { + userImage.updateDeletedAt(LocalDateTime.now()); + } + return userImage; + }) + .collect(Collectors.toCollection(ArrayList::new)); + } + + public List createUsers(int cnt) { + List users = new ArrayList<>(); + for (int i = 0; i < cnt; i++) { + users.add( + createNewUser("testUser" + i, "testUser" + i + "@gmail.com", RacketType.PENHOLDER, SnsType.NONE, + RoleType.USER)); + } + userRepository.saveAll(users); + return users; + } + + public SlotManagement createSlotManagement(Integer interval) { + SlotManagement slotManagement = SlotManagement.builder() + .futureSlotTime(12) + .pastSlotTime(5) + .gameInterval(interval) + .openMinute(5) + .startTime(LocalDateTime.now().minusHours(2)) + .build(); + slotManagementRepository.save(slotManagement); + return slotManagement; + } + + public SlotManagement createSlot(int gameInterval) { + SlotManagement slotManagement = SlotManagement.builder() + .pastSlotTime(0) + .futureSlotTime(0) + .openMinute(0) + .gameInterval(gameInterval) + .startTime(LocalDateTime.now().minusHours(1)) + .build(); + return slotManagementRepository.save(slotManagement); + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/annotation/DataJpaUnitTest.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/DataJpaUnitTest.java new file mode 100644 index 000000000..471db80b7 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/DataJpaUnitTest.java @@ -0,0 +1,21 @@ +package gg.utils.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Tag; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +/** + * DataJpa ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜ + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Tag(TestTypeConstant.UNIT_TEST) +@DataJpaTest +public @interface DataJpaUnitTest { + +} diff --git a/src/test/java/com/gg/server/utils/annotation/IntegrationTest.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTest.java similarity index 80% rename from src/test/java/com/gg/server/utils/annotation/IntegrationTest.java rename to gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTest.java index b21fdaddd..51f868fd6 100644 --- a/src/test/java/com/gg/server/utils/annotation/IntegrationTest.java +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTest.java @@ -1,17 +1,19 @@ -package com.gg.server.utils.annotation; +package gg.utils.annotation; -import com.gg.server.utils.config.MySQLInitializer; -import com.gg.server.utils.config.RedisInitializer; -import com.gg.server.utils.config.TestRedisConfig; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + import org.junit.jupiter.api.Tag; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.ContextConfiguration; +import gg.utils.config.MySQLInitializer; +import gg.utils.config.RedisInitializer; +import gg.utils.config.TestRedisConfig; + /** * ํ†ตํ•ฉํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์˜ ์˜์กด์„ฑ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜. * @@ -27,4 +29,4 @@ @Tag(TestTypeConstant.INTEGRATION_TEST) public @interface IntegrationTest { -} \ No newline at end of file +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestAspect.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestAspect.java new file mode 100644 index 000000000..65a5caab1 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestAspect.java @@ -0,0 +1,25 @@ +package gg.utils.annotation; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import gg.repo.rank.redis.RankRedisRepository; + +@Aspect +@Component +public class IntegrationTestAspect { + + @Autowired + private RankRedisRepository rankRedisRepository; + + /** + * ํ†ตํ•ฉํ…Œ์ŠคํŠธ ์ข…๋ฃŒ ํ›„ redis ๋ฐ์ดํ„ฐ ์‚ญ์ œ + */ + @After("execution(* *(..)) && @within(integrationTest)") + public void afterTest(JoinPoint joinPoint, IntegrationTest integrationTest) { + rankRedisRepository.deleteAll(); + } +} diff --git a/src/test/java/com/gg/server/utils/annotation/IntegrationTestWithRedisTransaction.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestWithRedisTransaction.java similarity index 84% rename from src/test/java/com/gg/server/utils/annotation/IntegrationTestWithRedisTransaction.java rename to gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestWithRedisTransaction.java index 5a2a0b5f9..3d78f7aab 100644 --- a/src/test/java/com/gg/server/utils/annotation/IntegrationTestWithRedisTransaction.java +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/IntegrationTestWithRedisTransaction.java @@ -1,15 +1,17 @@ -package com.gg.server.utils.annotation; +package gg.utils.annotation; -import com.gg.server.utils.config.MySQLInitializer; -import com.gg.server.utils.config.RedisInitializer; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + import org.junit.jupiter.api.Tag; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; +import gg.utils.config.MySQLInitializer; +import gg.utils.config.RedisInitializer; + /** * ํ†ตํ•ฉํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์˜ ์˜์กด์„ฑ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜. * @@ -25,4 +27,4 @@ @Tag(TestTypeConstant.INTEGRATION_TEST) public @interface IntegrationTestWithRedisTransaction { -} \ No newline at end of file +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/annotation/TestTypeConstant.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/TestTypeConstant.java new file mode 100644 index 000000000..ef86dd294 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/TestTypeConstant.java @@ -0,0 +1,18 @@ +package gg.utils.annotation; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * TestType. + * + *

+ * Tag ์—์„œ ์‚ฌ์šฉํ•  ํ…Œ์ŠคํŠธ ํƒ€์ž…์„ ์ •์˜ + *

+ * + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class TestTypeConstant { + public static final String UNIT_TEST = "UnitTest"; + public static final String INTEGRATION_TEST = "IntegrationTest"; +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/annotation/UnitTest.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/UnitTest.java new file mode 100644 index 000000000..25a9c5950 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/UnitTest.java @@ -0,0 +1,22 @@ +package gg.utils.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +/** + * Unit ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜ + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Tag(TestTypeConstant.UNIT_TEST) +@ExtendWith(MockitoExtension.class) +public @interface UnitTest { + +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/annotation/WebMvcUnitTest.java b/gg-utils/src/testFixtures/java/gg/utils/annotation/WebMvcUnitTest.java new file mode 100644 index 000000000..6b4e4f656 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/annotation/WebMvcUnitTest.java @@ -0,0 +1,21 @@ +package gg.utils.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Tag; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + +/** + * WebMvc ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜ + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Tag(TestTypeConstant.UNIT_TEST) +@WebMvcTest +public @interface WebMvcUnitTest { + +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/config/MySQLInitializer.java b/gg-utils/src/testFixtures/java/gg/utils/config/MySQLInitializer.java new file mode 100644 index 000000000..73ab9cf48 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/config/MySQLInitializer.java @@ -0,0 +1,39 @@ +package gg.utils.config; + +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.containers.MySQLContainer; + +/** + * MysqlInitializer. + * + *

+ * mysql testContainer ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ + *

+ * + * @author : middlefitting + * @since : 2024/01/09 + */ +public class MySQLInitializer implements + ApplicationContextInitializer { + private static final String params = "?serverTimezone=Asia/Seoul&characterEncoding=UTF-8"; + private static final MySQLContainer MYSQL_CONTAINER = + new MySQLContainer<>("mysql:8.0") + .withDatabaseName("test") + .withUsername("root") + .withPassword("1234"); + + static { + MYSQL_CONTAINER.start(); + } + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + TestPropertyValues.of( + "spring.datasource.url=" + MYSQL_CONTAINER.getJdbcUrl() + params, + "spring.datasource.username=" + MYSQL_CONTAINER.getUsername(), + "spring.datasource.password=" + MYSQL_CONTAINER.getPassword() + ).applyTo(applicationContext.getEnvironment()); + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/config/RedisInitializer.java b/gg-utils/src/testFixtures/java/gg/utils/config/RedisInitializer.java new file mode 100644 index 000000000..eaba9f188 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/config/RedisInitializer.java @@ -0,0 +1,27 @@ +package gg.utils.config; + +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.utility.DockerImageName; + +import com.redis.testcontainers.RedisContainer; + +public class RedisInitializer implements + ApplicationContextInitializer { + private static final RedisContainer REDIS_CONTAINER = + new RedisContainer(DockerImageName.parse("redis:5.0.3-alpine")) + .withExposedPorts(6379); + + static { + REDIS_CONTAINER.start(); + } + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + TestPropertyValues.of( + "spring.redis.host=" + REDIS_CONTAINER.getHost(), + "spring.redis.port=" + REDIS_CONTAINER.getMappedPort(6379) + ).applyTo(applicationContext.getEnvironment()); + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/config/TestRedisConfig.java b/gg-utils/src/testFixtures/java/gg/utils/config/TestRedisConfig.java new file mode 100644 index 000000000..fe0e85db7 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/config/TestRedisConfig.java @@ -0,0 +1,37 @@ +package gg.utils.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * TestRedisConfig. + * + *

+ * ํ…Œ์ŠคํŠธ์—์„œ redis Transaction์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ ์„ค์ • + * ํ•ด๋‹น ๋นˆ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ฐ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค redis ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™” ํ•„์š” + *

+ */ +@TestConfiguration +public class TestRedisConfig { + + @Primary + @Bean(name = "testRedisTemplate") + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + final RedisTemplate redisTemplate = new RedisTemplate<>(); + + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + + redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setEnableTransactionSupport(false); + + return redisTemplate; + } +} diff --git a/gg-utils/src/testFixtures/java/gg/utils/dto/GameInfoDto.java b/gg-utils/src/testFixtures/java/gg/utils/dto/GameInfoDto.java new file mode 100644 index 000000000..be50aa211 --- /dev/null +++ b/gg-utils/src/testFixtures/java/gg/utils/dto/GameInfoDto.java @@ -0,0 +1,14 @@ +package gg.utils.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class GameInfoDto { + private Long gameId; + private Long myTeamId; + private Long myUserId; + private Long enemyTeamId; + private Long enemyUserId; +} diff --git a/gradlew.bat b/gradlew.bat index 53a6b238d..f127cfd49 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,91 +1,91 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/naver-checkstyle-rules.xml b/naver-checkstyle-rules.xml new file mode 100644 index 000000000..a6e5eb3cf --- /dev/null +++ b/naver-checkstyle-rules.xml @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/naver-checkstyle-suppressions.xml b/naver-checkstyle-suppressions.xml new file mode 100644 index 000000000..3f11e0cd3 --- /dev/null +++ b/naver-checkstyle-suppressions.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/naver-intellij-formatter.xml b/naver-intellij-formatter.xml new file mode 100644 index 000000000..658fc659f --- /dev/null +++ b/naver-intellij-formatter.xml @@ -0,0 +1,62 @@ + + + diff --git a/settings.gradle b/settings.gradle index 096502d21..ae330bfed 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,7 @@ rootProject.name = 'server' +include 'gg-data' +include 'gg-admin-repo' +include 'gg-repo' +include 'gg-pingpong-api' +include 'gg-utils' + diff --git a/src/main/java/com/gg/server/Application.java b/src/main/java/com/gg/server/Application.java deleted file mode 100644 index d09e439f3..000000000 --- a/src/main/java/com/gg/server/Application.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} diff --git a/src/main/java/com/gg/server/admin/announcement/controller/AnnouncementAdminController.java b/src/main/java/com/gg/server/admin/announcement/controller/AnnouncementAdminController.java deleted file mode 100644 index c8e6c4006..000000000 --- a/src/main/java/com/gg/server/admin/announcement/controller/AnnouncementAdminController.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gg.server.admin.announcement.controller; - -import com.gg.server.admin.announcement.dto.AnnouncementAdminAddDto; -import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; -import com.gg.server.admin.announcement.service.AnnouncementAdminService; -import com.gg.server.global.dto.PageRequestDto; -import lombok.AllArgsConstructor; - -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -@RestController -@AllArgsConstructor -@RequestMapping("pingpong/admin") -@Validated -public class AnnouncementAdminController { - private final AnnouncementAdminService announcementAdminService; - - @GetMapping("/announcement") - public ResponseEntity getAnnouncementList( - @ModelAttribute @Valid PageRequestDto anReq) { - - Pageable pageable = PageRequest.of(anReq.getPage() - 1, anReq.getSize(), Sort.by("createdAt").descending()); - - return ResponseEntity.ok() - .body(announcementAdminService.findAllAnnouncement(pageable)); - } - - @PostMapping("/announcement") - public ResponseEntity addaAnnouncement(@Valid @RequestBody AnnouncementAdminAddDto addDto){ - announcementAdminService.addAnnouncement(addDto); - - return new ResponseEntity(HttpStatus.CREATED); - } - - - @DeleteMapping("/announcement/{deleterIntraId}") - public ResponseEntity announcementModify(@PathVariable String deleterIntraId) { - announcementAdminService.modifyAnnouncementIsDel(deleterIntraId); - - return new ResponseEntity(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/admin/announcement/data/AnnouncementAdminRepository.java b/src/main/java/com/gg/server/admin/announcement/data/AnnouncementAdminRepository.java deleted file mode 100644 index d85cac043..000000000 --- a/src/main/java/com/gg/server/admin/announcement/data/AnnouncementAdminRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.admin.announcement.data; - -import com.gg.server.domain.announcement.data.Announcement; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface AnnouncementAdminRepository extends JpaRepository { - - Optional findFirstByOrderByIdDesc(); -} diff --git a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminAddDto.java b/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminAddDto.java deleted file mode 100644 index 368d619b5..000000000 --- a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminAddDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.admin.announcement.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class AnnouncementAdminAddDto { - @NotNull(message = "plz. content") - private String content; - @NotNull(message = "plz. creatorIntraId") - private String creatorIntraId; -} diff --git a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminListResponseDto.java b/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminListResponseDto.java deleted file mode 100644 index f851a2716..000000000 --- a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminListResponseDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.announcement.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class AnnouncementAdminListResponseDto { - private List announcementList; - private int totalPage; -} diff --git a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminResponseDto.java b/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminResponseDto.java deleted file mode 100644 index c236dfa83..000000000 --- a/src/main/java/com/gg/server/admin/announcement/dto/AnnouncementAdminResponseDto.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.admin.announcement.dto; - -import com.gg.server.domain.announcement.data.Announcement; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -public class AnnouncementAdminResponseDto { - private String creatorIntraId; - private String deleterIntraId; - private String content; - private LocalDateTime createdAt; - private LocalDateTime modifiedAt; - private LocalDateTime deletedAt; - - public AnnouncementAdminResponseDto(Announcement announcementAdmin) - { - this.content = announcementAdmin.getContent(); - this.creatorIntraId = announcementAdmin.getCreatorIntraId(); - this.deleterIntraId = announcementAdmin.getDeleterIntraId(); - this.createdAt = announcementAdmin.getCreatedAt(); - this.modifiedAt = announcementAdmin.getModifiedAt(); - this.deletedAt = announcementAdmin.getDeletedAt(); - } -} diff --git a/src/main/java/com/gg/server/admin/announcement/service/AnnouncementAdminService.java b/src/main/java/com/gg/server/admin/announcement/service/AnnouncementAdminService.java deleted file mode 100644 index f6f4da05a..000000000 --- a/src/main/java/com/gg/server/admin/announcement/service/AnnouncementAdminService.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.gg.server.admin.announcement.service; - -import com.gg.server.admin.announcement.data.AnnouncementAdminRepository; -import com.gg.server.admin.announcement.dto.AnnouncementAdminAddDto; -import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; -import com.gg.server.admin.announcement.dto.AnnouncementAdminResponseDto; -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.announcement.exception.AnnounceDupException; -import com.gg.server.domain.announcement.exception.AnnounceNotFoundException; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@AllArgsConstructor -public class AnnouncementAdminService { - private final AnnouncementAdminRepository announcementAdminRepository; - - @Transactional(readOnly = true) - public AnnouncementAdminListResponseDto findAllAnnouncement(Pageable pageable) { - Page allAnnouncements = announcementAdminRepository.findAll(pageable); - Page responseDtos = allAnnouncements.map(AnnouncementAdminResponseDto::new); - - return new AnnouncementAdminListResponseDto(responseDtos.getContent(), - responseDtos.getTotalPages()); - } - - @Transactional - public void addAnnouncement(AnnouncementAdminAddDto addDto){ - if (findAnnouncementExist() == true) - throw new AnnounceDupException(); - - Announcement announcementAdmin = Announcement.from(addDto); - - announcementAdminRepository.save(announcementAdmin); - } - - @Transactional - public void modifyAnnouncementIsDel(String deleterIntraId) { - if (findAnnouncementExist() == false) - throw new AnnounceNotFoundException(); - - Announcement announcement = announcementAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new AnnounceNotFoundException()); - announcement.update(deleterIntraId, LocalDateTime.now()); - } - - private Boolean findAnnouncementExist() { - Announcement announcement = announcementAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new AnnounceNotFoundException()); - - if (announcement.getDeletedAt() == null) - return true; - - return false; - } - -} diff --git a/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java b/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java deleted file mode 100644 index 581766615..000000000 --- a/src/main/java/com/gg/server/admin/coin/controller/CoinAdminController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gg.server.admin.coin.controller; - -import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; -import com.gg.server.admin.coin.service.CoinAdminService; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequiredArgsConstructor -@RequestMapping("pingpong/admin/coin") -public class CoinAdminController { - private final CoinAdminService coinAdminService; - - @PutMapping() - public ResponseEntity updateUserCoin(@RequestBody CoinUpdateRequestDto coinUpdateRequestDto) { - coinAdminService.updateUserCoin(coinUpdateRequestDto); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java b/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java deleted file mode 100644 index b67d1537a..000000000 --- a/src/main/java/com/gg/server/admin/coin/controller/CoinPolicyAdminController.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.admin.coin.controller; - -import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; -import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; -import com.gg.server.admin.coin.service.CoinPolicyAdminService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.AllArgsConstructor; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("pingpong/admin") -@Validated -public class CoinPolicyAdminController { - private final CoinPolicyAdminService coinPolicyAdminService; - - @GetMapping("/coinpolicy") - public ResponseEntity getCoinPolicyList(@ModelAttribute @Valid PageRequestDto coReq){ - Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); - - return ResponseEntity.ok() - .body(coinPolicyAdminService.findAllCoinPolicy(pageable)); - } - - @PostMapping("/coinpolicy") - public ResponseEntity addCoinPolicy(@Parameter(hidden = true) @Login UserDto userDto, @Valid @RequestBody CoinPolicyAdminAddDto addDto){ - - coinPolicyAdminService.addCoinPolicy(userDto, addDto); - return new ResponseEntity(HttpStatus.CREATED); - } - -} diff --git a/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java b/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java deleted file mode 100644 index 87e8f5412..000000000 --- a/src/main/java/com/gg/server/admin/coin/data/CoinPolicyAdminRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.coin.data; - -import com.gg.server.domain.coin.data.CoinPolicy; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface CoinPolicyAdminRepository extends JpaRepository { - Optional findFirstByOrderByIdDesc(); -} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java deleted file mode 100644 index 1420c2ea3..000000000 --- a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminAddDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.admin.coin.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class CoinPolicyAdminAddDto { - @NotNull(message = "plz. not null attendance") - @PositiveOrZero(message = "plz. attendance PositiveOrZero") - private int attendance; - - @NotNull(message = "plz. not null normal") - @PositiveOrZero(message = "plz. normal PositiveOrZero") - private int normal; - - @NotNull(message = "plz. not null rankWin") - @PositiveOrZero(message = "plz. rankWin PositiveOrZero") - private int rankWin; - - @NotNull(message = "plz. not null rankLose") - @PositiveOrZero(message = "plz. rankLose PositiveOrZero") - private int rankLose; -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java deleted file mode 100644 index b5014b54e..000000000 --- a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminListResponseDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.coin.dto; - -import com.gg.server.admin.announcement.dto.AnnouncementAdminResponseDto; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class CoinPolicyAdminListResponseDto { - private List coinPolicyList; - private int totalPage; -} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java deleted file mode 100644 index 08110e751..000000000 --- a/src/main/java/com/gg/server/admin/coin/dto/CoinPolicyAdminResponseDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gg.server.admin.coin.dto; - -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.coin.data.CoinPolicy; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -public class CoinPolicyAdminResponseDto { - private Long coinPolicyId; - private String createUserId; - private int attendance; - private int normal; - private int rankWin; - private int rankLose; - private LocalDateTime createdAt; - - public CoinPolicyAdminResponseDto(CoinPolicy coinPolicyAdmin) - { - this.coinPolicyId = coinPolicyAdmin.getId(); - this.createUserId = coinPolicyAdmin.getUser().getIntraId(); - this.attendance = coinPolicyAdmin.getAttendance(); - this.normal = coinPolicyAdmin.getNormal(); - this.rankWin = coinPolicyAdmin.getRankWin(); - this.rankLose = coinPolicyAdmin.getRankLose(); - this.createdAt = coinPolicyAdmin.getCreatedAt(); - } -} diff --git a/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java b/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java deleted file mode 100644 index 85349c464..000000000 --- a/src/main/java/com/gg/server/admin/coin/dto/CoinUpdateRequestDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.admin.coin.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class CoinUpdateRequestDto { - @NotNull(message = "intraId๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private String intraId; - @NotNull(message = "change๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private int change; - @NotNull(message = "content๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private String content; -} diff --git a/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java b/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java deleted file mode 100644 index 2c2237f26..000000000 --- a/src/main/java/com/gg/server/admin/coin/service/CoinAdminService.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.admin.coin.service; - -import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; -import com.gg.server.domain.coin.data.CoinHistory; -import com.gg.server.domain.coin.service.CoinHistoryService; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class CoinAdminService { - private final UserRepository userRepository; - private final CoinHistoryService coinHistoryService; - - @Transactional - public void updateUserCoin(CoinUpdateRequestDto coinUpdateRequestDto) { - User user = userRepository.findByIntraId(coinUpdateRequestDto.getIntraId()).orElseThrow(UserNotFoundException::new); - user.addGgCoin(coinUpdateRequestDto.getChange()); - coinHistoryService.addCoinHistory(new CoinHistory(user, coinUpdateRequestDto.getContent(), coinUpdateRequestDto.getChange())); - } -} diff --git a/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java b/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java deleted file mode 100644 index 8311b72e7..000000000 --- a/src/main/java/com/gg/server/admin/coin/service/CoinPolicyAdminService.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gg.server.admin.coin.service; - -import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; -import com.gg.server.admin.announcement.dto.AnnouncementAdminResponseDto; -import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; -import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; -import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; -import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.coin.data.CoinPolicy; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@AllArgsConstructor -public class CoinPolicyAdminService { - private final CoinPolicyAdminRepository coinPolicyAdminRepository; - private final UserAdminRepository userAdminRepository; - - @Transactional(readOnly = true) - public CoinPolicyAdminListResponseDto findAllCoinPolicy(Pageable pageable) { - Page allCoinPolicy = coinPolicyAdminRepository.findAll(pageable); - Page responseDtos = allCoinPolicy.map(CoinPolicyAdminResponseDto::new); - - return new CoinPolicyAdminListResponseDto(responseDtos.getContent(), - responseDtos.getTotalPages()); - } - - @Transactional - public void addCoinPolicy(UserDto userDto, CoinPolicyAdminAddDto addDto){ - User user = userAdminRepository.findByIntraId(userDto.getIntraId()).orElseThrow(UserNotFoundException::new); - - CoinPolicy coinPolicy = CoinPolicy.from(user, addDto); - coinPolicyAdminRepository.save(coinPolicy); - } -} diff --git a/src/main/java/com/gg/server/admin/feedback/controller/FeedbackAdminController.java b/src/main/java/com/gg/server/admin/feedback/controller/FeedbackAdminController.java deleted file mode 100644 index acd10b0f2..000000000 --- a/src/main/java/com/gg/server/admin/feedback/controller/FeedbackAdminController.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gg.server.admin.feedback.controller; - -import com.gg.server.admin.feedback.dto.FeedbackAdminPageRequestDto; -import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; -import com.gg.server.admin.feedback.service.FeedbackAdminService; -import com.gg.server.global.dto.PageRequestDto; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -@RestController -@RequestMapping("pingpong/admin/feedback") -@RequiredArgsConstructor -@Validated -public class FeedbackAdminController { - private final FeedbackAdminService feedbackAdminService; - - @GetMapping - public FeedbackListAdminResponseDto feedbackAll(@ModelAttribute @Valid FeedbackAdminPageRequestDto req) { - - if (req.getIntraId() == null){ - Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), Sort.by("isSolved").and(Sort.by("createdAt"))); - return feedbackAdminService.findAllFeedback(pageable); - } - Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), Sort.by("intra_id").and(Sort.by("createdAt"))); - return feedbackAdminService.findByPartsOfIntraId(req.getIntraId(), pageable); - } - - @PatchMapping("/{feedbackId}") - public ResponseEntity feedbackIsSolvedToggle(@PathVariable @NotNull Long feedbackId){ - feedbackAdminService.toggleFeedbackIsSolvedByAdmin(feedbackId); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - -} diff --git a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepository.java b/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepository.java deleted file mode 100644 index 887fcb1fe..000000000 --- a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gg.server.admin.feedback.data; - -import com.gg.server.domain.feedback.data.Feedback; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface FeedbackAdminRepository extends JpaRepository, FeedbackAdminRepositorySearch { -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearch.java b/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearch.java deleted file mode 100644 index 1744f0cf6..000000000 --- a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearch.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.feedback.data; - -import com.gg.server.domain.feedback.data.Feedback; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.query.Param; - -public interface FeedbackAdminRepositorySearch { - Page findFeedbacksByUserIntraId(@Param("intraId") String intraId, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearchImpl.java b/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearchImpl.java deleted file mode 100644 index ea3e3c6c1..000000000 --- a/src/main/java/com/gg/server/admin/feedback/data/FeedbackAdminRepositorySearchImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.gg.server.admin.feedback.data; - -import com.gg.server.domain.feedback.data.Feedback; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - -import javax.persistence.EntityManager; -import java.util.List; - -@RequiredArgsConstructor -public class FeedbackAdminRepositorySearchImpl implements FeedbackAdminRepositorySearch{ - - private final EntityManager em; - - public Page findFeedbacksByUserIntraId(String intraId, Pageable pageable) { - long feedbackNum = countTotalFeedbacks(intraId, pageable); - String sql = "select f from Feedback f join fetch f.user where " + - "f.user.intraId like \'%" + intraId + "%\' order by f.user.intraId asc, f.createdAt asc"; - List feedbackList = em.createQuery(sql, Feedback.class) - .setFirstResult((int) pageable.getOffset()) - .setMaxResults(pageable.getPageSize()) - .getResultList(); - Page feedbackPage = new PageImpl<>(feedbackList, pageable, feedbackNum); - return feedbackPage; - } - - private long countTotalFeedbacks(String intraId, Pageable pageable){ - String sql = "select f from Feedback f join fetch f.user where " + - "f.user.intraId like \'%" + intraId + "%\'"; - List feedbackList = em.createQuery(sql, Feedback.class) - .getResultList(); - return feedbackList.size(); - } -} diff --git a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminPageRequestDto.java b/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminPageRequestDto.java deleted file mode 100644 index 217b99d3a..000000000 --- a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminPageRequestDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.feedback.dto; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; - -import javax.validation.constraints.NotNull; - -@Getter -public class FeedbackAdminPageRequestDto extends PageRequestDto { - String intraId; - - public FeedbackAdminPageRequestDto(String intraId, Integer page, Integer size) { - super(page, size); - this.intraId = intraId; - } -} diff --git a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminResponseDto.java b/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminResponseDto.java deleted file mode 100644 index 8c0f680b3..000000000 --- a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackAdminResponseDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.admin.feedback.dto; - -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.type.FeedbackType; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.sql.Date; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -public class FeedbackAdminResponseDto { - private Long id; - private String intraId; - private LocalDateTime createdAt; - private FeedbackType category; - private String content; - private Boolean isSolved; - - public FeedbackAdminResponseDto(Feedback feedback){ - this.id = feedback.getId(); - this.intraId = feedback.getUser().getIntraId(); - this.createdAt = feedback.getCreatedAt(); - this.category = feedback.getCategory(); - this.content = feedback.getContent(); - this.isSolved = feedback.getIsSolved(); - } -} diff --git a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackListAdminResponseDto.java b/src/main/java/com/gg/server/admin/feedback/dto/FeedbackListAdminResponseDto.java deleted file mode 100644 index d222e9a49..000000000 --- a/src/main/java/com/gg/server/admin/feedback/dto/FeedbackListAdminResponseDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.admin.feedback.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@NoArgsConstructor -@Getter -public class FeedbackListAdminResponseDto { - private List feedbackList; - private int totalPage; - - public FeedbackListAdminResponseDto(List newDtos, int totalPage){ - this.feedbackList = newDtos; - this.totalPage= totalPage; - } -} diff --git a/src/main/java/com/gg/server/admin/feedback/service/FeedbackAdminService.java b/src/main/java/com/gg/server/admin/feedback/service/FeedbackAdminService.java deleted file mode 100644 index ee272d076..000000000 --- a/src/main/java/com/gg/server/admin/feedback/service/FeedbackAdminService.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gg.server.admin.feedback.service; - -import com.gg.server.admin.feedback.data.FeedbackAdminRepository; -import com.gg.server.admin.feedback.dto.FeedbackAdminResponseDto; -import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.exception.FeedbackNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class FeedbackAdminService { - private final FeedbackAdminRepository feedbackAdminRepository; - - @Transactional(readOnly = true) - public FeedbackListAdminResponseDto findAllFeedback(Pageable pageable){ - Page feedbacks = feedbackAdminRepository.findAll(pageable); - Page feedbackAdminResponseDtos = feedbacks.map(FeedbackAdminResponseDto::new); - - FeedbackListAdminResponseDto responseDto = new FeedbackListAdminResponseDto(feedbackAdminResponseDtos.getContent(), - feedbackAdminResponseDtos.getTotalPages()); - return responseDto; - } - - @Transactional - public void toggleFeedbackIsSolvedByAdmin(Long feedbackId){ - Feedback feedback = feedbackAdminRepository.findById(feedbackId).orElseThrow(FeedbackNotFoundException::new); - if (feedback.getIsSolved()){ - feedback.setIsSolved(false); - }else { - feedback.setIsSolved(true); - } - } - - @Transactional(readOnly = true) - public FeedbackListAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { - Page feedbacks = feedbackAdminRepository.findFeedbacksByUserIntraId(intraId, pageable); - Page feedbackAdminResponseDtos = feedbacks.map(FeedbackAdminResponseDto::new); - FeedbackListAdminResponseDto responseDto = new FeedbackListAdminResponseDto(feedbackAdminResponseDtos.getContent(), - feedbackAdminResponseDtos.getTotalPages()); - return responseDto; - } -} diff --git a/src/main/java/com/gg/server/admin/game/controller/GameAdminController.java b/src/main/java/com/gg/server/admin/game/controller/GameAdminController.java deleted file mode 100644 index a2846779f..000000000 --- a/src/main/java/com/gg/server/admin/game/controller/GameAdminController.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.gg.server.admin.game.controller; - -import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; -import com.gg.server.admin.game.dto.GameUserLogAdminReqDto; -import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; -import com.gg.server.admin.game.service.GameAdminService; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import javax.validation.constraints.Positive; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/admin/games") -public class GameAdminController { - private final GameAdminService gameAdminService; - - @GetMapping - public GameLogListAdminResponseDto gameFindBySeasonId(@ModelAttribute @Valid PageRequestDto pageRequestDto) { - int page = pageRequestDto.getPage(); - int size = pageRequestDto.getSize(); - - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("startTime").descending()); - return gameAdminService.findAllGamesByAdmin(pageable); - } - - /** - * ํŠน์ • ์œ ์ €์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ API - * @param reqDto intraId page size - * @return GameLogListAdminResponseDto gameLogList totalPage - */ - @GetMapping("/users") - public GameLogListAdminResponseDto gameFindByIntraId(@ModelAttribute GameUserLogAdminReqDto reqDto) { - - Pageable pageable = PageRequest.of(reqDto.getPage() - 1, reqDto.getSize()); - return gameAdminService.findGamesByIntraId(reqDto.getIntraId(), pageable); - } - - /** - * ๋žญํ‚น ์ ์ˆ˜ ์ˆ˜์ • API - * @param reqDto team1Id team1Score team2Id team2Score - * @param gameId ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ id - * @return ResponseEntity - * @throws InvalidParameterException ์ ์ˆ˜๊ฐ€ 3์ ์„ ์ดˆ๊ณผํ•˜๊ฑฐ๋‚˜, ๋‘ ํŒ€์˜ ์ ์ˆ˜๊ฐ€ ๊ฐ™์„ ๊ฒฝ์šฐ - */ - @PutMapping("/{gameId}") - public ResponseEntity gameResultEdit(@Valid @RequestBody RankGamePPPModifyReqDto reqDto, - @PathVariable @Positive Long gameId) { - if (reqDto.getTeam1Score() + reqDto.getTeam2Score() > 3 || reqDto.getTeam1Score() == reqDto.getTeam2Score()) { - throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); - } - gameAdminService.rankResultEdit(reqDto, gameId); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/admin/game/data/GameAdminRepository.java b/src/main/java/com/gg/server/admin/game/data/GameAdminRepository.java deleted file mode 100644 index 4f5d0a2df..000000000 --- a/src/main/java/com/gg/server/admin/game/data/GameAdminRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.admin.game.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.season.data.Season; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - -public interface GameAdminRepository extends JpaRepository { - - Page findBySeason(Pageable pageable, Season season); - - Page findBySeasonAndModeIn(Pageable pageable, Season season, List modes); - - Page findAllByModeIn(Pageable pageable, List modes); - - @Query(value = "select t1.gameId, t1.startTime, t1.endTime, t1.status, t1.mode, " + - "t1.teamId t1TeamId, t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + - "t2.teamId t2TeamId, t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + - "from v_rank_game_detail t1, v_rank_game_detail t2 " + - "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsIn(@Param("games") List games); - @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.status = :status AND g.id = t.game.id" - + " AND t.id = tu.team.id AND tu.user.id = :userId") - Optional findByStatusTypeAndUserId(@Param("status") StatusType status, @Param("userId") Long userId); -} diff --git a/src/main/java/com/gg/server/admin/game/dto/GameLogAdminDto.java b/src/main/java/com/gg/server/admin/game/dto/GameLogAdminDto.java deleted file mode 100644 index 58d080092..000000000 --- a/src/main/java/com/gg/server/admin/game/dto/GameLogAdminDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.admin.game.dto; - -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.type.StatusType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.Duration; -import java.time.LocalDateTime; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class GameLogAdminDto { - private Long gameId; - private LocalDateTime startAt; - private String slotTime; - private String mode; - private StatusType status; - private GameTeamAdminDto team1; - private GameTeamAdminDto team2; - - public GameLogAdminDto(GameTeamUser game) { - this.gameId = game.getGameId(); - this.startAt = game.getStartTime(); - this.slotTime = game.getEndTime() == null ? null : - String.valueOf(Duration.between(game.getStartTime().toLocalTime(), game.getEndTime().toLocalTime()).toMinutes()); - this.mode = game.getMode().getCode(); - this.team1 = new GameTeamAdminDto(game.getT1IntraId(), game.getT1TeamId(), game.getT1Score(), game.getT1IsWin()); - this.team2 = new GameTeamAdminDto(game.getT2IntraId(), game.getT2TeamId(), game.getT2Score(), game.getT2IsWin()); - this.status = game.getStatus(); - } -} diff --git a/src/main/java/com/gg/server/admin/game/dto/GameLogListAdminResponseDto.java b/src/main/java/com/gg/server/admin/game/dto/GameLogListAdminResponseDto.java deleted file mode 100644 index ce3629ff6..000000000 --- a/src/main/java/com/gg/server/admin/game/dto/GameLogListAdminResponseDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.game.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class GameLogListAdminResponseDto { - private List gameLogList; - private int totalPage; - -} diff --git a/src/main/java/com/gg/server/admin/game/dto/GameTeamAdminDto.java b/src/main/java/com/gg/server/admin/game/dto/GameTeamAdminDto.java deleted file mode 100644 index 8a2376c1b..000000000 --- a/src/main/java/com/gg/server/admin/game/dto/GameTeamAdminDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.admin.game.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class GameTeamAdminDto { - private String intraId1; - @JsonInclude(JsonInclude.Include.NON_NULL) - private String intraId2; //๋ณต์‹์ผ ๊ฒฝ์šฐ์—๋งŒ ์žˆ์Œ - private Long teamId; - private Integer score; - @JsonInclude(JsonInclude.Include.NON_NULL) - private Boolean win; - - public GameTeamAdminDto(String intraId, Long teamId, Integer score, Boolean win) { - this.intraId1 = intraId; - this.teamId = teamId; - this.score = score; - this.win = win; - } -} diff --git a/src/main/java/com/gg/server/admin/game/dto/GameUserLogAdminReqDto.java b/src/main/java/com/gg/server/admin/game/dto/GameUserLogAdminReqDto.java deleted file mode 100644 index d040c00f9..000000000 --- a/src/main/java/com/gg/server/admin/game/dto/GameUserLogAdminReqDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.admin.game.dto; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; - -import javax.validation.constraints.NotNull; - -@Getter -public class GameUserLogAdminReqDto extends PageRequestDto { - @NotNull(message = "plz, intraId") - private String intraId; - - public GameUserLogAdminReqDto(String intraId, Integer page, Integer size){ - super(page,size); - this.intraId = intraId; - } -} diff --git a/src/main/java/com/gg/server/admin/game/dto/RankGamePPPModifyReqDto.java b/src/main/java/com/gg/server/admin/game/dto/RankGamePPPModifyReqDto.java deleted file mode 100644 index 26d607217..000000000 --- a/src/main/java/com/gg/server/admin/game/dto/RankGamePPPModifyReqDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gg.server.admin.game.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RankGamePPPModifyReqDto { - @NotNull(message = "Team1Id ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @Positive - private Long team1Id; - @NotNull(message = "Team1Score ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int team1Score; - @NotNull(message = "Team2Id ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @Positive - private Long team2Id; - @NotNull(message = "Team2Score ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int team2Score; -} diff --git a/src/main/java/com/gg/server/admin/game/exception/NotRecentlyGameException.java b/src/main/java/com/gg/server/admin/game/exception/NotRecentlyGameException.java deleted file mode 100644 index 2e8663ae5..000000000 --- a/src/main/java/com/gg/server/admin/game/exception/NotRecentlyGameException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; - -public class NotRecentlyGameException extends InvalidParameterException { - public NotRecentlyGameException() { - super(ErrorCode.GAME_NOT_RECENTLY.getMessage(), ErrorCode.GAME_NOT_RECENTLY); - } -} diff --git a/src/main/java/com/gg/server/admin/game/service/GameAdminService.java b/src/main/java/com/gg/server/admin/game/service/GameAdminService.java deleted file mode 100644 index 64d7cf47d..000000000 --- a/src/main/java/com/gg/server/admin/game/service/GameAdminService.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.gg.server.admin.game.service; - -import com.gg.server.admin.game.dto.GameLogAdminDto; -import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; -import com.gg.server.admin.game.data.GameAdminRepository; -import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; -import com.gg.server.admin.game.exception.NotRecentlyGameException; -import com.gg.server.admin.pchange.data.PChangeAdminRepository; -import com.gg.server.admin.pchange.exception.PChangeNotExistException; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.team.data.TeamUserAdminRepository; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; - -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Caching; -import org.springframework.data.domain.*; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class GameAdminService { - - private final GameAdminRepository gameAdminRepository; - private final SeasonAdminRepository seasonAdminRepository; - private final UserAdminRepository userAdminRepository; - private final PChangeRepository pChangeRepository; - private final PChangeAdminRepository pChangeAdminRepository; - private final RankRedisService rankRedisService; - private final TeamUserAdminRepository teamUserAdminRepository; - private final RedisMatchUserRepository redisMatchUserRepository; - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ œ์™ธํ•œ ์ผ๋ฐ˜, ๋žญํฌ ๊ฒŒ์ž„๋“ค์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

- * @param pageable - * @return - */ - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findAllGamesByAdmin(Pageable pageable) { - Page gamePage = gameAdminRepository.findAllByModeIn(pageable, List.of(Mode.NORMAL, Mode.RANK)); - return new GameLogListAdminResponseDto(getGameLogList(gamePage.getContent().stream().map(Game::getId).collect(Collectors.toList())), gamePage.getTotalPages()); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ œ์™ธํ•œ ํ•ด๋‹น ์‹œ์ฆŒ์˜ ์ผ๋ฐ˜, ๋žญํฌ ๊ฒŒ์ž„๋“ค์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

- * @param pageable - * @return - */ - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findGamesBySeasonId(Long seasonId, Pageable pageable){ - Season season = seasonAdminRepository.findById(seasonId).orElseThrow(SeasonNotFoundException::new); - Page games = gameAdminRepository.findBySeasonAndModeIn(pageable, season, List.of(Mode.NORMAL, Mode.RANK)); - return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); - } - - @Transactional(readOnly = true) - public List getGameLogList(List gameIdList){ - List teamViews = gameAdminRepository.findTeamsByGameIsIn(gameIdList); - return teamViews.stream().map(GameLogAdminDto::new).collect(Collectors.toList()); - } - - /** - * ํŠน์ • ์œ ์ €์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ (ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ œ์™ธ) - * @param intraId ์กฐํšŒํ•  ์œ ์ €์˜ intraId - * @param pageable page size - * @return GameLogListAdminResponseDto - * @throws UserNotFoundException intraId์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ €๊ฐ€ ์—†์„ ๊ฒฝ์šฐ - */ - @Transactional(readOnly = true) - public GameLogListAdminResponseDto findGamesByIntraId(String intraId, Pageable pageable){ - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - List pChangeList = pChangeRepository.findAllByUserIdGameModeIn(user.getId(), List.of(Mode.NORMAL, Mode.RANK)); - List gameList = new ArrayList<>(); - - for(PChange pChange : pChangeList) - gameList.add(pChange.getGame()); - - int start = (int)pageable.getOffset(); - int end = Math.min((start + pageable.getPageSize()), gameList.size()); - Page games = new PageImpl<>(gameList.subList(start, end), pageable, gameList.size()); - return new GameLogListAdminResponseDto(getGameLogList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.getTotalPages()); - } - - /** - * ๋žญํ‚น ์ ์ˆ˜ ์ˆ˜์ • - * @param reqDto team1Id team1Score team2Id team2Score - * @param gameId ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ id - * @throws GameNotExistException gameId์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์ž„์ด ์—†์„ ๊ฒฝ์šฐ - * @throws SeasonNotFoundException ๊ฒŒ์ž„์— ํ•ด๋‹นํ•˜๋Š” ์‹œ์ฆŒ์ด ์—†์„ ๊ฒฝ์šฐ - * @throws NotRecentlyGameException ๊ฒŒ์ž„์ด ๋‘๋ช… ๋‹ค ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„์ด ์•„๋‹ ๊ฒฝ์šฐ - */ - @Transactional - @Caching(evict = { - @CacheEvict(value = "rankGameListByIntra", allEntries = true), - @CacheEvict(value = "rankGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true), - @CacheEvict(value = "ranking", allEntries = true) - }) - public void rankResultEdit(RankGamePPPModifyReqDto reqDto, Long gameId) { - // ๊ฒŒ์ž„์ด ๋‘๋ช… ๋‹ค ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„์ธ์ง€ ํ™•์ธ (๊ทธ game์— ํ•ด๋‹นํ•˜๋Š” ํŒ€์ด ๋งž๋Š”์ง€ ํ™•์ธ) - List teamUsers = teamUserAdminRepository.findUsersByTeamIdIn(List.of(reqDto.getTeam1Id(), reqDto.getTeam2Id())); - Game game = gameAdminRepository.findById(gameId) - .orElseThrow(GameNotExistException::new); - Season season = seasonAdminRepository.findById(game.getSeason().getId()) - .orElseThrow(SeasonNotFoundException::new); - if (!isRecentlyGame(teamUsers, gameId) || EnrollSlots(teamUsers)) { - throw new NotRecentlyGameException(); - } - // pchange ๊ฐ€์ ธ์™€์„œ rank ppp ์ด์ „ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์ƒˆ ์ ์ˆ˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐ - for (TeamUser teamUser : - teamUsers) { - List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); - if (!pChanges.get(0).getGame().getId().equals(gameId)) { - throw new PChangeNotExistException(); - } - rollbackGameResult(reqDto, season, teamUser, pChanges); - teamUserAdminRepository.flush(); - pChangeAdminRepository.delete(pChanges.get(0)); - } - rankRedisService.updateRankRedis(teamUsers.get(0), teamUsers.get(1), game); - rankRedisService.updateAllTier(gameId); - } - - private void rollbackGameResult(RankGamePPPModifyReqDto reqDto, Season season, TeamUser teamUser, List pChanges) { - // pchange ppp๋„ update - // rankredis ์— ppp ๋‹ค์‹œ ๋ฐ˜์˜ - // rank zset ๋„ update - // ์ด์ „ ppp, exp ๋˜๋Œ๋ฆฌ๊ธฐ - // rank data ์— ์žˆ๋Š” ppp ๋˜๋Œ๋ฆฌ๊ธฐ - if (pChanges.size() == 1) { - rankRedisService.rollbackRank(teamUser, season.getStartPpp(), season.getId()); - teamUser.getUser().updateExp(0); - } else { - rankRedisService.rollbackRank(teamUser, pChanges.get(1).getPppResult(), season.getId()); - teamUser.getUser().updateExp(pChanges.get(1).getExp()); - } - if (teamUser.getTeam().getId().equals(reqDto.getTeam1Id())) { - teamUser.getTeam().updateScore(reqDto.getTeam1Score(), reqDto.getTeam1Score() > reqDto.getTeam2Score()); - } else if (teamUser.getTeam().getId().equals(reqDto.getTeam2Id())) { - teamUser.getTeam().updateScore(reqDto.getTeam2Score(), reqDto.getTeam2Score() > reqDto.getTeam1Score()); - } - } - - private Boolean isRecentlyGame(List teamUsers, Long gameId) { - for (TeamUser teamUser : teamUsers) { - List pChanges = pChangeAdminRepository.findByTeamUser(teamUser.getUser().getId()); - if (!pChanges.get(0).getGame().getId().equals(gameId)) - return false; - } - return true; - } - - private Boolean EnrollSlots(List teamUsers) { - for (TeamUser teamUser : teamUsers) { - Long userId = teamUser.getUser().getId(); - if (redisMatchUserRepository.countMatchTime(userId) > 0) { - return true; - } - if (gameAdminRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userId).isPresent()) { - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java b/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java deleted file mode 100644 index ab76b429e..000000000 --- a/src/main/java/com/gg/server/admin/item/controller/ItemAdminController.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.gg.server.admin.item.controller; - -import com.gg.server.admin.item.dto.ItemListResponseDto; -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.admin.item.service.ItemAdminService; -import com.gg.server.domain.item.exception.ItemImageLargeException; -import com.gg.server.domain.item.exception.ItemImageTypeException; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.validation.Valid; -import java.io.IOException; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/admin/items") -public class ItemAdminController { - private final ItemAdminService itemAdminService; - - @GetMapping("/history") - public ItemListResponseDto getItemHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), - Sort.by("createdAt").descending()); - return itemAdminService.getAllItemHistory(pageable); - } - - @PostMapping(path="/{itemId}", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}) - public ResponseEntity updateItem(@PathVariable("itemId") Long itemId, - @RequestPart @Valid ItemUpdateRequestDto updateItemInfo, - @RequestPart(required = false) MultipartFile imgData, - @Parameter(hidden = true) @Login UserDto user) throws IOException { - if (imgData != null) { - if (imgData.getSize() > 50000) { - throw new ItemImageLargeException(); - } else if (imgData.getContentType() == null || !imgData.getContentType().equals("image/jpeg")) { - throw new ItemImageTypeException(); - } - itemAdminService.updateItem(itemId, updateItemInfo, imgData, user); - } else { - itemAdminService.updateItem(itemId, updateItemInfo, user); - } - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - - @DeleteMapping("/{itemId}") - public ResponseEntity deleteItem(@PathVariable("itemId") Long itemId, @Parameter(hidden = true) @Login UserDto user) { - itemAdminService.deleteItem(itemId, user); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java b/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java deleted file mode 100644 index 7525bc053..000000000 --- a/src/main/java/com/gg/server/admin/item/data/ItemAdminRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.item.data; - -import com.gg.server.domain.item.data.Item; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ItemAdminRepository extends JpaRepository { - Page findAll(Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java deleted file mode 100644 index 5e8acf572..000000000 --- a/src/main/java/com/gg/server/admin/item/dto/ItemHistoryResponseDto.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gg.server.admin.item.dto; - -import com.gg.server.domain.item.data.Item; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ItemHistoryResponseDto { - private Long itemId; - private String name; - private String mainContent; - private String subContent; - private String imageUri; - private Integer price; - private Integer discount; - private boolean isVisible; - private LocalDateTime createdAt; - private String creatorIntraId; - private String deleterIntraId; - - public ItemHistoryResponseDto(Item item) { - this.itemId = item.getId(); - this.name = item.getName(); - this.mainContent = item.getMainContent(); - this.subContent = item.getSubContent(); - this.imageUri = item.getImageUri(); - this.price = item.getPrice(); - this.discount = item.getDiscount(); - this.isVisible = item.getIsVisible(); - this.createdAt = item.getCreatedAt(); - this.creatorIntraId = item.getCreatorIntraId(); - this.deleterIntraId = item.getDeleterIntraId(); - } - - @Override - public String toString() { - return "ItemHistoryResponseDto{" + - "itemId=" + itemId + - ", name='" + name + '\'' + - ", mainContent='" + mainContent + '\'' + - ", subContent='" + subContent + '\'' + - ", imageUri='" + imageUri + '\'' + - ", price=" + price + - ", discount=" + discount + - ", isVisible=" + isVisible + - ", createdAt=" + createdAt + - ", creatorIntraId='" + creatorIntraId + '\'' + - ", deleterIntraId='" + deleterIntraId + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java deleted file mode 100644 index c56e7f1a1..000000000 --- a/src/main/java/com/gg/server/admin/item/dto/ItemListResponseDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.item.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ItemListResponseDto { - private List historyList; - private Integer totalPage; -} diff --git a/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java b/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java deleted file mode 100644 index 4c454ebe7..000000000 --- a/src/main/java/com/gg/server/admin/item/dto/ItemUpdateRequestDto.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gg.server.admin.item.dto; - -import com.gg.server.domain.item.type.ItemType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ItemUpdateRequestDto { - @NotNull(message = "[Request] ์•„์ดํ…œ ์ด๋ฆ„์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private String name; - - @NotNull(message = "[Request] ์ฃผ ์„ค๋ช…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private String mainContent; - - @NotNull(message = "[Request] ๋ถ€ ์„ค๋ช…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private String subContent; - - @NotNull(message = "[Request] ๊ฐ€๊ฒฉ์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private Integer price; - - @NotNull(message = "[Request] ํ• ์ธ์œจ์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private Integer discount; - - @NotNull(message = "[Request] ์•„์ดํ…œ ํƒ€์ž…์€ Null ์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private ItemType itemType; - - @Override - public String toString() { - return "ItemUpdateRequestDto{" + - "name='" + name + '\'' + - ", mainContent='" + mainContent + '\'' + - ", subContent='" + subContent + '\'' + - ", price=" + price + - ", discount=" + discount + - ", itemType='" + itemType + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java b/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java deleted file mode 100644 index 1334c1909..000000000 --- a/src/main/java/com/gg/server/admin/item/exception/ItemNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class ItemNotFoundException extends NotExistException { - public ItemNotFoundException() { - super("์•„์ดํ…œ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.ITEM_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java b/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java deleted file mode 100644 index 7fb4a6f49..000000000 --- a/src/main/java/com/gg/server/admin/item/service/ItemAdminService.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gg.server.admin.item.service; - -import com.gg.server.admin.item.data.ItemAdminRepository; -import com.gg.server.admin.item.dto.ItemHistoryResponseDto; -import com.gg.server.admin.item.dto.ItemListResponseDto; -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.admin.item.exception.ItemNotFoundException; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.exception.ItemNotAvailableException; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.aws.AsyncNewItemImageUploader; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; - - -@Service -@RequiredArgsConstructor -public class ItemAdminService { - - private final ItemAdminRepository itemAdminRepository; - private final AsyncNewItemImageUploader asyncNewItemImageUploader; - - @Transactional(readOnly = true) - public ItemListResponseDto getAllItemHistory(Pageable pageable) { - Page responseDtos = itemAdminRepository.findAll(pageable).map(ItemHistoryResponseDto::new); - return new ItemListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - // ์•„์ดํ…œ ์ˆ˜์ • ์‹œ ์‹ ๊ทœ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ - @Transactional - public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, - MultipartFile itemImageFile, UserDto user) throws IOException { - Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); - if (!item.getIsVisible()) { - throw new ItemNotAvailableException(); - } - item.setVisibility(user.getIntraId()); - Item newItem = new Item(itemUpdateRequestDto, user.getIntraId(), null); - if (itemImageFile != null) - asyncNewItemImageUploader.upload(newItem, itemImageFile); - itemAdminRepository.save(newItem); - } - - // ์•„์ดํ…œ ์ˆ˜์ • ์‹œ ์‹ ๊ทœ ์ด๋ฏธ์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ - @Transactional - public void updateItem(Long itemId, ItemUpdateRequestDto itemUpdateRequestDto, - UserDto user) { - Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); - if (!item.getIsVisible()) { - throw new ItemNotAvailableException(); - } - item.setVisibility(user.getIntraId()); - Item newItem = new Item(itemUpdateRequestDto, user.getIntraId(), item.getImageUri()); - itemAdminRepository.save(newItem); - } - - @Transactional - public void deleteItem(Long itemId, UserDto user) { - Item item = itemAdminRepository.findById(itemId).orElseThrow(ItemNotFoundException::new); - item.setVisibility(user.getIntraId()); - } -} diff --git a/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java b/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java deleted file mode 100644 index 2986447f9..000000000 --- a/src/main/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.admin.megaphone.controller; - -import com.gg.server.admin.megaphone.dto.MegaphoneHistoryResponseDto; -import com.gg.server.admin.megaphone.service.MegaphoneAdminService; -import com.gg.server.global.dto.PageRequestDto; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/admin/megaphones") -public class MegaphoneAdminController { - private final MegaphoneAdminService megaphoneAdminService; - - @GetMapping("/history") - public MegaphoneHistoryResponseDto getMegaphoneHistory(@ModelAttribute @Valid PageRequestDto pageRequestDto, - @RequestParam(required = false) String intraId) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), - Sort.by("id").descending()); - if (intraId == null) - return megaphoneAdminService.getMegaphoneHistory(pageable); - return megaphoneAdminService.getMegaphoneHistoryByIntraId(intraId, pageable); - - } -} diff --git a/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java b/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java deleted file mode 100644 index 18e964254..000000000 --- a/src/main/java/com/gg/server/admin/megaphone/data/MegaphoneAdminRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.megaphone.data; - -import com.gg.server.domain.megaphone.data.Megaphone; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface MegaphoneAdminRepository extends JpaRepository { - Page findMegaphonesByUserIntraId(String intraId, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java deleted file mode 100644 index 9984a0351..000000000 --- a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneAdminResponseDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gg.server.admin.megaphone.dto; - -import com.gg.server.domain.megaphone.data.Megaphone; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class MegaphoneAdminResponseDto { - private Long megaphoneId; - private String content; - private String usedAt; - private String status; - private String intraId; - - public MegaphoneAdminResponseDto(Megaphone megaphone){ - this.megaphoneId = megaphone.getId(); - this.content = megaphone.getContent(); - this.usedAt = megaphone.getUsedAt().toString(); - this.status = megaphone.getReceipt().getStatus().getDescription(); - this.intraId = megaphone.getUser().getIntraId(); - } -} diff --git a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java b/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java deleted file mode 100644 index 9337d047e..000000000 --- a/src/main/java/com/gg/server/admin/megaphone/dto/MegaphoneHistoryResponseDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.admin.megaphone.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class MegaphoneHistoryResponseDto { - private List megaphoneList; - private int totalPage; - - public MegaphoneHistoryResponseDto(List newDtos, int totalPage){ - this.megaphoneList = newDtos; - this.totalPage= totalPage; - } -} diff --git a/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java b/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java deleted file mode 100644 index b91076db5..000000000 --- a/src/main/java/com/gg/server/admin/megaphone/service/MegaphoneAdminService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.admin.megaphone.service; - -import com.gg.server.admin.megaphone.data.MegaphoneAdminRepository; - -import com.gg.server.admin.megaphone.dto.MegaphoneAdminResponseDto; -import com.gg.server.admin.megaphone.dto.MegaphoneHistoryResponseDto; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - - -@Service -@RequiredArgsConstructor -public class MegaphoneAdminService { - private final MegaphoneAdminRepository megaphoneAdminRepository; - - public MegaphoneHistoryResponseDto getMegaphoneHistory(Pageable pageable) { - Page megaphoneHistory = megaphoneAdminRepository.findAll(pageable).map(MegaphoneAdminResponseDto::new); - return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); - } - - public MegaphoneHistoryResponseDto getMegaphoneHistoryByIntraId(String intraId, Pageable pageable) { - Page megaphoneHistory = megaphoneAdminRepository.findMegaphonesByUserIntraId(intraId, pageable).map(MegaphoneAdminResponseDto::new); - return new MegaphoneHistoryResponseDto(megaphoneHistory.getContent(), megaphoneHistory.getTotalPages()); - } -} diff --git a/src/main/java/com/gg/server/admin/noti/controller/NotiAdminController.java b/src/main/java/com/gg/server/admin/noti/controller/NotiAdminController.java deleted file mode 100644 index 5af681f7e..000000000 --- a/src/main/java/com/gg/server/admin/noti/controller/NotiAdminController.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.gg.server.admin.noti.controller; - - -import com.gg.server.admin.noti.dto.NotiListAdminRequestDto; -import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -@RestController -@AllArgsConstructor -@RequestMapping(value = "/pingpong/admin/notifications") -public class NotiAdminController { - - private final NotiAdminService notiAdminService; - - @GetMapping - public NotiListAdminResponseDto getAllNoti(@ModelAttribute NotiListAdminRequestDto requestDto) { - int page = requestDto.getPage(); - int size = requestDto.getSize(); - String intraId = requestDto.getIntraId(); - - Pageable pageable = PageRequest.of(page - 1, size, - Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending())); - if (intraId == null) - return notiAdminService.getAllNoti(pageable); - else - return notiAdminService.getFilteredNotifications(pageable, intraId); - } - @PostMapping - public ResponseEntity sendNotiToUser(@RequestBody SendNotiAdminRequestDto sendNotiAdminRequestDto) { - notiAdminService.sendAnnounceNotiToUser(sendNotiAdminRequestDto); - return new ResponseEntity(HttpStatus.CREATED); - } -} diff --git a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepository.java b/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepository.java deleted file mode 100644 index 0f8c3ffb7..000000000 --- a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.noti.data; - -import com.gg.server.domain.noti.data.Noti; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface NotiAdminRepository - extends JpaRepository, NotiAdminRepositoryCustom{ - - @Override - @EntityGraph(attributePaths = {"user"}) - Page findAll(Pageable pageable); - -} diff --git a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustom.java b/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustom.java deleted file mode 100644 index 4f9adfc18..000000000 --- a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustom.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.admin.noti.data; - -import com.gg.server.domain.noti.data.Noti; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.query.Param; - -public interface NotiAdminRepositoryCustom { - - Page findNotisByUserIntraId(Pageable pageable, @Param("intraId") String intraId); -} diff --git a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustomImpl.java b/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustomImpl.java deleted file mode 100644 index 306b85913..000000000 --- a/src/main/java/com/gg/server/admin/noti/data/NotiAdminRepositoryCustomImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.admin.noti.data; - -import com.gg.server.domain.noti.data.Noti; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - -import javax.persistence.EntityManager; -import java.util.List; - -@RequiredArgsConstructor -public class NotiAdminRepositoryCustomImpl implements NotiAdminRepositoryCustom { - private final EntityManager em; - @Override - public Page findNotisByUserIntraId(Pageable pageable, String intraId) { - long totalElem = countTotalElem(intraId); - String sql = "select n from Noti n join fetch n.user where " + - "n.user.intraId like \'%" + intraId + "%\' order by n.createdAt desc, n.user.intraId asc"; - List notis = em.createQuery(sql, Noti.class) - .setFirstResult((int) pageable.getOffset()) - .setMaxResults(pageable.getPageSize()) - .getResultList(); - Page result = new PageImpl<>(notis, pageable, totalElem); - return result; - } - - private long countTotalElem(String intraId) { - String sql = "select n from Noti n join fetch n.user where " + - "n.user.intraId like \'%" + intraId + "%\'"; - List notiList = em.createQuery(sql, Noti.class) - .getResultList(); - return notiList.size(); - } -} diff --git a/src/main/java/com/gg/server/admin/noti/dto/NotiAdminDto.java b/src/main/java/com/gg/server/admin/noti/dto/NotiAdminDto.java deleted file mode 100644 index 3d1aeaca2..000000000 --- a/src/main/java/com/gg/server/admin/noti/dto/NotiAdminDto.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.gg.server.admin.noti.dto; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.type.NotiType; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.time.LocalDateTime; -import java.util.Objects; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class NotiAdminDto { - private Long id; - private String intraId; - private NotiType type; - private Boolean isChecked; - private String message; - private LocalDateTime createdAt; - - public NotiAdminDto(Noti noti) - { - if (noti != null) { - this.id = noti.getId(); - this.intraId = noti.getUser().getIntraId(); - this.type = noti.getType(); - this.isChecked = noti.getIsChecked(); - this.message = noti.getMessage(); - this.createdAt = noti.getCreatedAt(); - } - } - - @Override - public String toString() { - return "NotiAdminDto{" + - "id=" + id + - ", user=" + intraId + - ", type=" + type + - ", isChecked=" + isChecked + - ", message='" + message + '\'' + - ", creatdDate=" + createdAt + - '}'; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof NotiAdminDto)) { - return false; - } - NotiAdminDto other = (NotiAdminDto) o; - return Objects.equals(id, other.id) - && Objects.equals(intraId, other.intraId) - && Objects.equals(type, other.type) - && Objects.equals(isChecked, other.isChecked) - && Objects.equals(message, other.message) - && Objects.equals(createdAt, other.createdAt); - } -} diff --git a/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminRequestDto.java b/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminRequestDto.java deleted file mode 100644 index 6a9e334e6..000000000 --- a/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminRequestDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.noti.dto; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class NotiListAdminRequestDto extends PageRequestDto { - private String intraId; - - public NotiListAdminRequestDto(Integer page, Integer size, String intraId) { - super(page, size); - this.intraId = intraId; - } -} diff --git a/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminResponseDto.java b/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminResponseDto.java deleted file mode 100644 index ceaedd5c8..000000000 --- a/src/main/java/com/gg/server/admin/noti/dto/NotiListAdminResponseDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.admin.noti.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Objects; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class NotiListAdminResponseDto { - private List notiList; - @JsonInclude(JsonInclude.Include.NON_NULL) - private Integer totalPage; - @Override - public String toString() { - return "NotiListResponseDto{" + - "notifications=" + notiList + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NotiListAdminResponseDto other = (NotiListAdminResponseDto) o; - return Objects.equals(notiList, other.notiList); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/noti/dto/SendNotiAdminRequestDto.java b/src/main/java/com/gg/server/admin/noti/dto/SendNotiAdminRequestDto.java deleted file mode 100644 index 4d286d150..000000000 --- a/src/main/java/com/gg/server/admin/noti/dto/SendNotiAdminRequestDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.admin.noti.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; -import java.util.Objects; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SendNotiAdminRequestDto { - - @NotNull - private String intraId; - - @NotNull - @Size(max=255) - private String message; - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof SendNotiAdminRequestDto)) { - return false; - } - SendNotiAdminRequestDto other = (SendNotiAdminRequestDto) o; - return Objects.equals(message, other.message); - } -} diff --git a/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java b/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java deleted file mode 100644 index c5478e47a..000000000 --- a/src/main/java/com/gg/server/admin/noti/service/NotiAdminService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.admin.noti.service; - -import com.gg.server.admin.noti.data.NotiAdminRepository; -import com.gg.server.admin.noti.dto.NotiAdminDto; -import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.service.SnsNotiService; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@AllArgsConstructor -public class NotiAdminService { - private final NotiAdminRepository notiAdminRepository; - private final UserAdminRepository userAdminRepository; - private final SnsNotiService snsNotiService; - - @Transactional - public void sendAnnounceNotiToUser(SendNotiAdminRequestDto sendNotiAdminRequestDto) { - String message = sendNotiAdminRequestDto.getMessage(); - String intraId = sendNotiAdminRequestDto.getIntraId(); - - User user = userAdminRepository.findByIntraId(intraId) - .orElseThrow(UserNotFoundException::new); - Noti noti = notiAdminRepository.save(new Noti(user, NotiType.ANNOUNCE, message, false)); - snsNotiService.sendSnsNotification(noti, UserDto.from(user)); - } - - @Transactional(readOnly = true) - public NotiListAdminResponseDto getAllNoti(Pageable pageable) { - Page allNotiPage = notiAdminRepository.findAll(pageable); - Page notiAdminDtoPage = allNotiPage.map(NotiAdminDto::new); - return new NotiListAdminResponseDto(notiAdminDtoPage.getContent(), notiAdminDtoPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public NotiListAdminResponseDto getFilteredNotifications(Pageable pageable, String intraId) { - Page findNotis = notiAdminRepository.findNotisByUserIntraId(pageable, intraId); - Page notiResponseDtoPage = findNotis.map(NotiAdminDto::new); - return new NotiListAdminResponseDto(notiResponseDtoPage.getContent(), notiResponseDtoPage.getTotalPages()); - } -} diff --git a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepository.java b/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepository.java deleted file mode 100644 index 4e8b3c3b1..000000000 --- a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gg.server.admin.pchange.data; - -import com.gg.server.domain.pchange.data.PChange; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PChangeAdminRepository extends JpaRepository, PChangeAdminRepositoryCustom { -} diff --git a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustom.java b/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustom.java deleted file mode 100644 index 215056b7d..000000000 --- a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustom.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.admin.pchange.data; - -import com.gg.server.domain.pchange.data.PChange; - -import java.util.List; - -public interface PChangeAdminRepositoryCustom { - List findByTeamUser(Long userId); -} diff --git a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustomImpl.java b/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustomImpl.java deleted file mode 100644 index 341b936ea..000000000 --- a/src/main/java/com/gg/server/admin/pchange/data/PChangeAdminRepositoryCustomImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.admin.pchange.data; - -import com.gg.server.domain.pchange.data.PChange; -import lombok.RequiredArgsConstructor; - -import javax.persistence.EntityManager; -import javax.persistence.LockModeType; -import java.util.List; - -@RequiredArgsConstructor -public class PChangeAdminRepositoryCustomImpl implements PChangeAdminRepositoryCustom { - private final EntityManager em; - @Override - public List findByTeamUser(Long userId) { - String query = "SELECT p FROM PChange p WHERE p.user.id = :userId ORDER BY p.createdAt desc"; - return em.createQuery(query, PChange.class) - .setParameter("userId", userId) - .setMaxResults(2) - .setLockMode(LockModeType.PESSIMISTIC_WRITE) - .getResultList(); - } -} diff --git a/src/main/java/com/gg/server/admin/pchange/exception/PChangeNotExistException.java b/src/main/java/com/gg/server/admin/pchange/exception/PChangeNotExistException.java deleted file mode 100644 index 0c89a5f8d..000000000 --- a/src/main/java/com/gg/server/admin/pchange/exception/PChangeNotExistException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.pchange.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class PChangeNotExistException extends NotExistException { - public PChangeNotExistException() { - super(ErrorCode.PCHANGE_NOT_FOUND.getMessage(), ErrorCode.PCHANGE_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/controller/PenaltyAdminController.java b/src/main/java/com/gg/server/admin/penalty/controller/PenaltyAdminController.java deleted file mode 100644 index d9ea1893b..000000000 --- a/src/main/java/com/gg/server/admin/penalty/controller/PenaltyAdminController.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gg.server.admin.penalty.controller; - -import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; -import com.gg.server.admin.penalty.dto.PenaltyRequestDto; -import com.gg.server.admin.penalty.service.PenaltyAdminService; -import com.gg.server.global.dto.PageRequestDto; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -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; - -@RestController -@RequiredArgsConstructor -@Validated -@RequestMapping("/pingpong/admin/") -public class PenaltyAdminController { - private final PenaltyAdminService penaltyAdminService; - - @PostMapping("penalty") - public ResponseEntity givePenaltyToUser(@RequestBody @Valid PenaltyRequestDto requestDto) { - penaltyAdminService.givePenalty(requestDto.getIntraId(), requestDto.getPenaltyTime(), requestDto.getReason()); - return ResponseEntity.status(HttpStatus.CREATED).build(); - } - - @GetMapping("penalty") - public PenaltyListResponseDto getAllPenaltyUser(@ModelAttribute @Valid PageRequestDto pageRequestDto, - @RequestParam(required = false) String intraId, @RequestParam Boolean current) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), - Sort.by("startTime").descending()); - if (intraId == null) - return penaltyAdminService.getAllPenalties(pageable, current); - return penaltyAdminService.getAllPenaltiesByIntraId(pageable, intraId, current); - } - - @DeleteMapping("penalty/{penaltyId}") - public ResponseEntity releasePenaltyUser(@PathVariable @Min(1) Long penaltyId) { - penaltyAdminService.deletePenalty(penaltyId); - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepository.java b/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepository.java deleted file mode 100644 index eac12e24b..000000000 --- a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.admin.penalty.data; - -import com.gg.server.domain.penalty.data.Penalty; -import java.time.LocalDateTime; -import java.util.List; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface PenaltyAdminRepository extends JpaRepository, PenaltyAdminRepositoryCustom{ - @EntityGraph(attributePaths = {"user"}) - Page findAll(Pageable pageable); - @Query("select p from Penalty p where p.user.id = :userId and p.startTime > :startTime") - List findAfterPenaltiesByUser(@Param("userId") Long userId, - @Param("startTime") LocalDateTime startTime); -} diff --git a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustom.java b/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustom.java deleted file mode 100644 index 86284955a..000000000 --- a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustom.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.penalty.data; - -import com.gg.server.domain.penalty.data.Penalty; -import java.time.LocalDateTime; -import java.util.List; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.query.Param; - -public interface PenaltyAdminRepositoryCustom { - Page findAllCurrent(Pageable pageable, LocalDateTime targetTime); - Page findAllByIntraId(Pageable pageable, String intraId); - Page findAllCurrentByIntraId(Pageable pageable, LocalDateTime targetTime, - String intraId); -} diff --git a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustomImpl.java b/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustomImpl.java deleted file mode 100644 index c449b03c5..000000000 --- a/src/main/java/com/gg/server/admin/penalty/data/PenaltyAdminRepositoryCustomImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.gg.server.admin.penalty.data; - -import com.gg.server.domain.penalty.data.Penalty; -import java.time.LocalDateTime; -import java.util.List; -import javax.persistence.EntityManager; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - -@RequiredArgsConstructor -public class PenaltyAdminRepositoryCustomImpl implements PenaltyAdminRepositoryCustom{ - private final EntityManager em; - - @Override - public Page findAllCurrent(Pageable pageable, LocalDateTime targetTime) { - String sql = "select p from Penalty p where TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " - + "order by p.startTime desc"; - long count = countCurrent(targetTime); - List penalties = em.createQuery(sql, Penalty.class) - .setParameter("targetTime", targetTime) - .setFirstResult((int) pageable.getOffset()) - .setMaxResults(pageable.getPageSize()) - .getResultList(); - Page result = new PageImpl<>(penalties, pageable, count); - return result; - } - - @Override - public Page findAllByIntraId(Pageable pageable, String intraId) { - String sql = "SELECT p FROM Penalty p JOIN FETCH p.user WHERE p.user.intraId LIKE :intraId ORDER BY p.startTime DESC"; - long count = countByIntraId(intraId); - List penalties = em.createQuery(sql, Penalty.class) - .setParameter("intraId", "%" + intraId + "%") - .setFirstResult((int) pageable.getOffset()) - .setMaxResults(pageable.getPageSize()) - .getResultList(); - Page result = new PageImpl<>(penalties, pageable, count); - return result; - } - - @Override - public Page findAllCurrentByIntraId(Pageable pageable, LocalDateTime targetTime, String intraId) { - String sql = "select p from Penalty p join fetch p.user where " + - "p.user.intraId like :intraId and TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " - + "order by p.startTime desc"; - long count = countCurrentByIntraId(intraId, targetTime); - List penalties = em.createQuery(sql, Penalty.class) - .setParameter("intraId", "%" + intraId + "%") - .setParameter("targetTime", targetTime) - .setFirstResult((int) pageable.getOffset()) - .setMaxResults(pageable.getPageSize()) - .getResultList(); - Page result = new PageImpl<>(penalties, pageable, count); - return result; - } - - private long countCurrent(LocalDateTime targetTime) { - String sql = "select p from Penalty p where TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " - + "order by p.startTime desc"; - return em.createQuery(sql, Penalty.class) - .setParameter("targetTime", targetTime) - .getResultList().size(); - } - - private long countByIntraId(String intraId) { - String sql = "select p FROM Penalty p join fetch p.user u WHERE u.intraId LIKE :intraId " - + "order by p.startTime desc"; - return em.createQuery(sql, Penalty.class) - .setParameter("intraId", "%" + intraId + "%") - .getResultList() - .size(); - } - - private long countCurrentByIntraId(String intraId, LocalDateTime targetTime) { - String sql = "select p from Penalty p join fetch p.user where " + - "p.user.intraId like :intraId and TIME_TO_SEC(TIMEDIFF(:targetTime, p.startTime)) < p.penaltyTime * 60 " - + "order by p.startTime desc"; - return em.createQuery(sql, Penalty.class) - .setParameter("intraId", "%" + intraId + "%") - .setParameter("targetTime", targetTime) - .getResultList() - .size(); - - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/data/PenaltyUserAdminRedisRepository.java b/src/main/java/com/gg/server/admin/penalty/data/PenaltyUserAdminRedisRepository.java deleted file mode 100644 index 9e9226078..000000000 --- a/src/main/java/com/gg/server/admin/penalty/data/PenaltyUserAdminRedisRepository.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gg.server.admin.penalty.data; - -import com.gg.server.admin.penalty.type.PenaltyKey; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class PenaltyUserAdminRedisRepository { - private final RedisTemplate redisTemplate; - - public void addPenaltyUser(RedisPenaltyUser penaltyUser, LocalDateTime releaseTime) { - LocalDateTime now = LocalDateTime.now(); - Duration duration = Duration.between(now, releaseTime); - redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, - duration.getSeconds(), TimeUnit.SECONDS); - } - public Optional findByIntraId(String intraId) { - RedisPenaltyUser penaltyUser = redisTemplate.opsForValue().get(PenaltyKey.USER_ADMIN + intraId); - return Optional.ofNullable(penaltyUser); - } - - - public List findAll() { - Set penaltyUserKeys = redisTemplate.keys(PenaltyKey.ALL + "*"); - List users = penaltyUserKeys.stream().map(key -> redisTemplate.opsForValue().get(key)) - .collect(Collectors.toList()); - return users; - } - - public List findAllByKeyword(String keyword) { - Set penaltyUserKeys = redisTemplate.keys(PenaltyKey.ALL + "*" + keyword + "*"); - List users = penaltyUserKeys.stream().map(key -> redisTemplate.opsForValue().get(key)) - .collect(Collectors.toList()); - return users; - } - - public void deletePenaltyInUser(RedisPenaltyUser penaltyUser, Integer penaltyTime) { - LocalDateTime newReleaseTime = penaltyUser.getReleaseTime().minusMinutes(penaltyTime); - penaltyUser.updateReleaseTime(newReleaseTime, penaltyUser.getPenaltyTime() - penaltyTime); - Duration duration = Duration.between(LocalDateTime.now(), newReleaseTime); - if (duration.isNegative()) { - redisTemplate.delete(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId()); - return; - } - redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, - duration.getSeconds(), TimeUnit.SECONDS); - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyListResponseDto.java b/src/main/java/com/gg/server/admin/penalty/dto/PenaltyListResponseDto.java deleted file mode 100644 index e2feef6b6..000000000 --- a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyListResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.admin.penalty.dto; - -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class PenaltyListResponseDto { - List penaltyList; - Integer totalPage; -} diff --git a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyRequestDto.java b/src/main/java/com/gg/server/admin/penalty/dto/PenaltyRequestDto.java deleted file mode 100644 index 06ea3493a..000000000 --- a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyRequestDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.admin.penalty.dto; - -import javax.validation.constraints.PositiveOrZero; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class PenaltyRequestDto { - @Length(max = 30) - private String intraId; - @PositiveOrZero - private Integer penaltyTime; - private String reason; -} diff --git a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyUserResponseDto.java b/src/main/java/com/gg/server/admin/penalty/dto/PenaltyUserResponseDto.java deleted file mode 100644 index 02b56de0e..000000000 --- a/src/main/java/com/gg/server/admin/penalty/dto/PenaltyUserResponseDto.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.gg.server.admin.penalty.dto; - -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import java.time.LocalDateTime; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class PenaltyUserResponseDto { - private Long penaltyId; - private String intraId; - private String reason; - private LocalDateTime releaseTime; - - public PenaltyUserResponseDto(RedisPenaltyUser penaltyUser) { - this.intraId = penaltyUser.getIntraId(); - this.reason = penaltyUser.getReason(); - this.releaseTime = penaltyUser.getReleaseTime(); - } - - public PenaltyUserResponseDto(Penalty penalty) { - this.penaltyId = penalty.getId(); - this.intraId = penalty.getUser().getIntraId(); - this.reason = penalty.getMessage(); - this.releaseTime = penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()); - } - - @Override - public String toString() { - return "PenaltyUserResponseDto{" + - "penaltyId=" + penaltyId + - ", intraId='" + intraId + '\'' + - ", reason='" + reason + '\'' + - ", releaseTime=" + releaseTime + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java b/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java deleted file mode 100644 index dcff03b48..000000000 --- a/src/main/java/com/gg/server/admin/penalty/service/PenaltyAdminService.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.gg.server.admin.penalty.service; - -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; -import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; -import com.gg.server.admin.penalty.dto.PenaltyUserResponseDto; -import com.gg.server.domain.penalty.exception.PenaltyExpiredException; -import com.gg.server.domain.penalty.exception.PenaltyNotFoundException; -import com.gg.server.domain.penalty.exception.RedisPenaltyUserNotFoundException; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.service.UserFindService; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class PenaltyAdminService { - private final PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; - private final UserFindService userFindService; - private final PenaltyAdminRepository penaltyRepository; - - @Transactional - public void givePenalty(String intraId, Integer penaltyTime, String reason) { - User user = userFindService.findByIntraId(intraId); - Optional redisPenaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - LocalDateTime releaseTime; - RedisPenaltyUser penaltyUser; - Penalty penalty; - LocalDateTime now = LocalDateTime.now(); - if (redisPenaltyUser.isPresent()) { - releaseTime = redisPenaltyUser.get().getReleaseTime().plusHours(penaltyTime); - penaltyUser = new RedisPenaltyUser(intraId, redisPenaltyUser.get().getPenaltyTime() + penaltyTime * 60, - releaseTime, redisPenaltyUser.get().getStartTime(), reason); - penalty = new Penalty(user, PenaltyType.NOSHOW, reason, redisPenaltyUser.get().getReleaseTime(), penaltyTime * 60); - } else { - releaseTime = now.plusHours(penaltyTime); - penaltyUser = new RedisPenaltyUser(intraId, penaltyTime * 60, releaseTime, now, reason); - penalty = new Penalty(user, PenaltyType.NOSHOW, reason, now, penaltyTime * 60); - } - penaltyRepository.save(penalty); - penaltyUserAdminRedisRepository.addPenaltyUser(penaltyUser, releaseTime); - } - - - @Transactional(readOnly = true) - public PenaltyListResponseDto getAllPenalties(Pageable pageable, Boolean current) { - Page allPenalties; - if (current) { - allPenalties = penaltyRepository.findAllCurrent(pageable, LocalDateTime.now()); - } else { - allPenalties = penaltyRepository.findAll(pageable); - } - Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); - return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - - @Transactional - public void deletePenalty(Long penaltyId) { - Penalty penalty = penaltyRepository.findById(penaltyId).orElseThrow(() - -> new PenaltyNotFoundException()); - if (penalty.getStartTime().plusMinutes(penalty.getPenaltyTime()).isBefore(LocalDateTime.now())) { - throw new PenaltyExpiredException(); - } - RedisPenaltyUser penaltyUser = penaltyUserAdminRedisRepository - .findByIntraId(penalty.getUser().getIntraId()).orElseThrow(() - -> new RedisPenaltyUserNotFoundException()); - penaltyUserAdminRedisRepository.deletePenaltyInUser(penaltyUser, - penalty.getPenaltyTime());//redis ์‹œ๊ฐ„ ์ค„์—ฌ์ฃผ๊ธฐ - //๋’ค์— ์žˆ๋Š” penalty ์‹œ๊ฐ„ ๋‹น๊ฒจ์ฃผ๊ธฐ - modifyStartTimeOfAfterPenalties(penalty); - penaltyRepository.delete(penalty); - } - - @Transactional(readOnly = true) - public PenaltyListResponseDto getAllPenaltiesByIntraId(Pageable pageable, String intraId, Boolean current) { - Page allPenalties; - if (current) { - allPenalties = penaltyRepository.findAllCurrentByIntraId(pageable, LocalDateTime.now(), intraId); - } else { - allPenalties = penaltyRepository.findAllByIntraId(pageable, intraId); - } - Page responseDtos = allPenalties.map(PenaltyUserResponseDto::new); - return new PenaltyListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - private void modifyStartTimeOfAfterPenalties(Penalty penalty) { - List afterPenalties = penaltyRepository.findAfterPenaltiesByUser(penalty.getUser().getId(), - penalty.getStartTime()); - LocalDateTime newStartTime; - if (penalty.getStartTime().isAfter(LocalDateTime.now())) { - newStartTime = penalty.getStartTime(); - } else { - newStartTime = LocalDateTime.now(); - } - for (Penalty afterPenalty : afterPenalties) { - afterPenalty.updateStartTime(newStartTime); - newStartTime = newStartTime.plusMinutes(afterPenalty.getPenaltyTime()); - } - } -} diff --git a/src/main/java/com/gg/server/admin/penalty/type/PenaltyKey.java b/src/main/java/com/gg/server/admin/penalty/type/PenaltyKey.java deleted file mode 100644 index 3ef35a89c..000000000 --- a/src/main/java/com/gg/server/admin/penalty/type/PenaltyKey.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gg.server.admin.penalty.type; - -public class PenaltyKey { - public static final String ALL = "PENALTY:"; - public static final String USER = "PENALTY:USER:"; - public static final String USER_ADMIN = "PENALTY:USER:ADMIN:"; -} diff --git a/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java b/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java deleted file mode 100644 index ceed91df3..000000000 --- a/src/main/java/com/gg/server/admin/rank/service/RankAdminService.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gg.server.admin.rank.service; - -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.season.exception.SeasonForbiddenException; -import com.gg.server.domain.season.exception.SeasonTimeBeforeException; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static com.gg.server.domain.user.type.RoleType.GUEST; - -@Service -@AllArgsConstructor -public class RankAdminService { - private final RankRepository rankRepository; - private final UserAdminRepository userAdminRepository; - private final SeasonRepository seasonRepository; - private final TierRepository tierRepository; - - @Transactional - public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { - if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) - throw new SeasonTimeBeforeException(); - List users = userAdminRepository.findAll(); - - List ranks = new ArrayList<>(); - Season season = seasonRepository.findById(seasonAdminDto.getSeasonId()).get(); - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - users.forEach(user -> { - if (user.getRoleType() != GUEST) { - Rank userRank = Rank.from(user, season, seasonAdminDto.getStartPpp(), tier); - ranks.add(userRank); - } - }); - rankRepository.saveAll(ranks); - } - - @Transactional - public void deleteAllUserRankBySeason(SeasonAdminDto seasonAdminDto) { - if (LocalDateTime.now().isAfter(seasonAdminDto.getStartTime())) - throw new SeasonForbiddenException(); - - rankRepository.deleteAllBySeasonId(seasonAdminDto.getSeasonId()); - } -} diff --git a/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java b/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java deleted file mode 100644 index c8c6a1cca..000000000 --- a/src/main/java/com/gg/server/admin/rank/service/RankRedisAdminService.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.gg.server.admin.rank.service; - -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static com.gg.server.domain.user.type.RoleType.GUEST; - -@Service -@AllArgsConstructor -public class RankRedisAdminService { - private final UserRepository userRepository; - private final RankRedisRepository rankRedisRepository; - private final TierRepository tierRepository; - - @Transactional - public void addAllUserRankByNewSeason(SeasonAdminDto seasonAdminDto) { - List users = userRepository.findAll(); - - String redisHashKey = RedisKeyManager.getHashKey(seasonAdminDto.getSeasonId()); - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - - users.forEach(user -> { - if (user.getRoleType() != GUEST) { - UserDto userDto = UserDto.from(user); - RankRedis userRank = RankRedis.from(userDto, seasonAdminDto.getStartPpp(), tier.getImageUri()); - - rankRedisRepository.addRankData(redisHashKey, user.getId(), userRank); - } - }); - } - - @Transactional - public void deleteSeasonRankBySeasonId(Long seasonId) { - String redisHashKey = RedisKeyManager.getHashKey(seasonId); - - rankRedisRepository.deleteHashKey(redisHashKey); - } - - public void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { - rankRedisRepository.updateRankData(hashKey, userId, userRank); - if (userPlayedRank(userRank)){ - rankRedisRepository.deleteFromZSet(zsetKey, userId); - rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); - } - } - - private boolean userPlayedRank(RankRedis userRank) { - return (userRank.getWins() + userRank.getLosses()) != 0; - } -} diff --git a/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java b/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java deleted file mode 100644 index 5f67a94e0..000000000 --- a/src/main/java/com/gg/server/admin/receipt/controller/ReceiptAdminController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.admin.receipt.controller; - -import com.gg.server.admin.receipt.dto.ReceiptAdminPageRequestDto; -import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; -import com.gg.server.admin.receipt.service.ReceiptAdminService; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/admin/receipt") -public class ReceiptAdminController { - private final ReceiptAdminService receiptAdminService; - - @GetMapping - public ReceiptListResponseDto getReceiptList(@ModelAttribute @Valid ReceiptAdminPageRequestDto req) { - - if (req.getIntraId() == null) { - Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), - Sort.by("createdAt").descending()); - return receiptAdminService.getAllReceipt(pageable); - } - Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), - Sort.by("createdAt").descending()); - return receiptAdminService.findByIntraId(req.getIntraId(), pageable); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java deleted file mode 100644 index 69f387d11..000000000 --- a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.admin.receipt.data; - -import com.gg.server.domain.receipt.data.Receipt; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ReceiptAdminRepository extends JpaRepository, ReceiptAdminRepositorySearch{ - Page findAll(Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java b/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java deleted file mode 100644 index 4065857a5..000000000 --- a/src/main/java/com/gg/server/admin/receipt/data/ReceiptAdminRepositorySearch.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.admin.receipt.data; - -import com.gg.server.domain.receipt.data.Receipt; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface ReceiptAdminRepositorySearch { - @Query(value = "select re from Receipt re where re.purchaserIntraId = :intraId or re.ownerIntraId = :intraId") - Page findReceiptByIntraId(@Param("intraId") String intraId, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java deleted file mode 100644 index 5fcd0db68..000000000 --- a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptAdminPageRequestDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.admin.receipt.dto; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; - -@Getter -public class ReceiptAdminPageRequestDto extends PageRequestDto { - private String intraId; - - public ReceiptAdminPageRequestDto(String intraId, Integer page, Integer size) { - super(page, size); - this.intraId = intraId; - } -} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java deleted file mode 100644 index e994ac244..000000000 --- a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptListResponseDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.receipt.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ReceiptListResponseDto { - private List receiptList; - private Integer totalPage; -} diff --git a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java b/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java deleted file mode 100644 index 41c9e1b44..000000000 --- a/src/main/java/com/gg/server/admin/receipt/dto/ReceiptResponseDto.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gg.server.admin.receipt.dto; - -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.type.ItemStatus; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class ReceiptResponseDto { - private Long receiptId; - private LocalDateTime createdAt; - private String itemName; - private Integer itemPrice; - private String purchaserIntraId; - private String ownerIntraId; - private ItemStatus itemStatusType; - - public ReceiptResponseDto(Receipt receipt) { - Item item = receipt.getItem(); - this.itemName = item.getName(); - this.itemPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); - this.receiptId = receipt.getId(); - this.createdAt = receipt.getCreatedAt(); - this.purchaserIntraId = receipt.getPurchaserIntraId(); - this.ownerIntraId = receipt.getOwnerIntraId(); - this.itemStatusType = receipt.getStatus(); - } - - @Override - public String toString() { - return "ReceiptResponseDto{" + - "receiptId=" + receiptId + - ", createdAt=" + createdAt + - ", itemName='" + itemName + '\'' + - ", itemPrice=" + itemPrice + - ", purchaserIntraId='" + purchaserIntraId + '\'' + - ", ownerIntraId='" + ownerIntraId + '\'' + - ", itemStatusType=" + itemStatusType + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java b/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java deleted file mode 100644 index 9462acbbf..000000000 --- a/src/main/java/com/gg/server/admin/receipt/service/ReceiptAdminService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.admin.receipt.service; - -import com.gg.server.admin.receipt.data.ReceiptAdminRepository; -import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; -import com.gg.server.admin.receipt.dto.ReceiptResponseDto; -import com.gg.server.domain.receipt.data.Receipt; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class ReceiptAdminService { - private final ReceiptAdminRepository receiptAdminRepository; - - @Transactional(readOnly = true) - public ReceiptListResponseDto getAllReceipt(Pageable pageable) { - Page responseDtos = receiptAdminRepository.findAll(pageable).map(ReceiptResponseDto::new); - return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - @Transactional(readOnly = true) - public ReceiptListResponseDto findByIntraId(String intraId, Pageable pageable) { - Page receipts = receiptAdminRepository.findReceiptByIntraId(intraId, pageable); - Page responseDtos = receipts.map(ReceiptResponseDto::new); - return new ReceiptListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } -} diff --git a/src/main/java/com/gg/server/admin/season/controller/SeasonAdminController.java b/src/main/java/com/gg/server/admin/season/controller/SeasonAdminController.java deleted file mode 100644 index 71faca85e..000000000 --- a/src/main/java/com/gg/server/admin/season/controller/SeasonAdminController.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.gg.server.admin.season.controller; - -import com.gg.server.admin.season.dto.SeasonCreateRequestDto; -import com.gg.server.admin.season.dto.SeasonUpdateRequestDto; -import com.gg.server.admin.season.service.SeasonAdminService; -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.admin.season.dto.SeasonListAdminResponseDto; -import lombok.AllArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.List; - -@RestController -@RequestMapping(value = "/pingpong/admin") -@AllArgsConstructor -public class SeasonAdminController { - private final SeasonAdminService seasonAdminService; - - @GetMapping(value = "/seasons") - public SeasonListAdminResponseDto rankSeasonList() { - List seasons = seasonAdminService.findAllSeasons(); - - return new SeasonListAdminResponseDto(seasons); - } - - @PostMapping(value = "/seasons") - public synchronized ResponseEntity createSeason(@Valid @RequestBody SeasonCreateRequestDto seasonCreateReqeustDto) { - seasonAdminService.createSeason(seasonCreateReqeustDto); - - return new ResponseEntity(HttpStatus.CREATED); - } - - @DeleteMapping(value = "/seasons/{seasonId}") - public synchronized ResponseEntity deleteSeason(@PathVariable Long seasonId) { - seasonAdminService.deleteSeason(seasonId); - - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - - @PutMapping(value = "/seasons/{seasonId}") - public synchronized ResponseEntity updateSeason(@PathVariable Long seasonId, @RequestBody SeasonUpdateRequestDto seasonUpdateRequestDto) { - seasonAdminService.updateSeason(seasonId, seasonUpdateRequestDto); - - return new ResponseEntity(HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/admin/season/data/SeasonAdminRepository.java b/src/main/java/com/gg/server/admin/season/data/SeasonAdminRepository.java deleted file mode 100644 index 171c8fd13..000000000 --- a/src/main/java/com/gg/server/admin/season/data/SeasonAdminRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.admin.season.data; - -import com.gg.server.domain.season.data.Season; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -public interface SeasonAdminRepository extends JpaRepository { - /* ์ž…๋ ฅ์‹œ๊ฐ„๊ณผ ๋ชจ๋“œ๋กœ ์ž…๋ ฅ์‹œ๊ฐ„ ์ดํ›„ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์‹œ์ฆŒ ๊ฐ€์ ธ์˜ค๊ธฐ */ - @Query("SELECT e FROM Season e WHERE e.startTime > :targetTime ORDER BY e.startTime ASC") - List findAfterSeasons(@Param("targetTime") LocalDateTime targetTime); - @Query("SELECT e FROM Season e WHERE e.startTime < :targetTime ORDER BY e.startTime DESC") - List findBeforeSeasons(@Param("targetTime") LocalDateTime targetTime); - @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now") - Optional findCurrentSeason(@Param("now") LocalDateTime now); - - List findAllByOrderByStartTimeDesc(); -} diff --git a/src/main/java/com/gg/server/admin/season/dto/SeasonAdminDto.java b/src/main/java/com/gg/server/admin/season/dto/SeasonAdminDto.java deleted file mode 100644 index c4a385b8e..000000000 --- a/src/main/java/com/gg/server/admin/season/dto/SeasonAdminDto.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.admin.season.dto; - -import com.gg.server.admin.season.type.SeasonStatus; -import com.gg.server.domain.season.data.Season; -import lombok.*; - -import java.time.LocalDateTime; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SeasonAdminDto { - - private Long seasonId; - private String seasonName; - private LocalDateTime startTime; - private LocalDateTime endTime; - private Integer startPpp; - private Integer pppGap; - private String status; - - public SeasonAdminDto(Season season) { - this.seasonId = season.getId(); - this.seasonName = season.getSeasonName(); - this.startTime = season.getStartTime(); - this.endTime = season.getEndTime(); - this.startPpp = season.getStartPpp(); - this.pppGap = season.getPppGap(); - this.status = getSeasonStatus(season); - } - - public String getSeasonStatus(Season season) { - LocalDateTime now = LocalDateTime.now(); - - if (now.isAfter(season.getEndTime())) - return SeasonStatus.SEASON_PAST.getSesonstauts(); - else if (now.isAfter(season.getStartTime()) && now.isBefore((season.getEndTime()))) - return SeasonStatus.SEASON_CURRENT.getSesonstauts(); - else - return SeasonStatus.SEASON_FUTURE.getSesonstauts(); - } -} diff --git a/src/main/java/com/gg/server/admin/season/dto/SeasonCreateRequestDto.java b/src/main/java/com/gg/server/admin/season/dto/SeasonCreateRequestDto.java deleted file mode 100644 index d24f7e0a4..000000000 --- a/src/main/java/com/gg/server/admin/season/dto/SeasonCreateRequestDto.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gg.server.admin.season.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.Future; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SeasonCreateRequestDto { - @NotNull(message = "plz. seasonName") - private String seasonName; - - @NotNull(message = "plz. startTime") - @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) - private LocalDateTime startTime; - - @NotNull(message = "plz. startPpp") - private Integer startPpp; - - @NotNull(message = "plz. pppGap") - private Integer pppGap; - - public String toString() { - return "SeasonCreateRequestAdminDto{" + '\'' + - "seasonName=" + seasonName + '\'' + - ", startTime=" + startTime + - ", startPpp='" + startPpp + '\'' + - ", pppGap='" + pppGap + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/season/dto/SeasonListAdminResponseDto.java b/src/main/java/com/gg/server/admin/season/dto/SeasonListAdminResponseDto.java deleted file mode 100644 index 43290915f..000000000 --- a/src/main/java/com/gg/server/admin/season/dto/SeasonListAdminResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.admin.season.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class SeasonListAdminResponseDto { - List seasonList; - - public SeasonListAdminResponseDto(List seasonList) { - this.seasonList = seasonList; - } - -} diff --git a/src/main/java/com/gg/server/admin/season/dto/SeasonUpdateRequestDto.java b/src/main/java/com/gg/server/admin/season/dto/SeasonUpdateRequestDto.java deleted file mode 100644 index 6d2d081bd..000000000 --- a/src/main/java/com/gg/server/admin/season/dto/SeasonUpdateRequestDto.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.admin.season.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.Future; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class SeasonUpdateRequestDto { - @NotNull(message = "plz. seasonName") - private String seasonName; - - @NotNull(message = "plz. startTime") - @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) - private LocalDateTime startTime; - - @NotNull(message = "plz. startPpp") - private Integer startPpp; - - @NotNull(message = "plz. pppGap") - private Integer pppGap; - -} diff --git a/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java b/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java deleted file mode 100644 index aeee8b46d..000000000 --- a/src/main/java/com/gg/server/admin/season/service/SeasonAdminService.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.gg.server.admin.season.service; - -import com.gg.server.admin.rank.service.RankAdminService; -import com.gg.server.admin.rank.service.RankRedisAdminService; -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.season.dto.SeasonCreateRequestDto; -import com.gg.server.admin.season.dto.SeasonUpdateRequestDto; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonForbiddenException; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.season.exception.SeasonTimeBeforeException; -import com.gg.server.global.exception.ErrorCode; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Service -@AllArgsConstructor -public class SeasonAdminService { - private final SeasonAdminRepository seasonAdminRepository; - private final RankRedisAdminService rankRedisAdminService; - private final RankAdminService rankAdminService; - - public List findAllSeasons() { - List seasons = seasonAdminRepository.findAllByOrderByStartTimeDesc(); - List dtoList = new ArrayList<>(); - for (Season season : seasons) { - SeasonAdminDto dto = new SeasonAdminDto(season); - dtoList.add(dto); - } - return dtoList; - } - - @Transactional - public void createSeason(SeasonCreateRequestDto createDto) { - Season newSeason = new Season(createDto); - - insert(newSeason); - seasonAdminRepository.save(newSeason); - - checkSeasonAtDB(); - - Long seasonId = newSeason.getId(); - SeasonAdminDto seasonAdminDto = findSeasonById(seasonId); - - if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { - rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); - rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); - } - } - - @Transactional - public SeasonAdminDto findSeasonById(Long seasonId) { - Season season = seasonAdminRepository.findById(seasonId).orElseThrow(()-> new SeasonNotFoundException()); - - return new SeasonAdminDto(season); - } - - - @Transactional - public void deleteSeason(Long seasonId) { - SeasonAdminDto seasonDto = findSeasonById(seasonId); - - Season season = seasonAdminRepository.findById(seasonDto.getSeasonId()) - .orElseThrow(() -> new SeasonNotFoundException()); - detach(season); - - if (LocalDateTime.now().isBefore(seasonDto.getStartTime())) { - rankAdminService.deleteAllUserRankBySeason(seasonDto); - rankRedisAdminService.deleteSeasonRankBySeasonId(seasonDto.getSeasonId()); - seasonAdminRepository.delete(season); - } - checkSeasonAtDB(); - } - - @Transactional - public void updateSeason(Long seasonId, SeasonUpdateRequestDto updateDto) { - Season season = seasonAdminRepository.findById(seasonId) - .orElseThrow(() -> new SeasonNotFoundException()); - - if (LocalDateTime.now().isAfter(season.getStartTime())) - throw new SeasonForbiddenException(); - - if (LocalDateTime.now().isBefore(season.getStartTime())) { - detach(season); - season.setSeasonName(updateDto.getSeasonName()); - season.setStartTime(updateDto.getStartTime()); - season.setStartPpp(updateDto.getStartPpp()); - season.setPppGap(updateDto.getPppGap()); - insert(season); - seasonAdminRepository.save(season); - checkSeasonAtDB(); - } - - SeasonAdminDto seasonAdminDto = findSeasonById(seasonId); - if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { - rankAdminService.deleteAllUserRankBySeason(seasonAdminDto); - rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); - rankRedisAdminService.deleteSeasonRankBySeasonId(seasonAdminDto.getSeasonId()); - rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); - } - } - - private void insert(Season season) - { - List beforeSeasons = seasonAdminRepository.findBeforeSeasons(season.getStartTime()); - Season beforeSeason; - if (beforeSeasons.isEmpty()) - beforeSeason = null; - else - beforeSeason = beforeSeasons.get(0).getId() != season.getId()? beforeSeasons.get(0) : beforeSeasons.get(1); - List afterSeasons = seasonAdminRepository.findAfterSeasons(season.getStartTime()); - Season afterSeason = afterSeasons.isEmpty() ? null : afterSeasons.get(0); - - if (LocalDateTime.now().plusHours(24).isAfter(season.getStartTime())) - throw new SeasonTimeBeforeException(); - if (beforeSeason != null) { - if (beforeSeason.getStartTime().plusDays(1).isAfter(season.getStartTime())) - throw new SeasonForbiddenException(); - beforeSeason.setEndTime(season.getStartTime().minusSeconds(1)); - } - if (afterSeason != null) - season.setEndTime(afterSeason.getStartTime().minusSeconds(1)); - else - season.setEndTime(LocalDateTime.of(9999, 12, 31, 23, 59, 59)); - } - - private void detach(Season season) - { - List beforeSeasons = seasonAdminRepository.findBeforeSeasons(season.getStartTime()); - Season beforeSeason = beforeSeasons.isEmpty() ? null : beforeSeasons.get(0); - List afterSeasons = seasonAdminRepository.findAfterSeasons(season.getStartTime()); - Season afterSeason = afterSeasons.isEmpty() ? null : afterSeasons.get(0); - - if ((LocalDateTime.now().isAfter(season.getStartTime()) && LocalDateTime.now().isBefore(season.getEndTime())) - || season.getEndTime().isBefore(LocalDateTime.now())) - throw new SeasonForbiddenException(); - if (beforeSeason != null) { - if (afterSeason != null) - beforeSeason.setEndTime(afterSeason.getStartTime().minusSeconds(1)); - else - beforeSeason.setEndTime(LocalDateTime.of(9999, 12, 31, 23, 59, 59)); - } - } - - private void checkSeasonAtDB() - { - List seasons = seasonAdminRepository.findAll(); - for (int i = 0; i < seasons.size(); i++) { - for (int j = i + 1; j < seasons.size(); j++) { - if (isOverlap(seasons.get(i), seasons.get(j))) - throw new SeasonForbiddenException(); - } - } - } - - private boolean isOverlap(Season season1, Season season2) { - LocalDateTime start1 = season1.getStartTime(); - LocalDateTime end1 = season1.getEndTime(); - LocalDateTime start2 = season2.getStartTime(); - LocalDateTime end2 = season2.getEndTime(); - - if (start1.isEqual(end1) || start2.isEqual(end2)) { - return false; - } - // ์ฒซ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์ด ๋‘ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์˜ ์ด์ „์— ๋๋‚  ๋•Œ - if (end1.isBefore(start2)) { - return false; - } - - // ์ฒซ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์ด ๋‘ ๋ฒˆ์งธ ๊ธฐ๊ฐ„์˜ ์ดํ›„์— ์‹œ์ž‘ํ•  ๋•Œ - if (start1.isAfter(end2)) { - return false; - } - - // ๋‚˜๋จธ์ง€ ๊ฒฝ์šฐ์—๋Š” ๋‘ ๊ธฐ๊ฐ„์ด ๊ฒน์นฉ๋‹ˆ๋‹ค. - return true; - } -} diff --git a/src/main/java/com/gg/server/admin/season/type/SeasonStatus.java b/src/main/java/com/gg/server/admin/season/type/SeasonStatus.java deleted file mode 100644 index 9ed5ba3bc..000000000 --- a/src/main/java/com/gg/server/admin/season/type/SeasonStatus.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.admin.season.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - - -@Getter -@RequiredArgsConstructor -public enum SeasonStatus { - - SEASON_PAST("PAST"), - SEASON_CURRENT("CURRENT"), - SEASON_FUTURE("FUTURE"); - - private final String Sesonstauts; - -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/controller/SlotAdminController.java b/src/main/java/com/gg/server/admin/slotmanagement/controller/SlotAdminController.java deleted file mode 100644 index 427c0938f..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/controller/SlotAdminController.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.admin.slotmanagement.controller; - -import com.gg.server.admin.slotmanagement.dto.SlotCreateRequestDto; -import com.gg.server.admin.slotmanagement.dto.SlotListAdminResponseDto; -import com.gg.server.admin.slotmanagement.service.SlotAdminService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -@Slf4j -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/admin/slot-management") -public class SlotAdminController { - private final SlotAdminService slotAdminService; - - @GetMapping - public SlotListAdminResponseDto getSlotSetting() { - - return slotAdminService.getSlotSetting(); - } - - @PostMapping - public synchronized ResponseEntity addSlotSetting(@Valid @RequestBody SlotCreateRequestDto requestDto){ - slotAdminService.addSlotSetting(requestDto); - return new ResponseEntity(HttpStatus.CREATED); - } - - @DeleteMapping - public synchronized ResponseEntity delSlotSetting(){ - slotAdminService.delSlotSetting(); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/data/adminSlotManagementRepository.java b/src/main/java/com/gg/server/admin/slotmanagement/data/adminSlotManagementRepository.java deleted file mode 100644 index bdc7ad793..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/data/adminSlotManagementRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.admin.slotmanagement.data; - -import com.gg.server.domain.slotmanagement.SlotManagement; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -public interface adminSlotManagementRepository extends JpaRepository { - @Query("select slot from SlotManagement slot where slot.endTime > :nowTime or slot.startTime > :nowTime or slot.endTime = null order by slot.startTime desc") - List findAfterNowSlotManagement(@Param("nowTime")LocalDateTime nowTime); - - List findAllByOrderByCreatedAtDesc(); - - Optional findFirstByOrderByIdDesc(); - -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotAdminDto.java b/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotAdminDto.java deleted file mode 100644 index 6b57e7b72..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotAdminDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.admin.slotmanagement.dto; - -import com.gg.server.domain.slotmanagement.SlotManagement; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SlotAdminDto { - private Integer pastSlotTime; - - private Integer futureSlotTime; - - private Integer interval; - - private Integer openMinute; - - private LocalDateTime startTime; - - private LocalDateTime endTime; - - public SlotAdminDto(SlotManagement slotManagement) { - this.pastSlotTime = slotManagement.getPastSlotTime(); - this.futureSlotTime = slotManagement.getFutureSlotTime(); - this.interval = slotManagement.getGameInterval(); - this.openMinute = slotManagement.getOpenMinute(); - this.startTime = slotManagement.getStartTime(); - this.endTime = slotManagement.getEndTime(); - } -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotCreateRequestDto.java b/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotCreateRequestDto.java deleted file mode 100644 index 64aad8f73..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotCreateRequestDto.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gg.server.admin.slotmanagement.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.Future; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; -import java.time.LocalDateTime; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SlotCreateRequestDto { - @NotNull(message = "Nothing pastSlotTime") - @PositiveOrZero(message = "plz. Positive Or Zero") - private Integer pastSlotTime; - - @NotNull(message = "Nothing futureSlotTime") - @PositiveOrZero(message = "plz. Positive Or Zero") - private Integer futureSlotTime; - - @NotNull(message = "Nothing interval") - @PositiveOrZero(message = "plz. Positive Or Zero") - private Integer interval; - - @NotNull(message = "Nothing openMinute") - @PositiveOrZero(message = "plz. Positive Or Zero") - private Integer openMinute; - - @NotNull(message = "Nothing startTime") - @Future(message = "๋ถˆ๊ฐ€๋Šฅํ•œ ์˜ˆ์•ฝ์‹œ์ ์ž…๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) - private LocalDateTime startTime; - - public void updateStartTime(){ - LocalDateTime setStartTime = LocalDateTime.of( - this.startTime.getYear(), this.startTime.getMonth(), - this.startTime.getDayOfMonth(), this.startTime.getHour(), 0); - this.startTime = setStartTime; - } - -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotListAdminResponseDto.java b/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotListAdminResponseDto.java deleted file mode 100644 index 2149c9f0c..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/dto/SlotListAdminResponseDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.slotmanagement.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class SlotListAdminResponseDto { - List slotList; - - public SlotListAdminResponseDto(List slotList) { - this.slotList = slotList; - } -} diff --git a/src/main/java/com/gg/server/admin/slotmanagement/service/SlotAdminService.java b/src/main/java/com/gg/server/admin/slotmanagement/service/SlotAdminService.java deleted file mode 100644 index 046dc7127..000000000 --- a/src/main/java/com/gg/server/admin/slotmanagement/service/SlotAdminService.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.gg.server.admin.slotmanagement.service; - -import com.gg.server.admin.slotmanagement.data.adminSlotManagementRepository; -import com.gg.server.admin.slotmanagement.dto.SlotAdminDto; -import com.gg.server.admin.slotmanagement.dto.SlotCreateRequestDto; -import com.gg.server.admin.slotmanagement.dto.SlotListAdminResponseDto; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.exception.SlotManagementForbiddenException; -import com.gg.server.domain.slotmanagement.exception.SlotManagementNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class SlotAdminService { - private final adminSlotManagementRepository adminSlotManagementRepository; - - @Transactional(readOnly = true) - public SlotListAdminResponseDto getSlotSetting() { - List slotManagements = adminSlotManagementRepository.findAfterNowSlotManagement(LocalDateTime.now()); - List dtoList = new ArrayList<>(); - for (SlotManagement slot : slotManagements) { - SlotAdminDto dto = new SlotAdminDto(slot); - dtoList.add(dto); - } - return new SlotListAdminResponseDto(dtoList); - } - - @Transactional - public void addSlotSetting(SlotCreateRequestDto requestDto) { - checkVaildSlotManagement(requestDto); - requestDto.updateStartTime(); - updateNowSlotManagementEndTime(requestDto.getStartTime()); - SlotManagement slotManagement = new SlotManagement(requestDto); - - adminSlotManagementRepository.save(slotManagement); - } - - @Transactional - public void delSlotSetting() { - List slotManagements = adminSlotManagementRepository.findAfterNowSlotManagement(LocalDateTime.now()); - - SlotManagement slotManagement = slotManagements.get(0); - if (LocalDateTime.now().isAfter(slotManagement.getStartTime())) - throw new SlotManagementForbiddenException(); - adminSlotManagementRepository.delete(slotManagement); - - SlotManagement beforeSlotManagement = slotManagements.get(1); - beforeSlotManagement.setNullEndTime(); - } - - private void checkVaildSlotManagement(SlotCreateRequestDto requestDto) { - if (requestDto.getPastSlotTime() > 23) - throw new SlotManagementForbiddenException(); - if (requestDto.getFutureSlotTime() > 12) - throw new SlotManagementForbiddenException(); - if (60 % requestDto.getInterval() != 0 || requestDto.getInterval() % 5 != 0) - throw new SlotManagementForbiddenException(); - if (requestDto.getPastSlotTime() > requestDto.getInterval()) - throw new SlotManagementForbiddenException(); - } - - private void updateNowSlotManagementEndTime(LocalDateTime endTime){ - SlotManagement nowSlotManagement = adminSlotManagementRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new SlotManagementNotFoundException()); - - LocalDateTime nowFutureSlotTime = LocalDateTime.now().isAfter(nowSlotManagement.getStartTime()) - ?LocalDateTime.now().plusHours(nowSlotManagement.getFutureSlotTime()) - :nowSlotManagement.getStartTime().plusHours(nowSlotManagement.getFutureSlotTime()); - - if (nowFutureSlotTime.isAfter(endTime)) - throw new SlotManagementForbiddenException(); - - nowSlotManagement.updateEndTime(endTime); - } -} diff --git a/src/main/java/com/gg/server/admin/team/data/TeamAdminRepository.java b/src/main/java/com/gg/server/admin/team/data/TeamAdminRepository.java deleted file mode 100644 index 9fd091379..000000000 --- a/src/main/java/com/gg/server/admin/team/data/TeamAdminRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.admin.team.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.team.data.Team; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; - -public interface TeamAdminRepository extends JpaRepository { - List findAllByGame(Game game); - -} diff --git a/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java b/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java deleted file mode 100644 index 07974e80d..000000000 --- a/src/main/java/com/gg/server/admin/team/data/TeamUserAdminRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.admin.team.data; - -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.user.data.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - -public interface TeamUserAdminRepository extends JpaRepository { - @Query("SELECT tu.user FROM TeamUser tu WHERE tu.team.id = :teamId") - List findUsersByTeamId(@Param("teamId") Long teamId); - - @Query("SELECT tu FROM TeamUser tu, Team t WHERE tu.team.id IN (:teamId) AND t.id = tu.team.id") - List findUsersByTeamIdIn(@Param("teamId") List teamId); -} diff --git a/src/main/java/com/gg/server/admin/tournament/controller/TournamentAdminController.java b/src/main/java/com/gg/server/admin/tournament/controller/TournamentAdminController.java deleted file mode 100644 index 6117eaa72..000000000 --- a/src/main/java/com/gg/server/admin/tournament/controller/TournamentAdminController.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.gg.server.admin.tournament.controller; - -import com.gg.server.admin.tournament.dto.*; -import com.gg.server.admin.tournament.service.TournamentAdminService; -import javax.validation.Valid; - -import com.gg.server.domain.tournament.dto.TournamentUserListResponseDto; -import lombok.AllArgsConstructor; -import javax.validation.constraints.Positive; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -@RestController -@AllArgsConstructor -@RequestMapping("/pingpong/admin/tournaments") -@Validated -public class TournamentAdminController { - private final TournamentAdminService tournamentAdminService; - - /*** - * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ - * @param tournamentAdminCreateRequestDto ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ - * @return "CREATED" ์‘๋‹ต ์ฝ”๋“œ - */ - @PostMapping() - public ResponseEntity createTournament(@RequestBody @Valid TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto) { - tournamentAdminService.createTournament(tournamentAdminCreateRequestDto); - return ResponseEntity.status(HttpStatus.CREATED).build(); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์ •๋ณด ์ˆ˜์ •

- * @param tournamentId ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ id - * @param tournamentAdminUpdateRequestDto ์š”์ฒญ ๋ฐ์ดํ„ฐ - * @return HttpStatus.NO_CONTENT - */ - @PatchMapping("/{tournamentId}") - public ResponseEntity updateTournamentInfo(@PathVariable @Positive Long tournamentId, - @Valid @RequestBody TournamentAdminUpdateRequestDto tournamentAdminUpdateRequestDto) { - tournamentAdminService.updateTournamentInfo(tournamentId, tournamentAdminUpdateRequestDto); - - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์ •๋ณด ์‚ญ์ œ

- * @param tournamentId ์‚ญ์ œํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ id - * @return HttpStatus.NO_CONTENT - */ - @DeleteMapping("/{tournamentId}") - public ResponseEntity deleteTournament(@PathVariable @Positive Long tournamentId) { - tournamentAdminService.deleteTournament(tournamentId); - - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์ถ”๊ฐ€

- *

์ด๋ฏธ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์ฐธ์—ฌ์ค‘์ด๊ฑฐ๋‚˜ ๋Œ€๊ธฐ์ž์ธ ์œ ์ €๋Š” ์‹ ์ฒญํ•  ์ˆ˜ ์—†๋‹ค.

- * @param tournamentId ์œ ์ €๋ฅผ ์ถ”๊ฐ€ํ•  ํ† ๋„ˆ๋จผํŠธ id - * @param tournamentAdminUserAddRequestDto ์š”์ฒญ ๋ฐ์ดํ„ฐ - * @return TournamentAdminAddUserResponseDto, HttpStatus.CREATED - */ - @PostMapping("/{tournamentId}/users") - public ResponseEntity addTournamentUser(@PathVariable @Positive Long tournamentId, - @Valid @RequestBody TournamentAdminAddUserRequestDto tournamentAdminUserAddRequestDto) { - TournamentAdminAddUserResponseDto responseDto = tournamentAdminService.addTournamentUser(tournamentId, tournamentAdminUserAddRequestDto); - - return ResponseEntity.status(HttpStatus.CREATED).body(responseDto); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์กฐํšŒ

- * @param tournamentId ์œ ์ €๋ฅผ ์กฐํšŒํ•  ํ† ๋„ˆ๋จผํŠธ id - * @param isJoined ์ฐธ์—ฌ์ค‘์ธ ์œ ์ €๋งŒ ์กฐํšŒํ• ์ง€ ์—ฌ๋ถ€ - * @return TournamentUserListResponseDto - */ - @GetMapping("/{tournamentId}/users") - public ResponseEntity getTournamentUserList(@PathVariable @Positive Long tournamentId, - @RequestParam(required = false) Boolean isJoined) { - TournamentUserListResponseDto responseDto = tournamentAdminService.getTournamentUserList(tournamentId, isJoined); - return ResponseEntity.status(HttpStatus.OK).body(responseDto); - } - - /** - *

๊ด€๋ฆฌ์ž ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์‚ญ์ œ

- *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ €๋ฅผ ์‚ญ์ œ์‹œ์ผœ ์ฃผ๋ฉฐ, ์ฐธ๊ฐ€์ž๊ฐ€ ์‚ญ์ œ๋˜๋Š” ๊ฒฝ์šฐ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋Œ€๊ธฐ์ž๋ฅผ ์ฐธ๊ฐ€์ž๋กœ ๋ฐ”๊พธ์–ด์ค€๋‹ค.

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @param userId ํƒ€๊ฒŸ ์œ ์ € id - */ - @DeleteMapping("/{tournamentId}/users/{userId}") - public ResponseEntity deleteTournamentUser(@PathVariable @Positive Long tournamentId, - @PathVariable @Positive Long userId) { - tournamentAdminService.deleteTournamentUser(tournamentId, userId); - - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ •๋ณด ์ˆ˜์ •

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @param tournamentGameUpdateReqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด - * @return HttpStatus.OK - */ - @PatchMapping("{tournamentId}/games") - public ResponseEntity updateTournamentGame(@PathVariable @Positive Long tournamentId, - @Valid @RequestBody TournamentGameUpdateRequestDto tournamentGameUpdateReqDto) { - tournamentAdminService.updateTournamentGame(tournamentId, tournamentGameUpdateReqDto); - return ResponseEntity.status(HttpStatus.OK).build(); - } -} diff --git a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserRequestDto.java b/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserRequestDto.java deleted file mode 100644 index f5be89a01..000000000 --- a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserRequestDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.tournament.dto; - -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TournamentAdminAddUserRequestDto { - @NotNull(message = "intraId๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - private String intraId; -} diff --git a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserResponseDto.java b/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserResponseDto.java deleted file mode 100644 index 063e0a302..000000000 --- a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminAddUserResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.admin.tournament.dto; - -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TournamentAdminAddUserResponseDto { - private Long userId; - - private String intraId; - - private Boolean isJoined; - -} diff --git a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminCreateRequestDto.java b/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminCreateRequestDto.java deleted file mode 100644 index 2c40d764a..000000000 --- a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminCreateRequestDto.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.admin.tournament.dto; - -import com.gg.server.domain.tournament.type.TournamentType; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class TournamentAdminCreateRequestDto { - @NotNull(message = "์ œ๋ชฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @Length(max = 30, message = "์ œ๋ชฉ์€ 30์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") - private String title; - - @NotNull(message = "๋‚ด์šฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @Length(max = 3000, message = "๋‚ด์šฉ์€ 3000์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") - private String contents; - - @NotNull(message = "์‹œ์ž‘ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - private LocalDateTime startTime; - - @NotNull(message = "์ข…๋ฃŒ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) - private LocalDateTime endTime; - - @NotNull(message = "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - private TournamentType type; -} diff --git a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminUpdateRequestDto.java b/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminUpdateRequestDto.java deleted file mode 100644 index ef7def536..000000000 --- a/src/main/java/com/gg/server/admin/tournament/dto/TournamentAdminUpdateRequestDto.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.admin.tournament.dto; - -import com.gg.server.domain.tournament.type.TournamentType; -import java.time.LocalDateTime; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.format.annotation.DateTimeFormat.ISO; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TournamentAdminUpdateRequestDto { - @NotNull(message = "์ œ๋ชฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @Length(max = 30, message = "์ œ๋ชฉ์€ 30์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") - private String title; - - @NotNull(message = "๋‚ด์šฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @Length(max = 3000, message = "๋‚ด์šฉ์€ 3000์ž ์ด๋‚ด๋กœ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.") - private String contents; - - @NotNull(message = "์‹œ์ž‘ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = ISO.DATE_TIME) - private LocalDateTime startTime; - - @NotNull(message = "์ข…๋ฃŒ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @DateTimeFormat(iso = ISO.DATE_TIME) - private LocalDateTime endTime; - - @NotNull(message = "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.") - @Enumerated(EnumType.STRING) - private TournamentType type; -} diff --git a/src/main/java/com/gg/server/admin/tournament/dto/TournamentGameUpdateRequestDto.java b/src/main/java/com/gg/server/admin/tournament/dto/TournamentGameUpdateRequestDto.java deleted file mode 100644 index fc1f6a954..000000000 --- a/src/main/java/com/gg/server/admin/tournament/dto/TournamentGameUpdateRequestDto.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gg.server.admin.tournament.dto; - -import com.gg.server.domain.team.dto.TeamReqDto; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class TournamentGameUpdateRequestDto { - - @NotNull - private Long tournamentGameId; - - private Long nextTournamentGameId; - @NotNull - @Valid - private TeamReqDto team1; - @NotNull - @Valid - private TeamReqDto team2; - - @Override - public String toString() { - return "TournamentGameUpdateReqDto{" + - "tournamentGameId=" + tournamentGameId + - ", nextTournamentGameId=" + nextTournamentGameId + - ", team1=" + team1 + - ", team2=" + team2 + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/tournament/service/TournamentAdminService.java b/src/main/java/com/gg/server/admin/tournament/service/TournamentAdminService.java deleted file mode 100644 index 8e7840635..000000000 --- a/src/main/java/com/gg/server/admin/tournament/service/TournamentAdminService.java +++ /dev/null @@ -1,355 +0,0 @@ -package com.gg.server.admin.tournament.service; - -import com.gg.server.admin.tournament.dto.*; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.ScoreNotInvalidException; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.match.service.MatchTournamentService; -import com.gg.server.domain.match.type.TournamentMatchStatus; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.tournament.data.*; -import com.gg.server.domain.tournament.dto.TournamentUserListResponseDto; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.exception.TournamentGameNotFoundException; -import com.gg.server.domain.tournament.exception.TournamentNotFoundException; -import com.gg.server.domain.tournament.exception.TournamentUpdateException; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.config.ConstantConfig; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; -import java.time.LocalDate; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static com.gg.server.domain.match.type.TournamentMatchStatus.*; - -@Service -@RequiredArgsConstructor -public class TournamentAdminService { - private final TournamentRepository tournamentRepository; - private final TournamentUserRepository tournamentUserRepository; - private final UserRepository userRepository; - private final GameRepository gameRepository; - private final TournamentGameRepository tournamentGameRepository; - private final SlotManagementRepository slotManagementRepository; - private final MatchTournamentService matchTournamentService; - private final ConstantConfig constantConfig; - private final GameService gameService; - - /*** - * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ Method - * @param tournamentAdminCreateRequestDto ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ - * @throws TournamentConflictException ํ† ๋„ˆ๋จผํŠธ์˜ ์ œ๋ชฉ์ด ๊ฒน์น  ๋•Œ - * @throws TournamentUpdateException ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์œผ๋กœ ๋ถ€์ ํ•ฉ ํ•  ๋•Œ - * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ && ๊ฒŒ์ž„ ์กด์žฌํ•  ๋•Œ - * @return ์ƒˆ๋กœ ์ƒ์„ฑ๋œ tournament - */ - @Transactional - public void createTournament(TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto) { - checkValidTournamentTime(tournamentAdminCreateRequestDto.getStartTime(), tournamentAdminCreateRequestDto.getEndTime()); - checkConflictedTournament(-1L, tournamentAdminCreateRequestDto.getStartTime(), tournamentAdminCreateRequestDto.getEndTime()); - checkGameExistence(tournamentAdminCreateRequestDto.getStartTime(), tournamentAdminCreateRequestDto.getEndTime()); - - Tournament tournament = Tournament.builder() - .title(tournamentAdminCreateRequestDto.getTitle()) - .contents(tournamentAdminCreateRequestDto.getContents()) - .startTime(tournamentAdminCreateRequestDto.getStartTime()) - .endTime(tournamentAdminCreateRequestDto.getEndTime()) - .type(tournamentAdminCreateRequestDto.getType()) - .status(TournamentStatus.BEFORE).build(); - createTournamentGameList(tournament, 7); - tournamentRepository.save(tournament); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์—…๋ฐ์ดํŠธ Method

- * @param tournamentId ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ id - * @param requestDto ์š”์ฒญํ•œ Dto - * @throws TournamentNotFoundException ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ - * @throws TournamentUpdateException ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ, ๋ณ€๊ฒฝํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์ด ๋ถ€์ ํ•ฉ ํ•  ๋•Œ - * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ && ๊ฒŒ์ž„ ์กด์žฌํ•  ๋•Œ - */ - @Transactional - public Tournament updateTournamentInfo(Long tournamentId, TournamentAdminUpdateRequestDto requestDto) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - checkValidTournamentTime(requestDto.getStartTime(), requestDto.getEndTime()); - checkConflictedTournament(targetTournament.getId(), requestDto.getStartTime(), requestDto.getEndTime()); - checkGameExistence(requestDto.getStartTime(), requestDto.getEndTime()); - - targetTournament.update( - requestDto.getTitle(), - requestDto.getContents(), - requestDto.getStartTime(), - requestDto.getEndTime(), - requestDto.getType(), - TournamentStatus.BEFORE); - return tournamentRepository.save(targetTournament); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ๋งค์„œ๋“œ

- *

ํ† ๋„ˆ๋จผํŠธ๋Š” BEFORE ์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ญ์ œ ๊ฐ€๋Šฅํ•˜๋‹ค.

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @throws TournamentNotFoundException ์ฐพ์„ ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ - * @throws TournamentUpdateException ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ํ† ๋„ˆ๋จผํŠธ ์ผ ๋•Œ - */ - @Transactional - public void deleteTournament(Long tournamentId) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - tournamentRepository.deleteById(tournamentId); - } - - /** - *

๊ด€๋ฆฌ์ž ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์œ ์ € ์ถ”๊ฐ€ ๋งค์„œ๋“œ

- *

ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์ด๋ฏธ ์‹ ์ฒญ ๋˜์–ด ์žˆ์œผ๋ฉด ์ถ”๊ฐ€ ๋ถˆ๊ฐ€

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ - * @param requestDto ์š”์ฒญ dto - * @return TournamentAdminAddUserResponseDto dto ๋ฐ˜ํ™˜ - * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ - * @throws TournamentUpdateException ์ด๋ฏธ ์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋œ ํ† ๋„ˆ๋จผํŠธ - * @throws UserNotFoundException ์œ ์ € ์—†์Œ - * @throws TournamentConflictException ์ด๋ฏธ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ค‘์ธ ์œ ์ € - */ - @Transactional - public TournamentAdminAddUserResponseDto addTournamentUser(Long tournamentId, TournamentAdminAddUserRequestDto requestDto) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - - User targetUser = userRepository.findByIntraId(requestDto.getIntraId()).orElseThrow(UserNotFoundException::new); - - List tournamentList = targetTournament.getTournamentUsers(); - tournamentList.stream().filter(tu->tu.getUser().getIntraId().equals(targetUser.getIntraId())) - .findAny() - .ifPresent(a->{throw new TournamentConflictException(ErrorCode.TOURNAMENT_ALREADY_PARTICIPANT);}); - - TournamentUser tournamentUser = new TournamentUser(targetUser, targetTournament, - tournamentList.size() < Tournament.ALLOWED_JOINED_NUMBER, LocalDateTime.now()); - tournamentUserRepository.save(tournamentUser); - - return new TournamentAdminAddUserResponseDto( - targetUser.getId(), - targetUser.getIntraId(), - tournamentUser.getIsJoined() - ); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์‚ญ์ œ ๋งค์„œ๋“œ

- *

์‚ญ์ œํ•˜๊ณ ์ž ํ•˜๋Š” ์œ ์ €๊ฐ€ ์ฐธ๊ฐ€์ž์ด๊ณ , ํ˜„์žฌ ๋Œ€๊ธฐ์ž๊ฐ€ ์žˆ๋‹ค๋ฉด ์ฐธ๊ฐ€์‹ ์ฒญ์ด ๋น ๋ฅธ ๋Œ€๊ธฐ์ž๋ฅผ ์ฐธ๊ฐ€์ž๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค.

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @param userId ํƒ€๊ฒŸ ์œ ์ € id - * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ - * @throws TournamentUpdateException ์ด๋ฏธ ์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜ ์ข…๋ฃŒ๋œ ํ† ๋„ˆ๋จผํŠธ - * @throws UserNotFoundException ์œ ์ € ์—†์Œ || ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹˜ - */ - @Transactional - public void deleteTournamentUser(Long tournamentId, Long userId) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - User targetUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - - List tournamentUserList = targetTournament.getTournamentUsers(); - TournamentUser targetTournamentUser = tournamentUserList.stream() - .filter(tu->tu.getUser().getId().equals(targetUser.getId())) - .findAny() - .orElseThrow(()->new TournamentNotFoundException(ErrorCode.TOURNAMENT_NOT_PARTICIPANT)); - targetTournamentUser.deleteTournament(); - if (targetTournamentUser.getIsJoined() && tournamentUserList.size() >= Tournament.ALLOWED_JOINED_NUMBER) { - tournamentUserList.get(Tournament.ALLOWED_JOINED_NUMBER - 1).updateIsJoined(true); - } - tournamentUserRepository.delete(targetTournamentUser); - } - - /*** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” ์ƒ์„ฑ Method - * @param tournament ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์— ๋งค์นญ๋  ํ† ๋„ˆ๋จผํŠธ - * @param cnt ํ† ๋„ˆ๋จผํŠธ ์ „์ฒด ๋ผ์šด๋“œ ์ˆ˜ - */ - private void createTournamentGameList(Tournament tournament, int cnt) { - TournamentRound[] rounds = TournamentRound.values(); - while (--cnt >= 0) { - TournamentGame tournamentGame = new TournamentGame(null, tournament, rounds[cnt]); - } - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„ ์ฒดํฌ : - * [ ํ˜„์žฌ ์‹œ๊ฐ„ + ์ตœ์†Œ 2์ผ ], - * [ ํ˜„์žฌ์‹œ๊ฐ„ ๋ณด๋‹ค ๋ฏธ๋ž˜ ], - * [ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ์ข…๋ฃŒ์‹œ๊ฐ„๋ณด๋‹ค ํ˜„์žฌ์‹œ์— ๊ฐ€๊นŒ์›€ ] - * [ ์ง„ํ–‰ ์‹œ๊ฐ„ ์ตœ์†Œ 2์‹œ๊ฐ„ ] - * - * @param startTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @throws InvalidParameterException ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์œผ๋กœ ๋ถ€์ ํ•ฉ ํ•  ๋•Œ - */ - private void checkValidTournamentTime(LocalDateTime startTime, LocalDateTime endTime) { - SlotManagement slotManagement = slotManagementRepository.findCurrent(startTime) - .orElseThrow(SlotNotFoundException::new); - int interval = slotManagement.getGameInterval(); - - if (startTime.isAfter(endTime) || startTime.isEqual(endTime) || - LocalDate.now().plusDays(constantConfig.getAllowedMinimalStartDays()).isAfter(startTime.toLocalDate()) || - startTime.plusHours(Tournament.MINIMUM_TOURNAMENT_DURATION).isAfter(endTime) || - startTime.getMinute() % interval != 0 || endTime.getMinute() % interval != 0) { - throw new TournamentUpdateException(ErrorCode.TOURNAMENT_INVALID_TIME); - } - } - - /** - *

tournamentList ์—์„œ targetTournament์„ ์ œ์™ธํ•œ ํ† ๋„ˆ๋จผํŠธ ์ค‘ ๊ฒน์น˜๋Š” ์‹œ๊ฐ„๋Œ€ ์กด์žฌ ์œ ๋ฌด ํ™•์ธ

- * @param targetTournamentId ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ id - * @param startTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์—…๋ฐ์ดํŠธํ•  ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @throws TournamentConflictException ์—…๋ฐ์ดํŠธ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ๊ฐ„์ด ๊ฒน์น  ๋•Œ - */ - private void checkConflictedTournament(Long targetTournamentId, LocalDateTime startTime, LocalDateTime endTime) { - List tournamentList = tournamentRepository.findAllBetween(startTime, endTime); - for (Tournament tournament : tournamentList) { - if (targetTournamentId.equals(tournament.getId()) || - (!tournament.getStatus().equals(TournamentStatus.BEFORE) && !tournament.getStatus().equals(TournamentStatus.LIVE))) { - continue; - } - throw new TournamentConflictException(); - } - } - - /** - *

ํƒ€๊ฒŸ ์‹œ๊ฐ„ ๋‚ด์— ๊ฒŒ์ž„์ด ์กด์žฌํ•˜๋Š”์ง€ ์ฒดํฌ

- * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ - */ - private void checkGameExistence(LocalDateTime startTime, LocalDateTime endTime) { - gameRepository.findAllBetweenTournament(startTime, endTime).stream() - .findAny() - .ifPresent(a->{throw new TournamentConflictException(ErrorCode.TOURNAMENT_CONFLICT_GAME);}); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ ์กฐํšŒ

- * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id - * @param isJoined ์ฐธ๊ฐ€์ž์ธ์ง€ ๋Œ€๊ธฐ์ž์ธ์ง€ ์—ฌ๋ถ€ - * @return TournamentUserListResponseDto - * @throws TournamentNotFoundException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ - */ - public TournamentUserListResponseDto getTournamentUserList(Long tournamentId, Boolean isJoined) { - Tournament tournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (isJoined == null){ - return new TournamentUserListResponseDto(tournamentUserRepository.findAllByTournament(tournament)); - } else { - return new TournamentUserListResponseDto(tournamentUserRepository.findAllByTournamentAndIsJoined(tournament, isJoined)); - } - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ •๋ณด ์ˆ˜์ •

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด - * @throws TournamentUpdateException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์‹œ์ž‘๋˜์ง€ ์•Š์•˜์„ ๋•Œ - */ - @Transactional - public void updateTournamentGame(Long tournamentId, TournamentGameUpdateRequestDto reqDto) { - if (reqDto.getTeam1().getScore() + reqDto.getTeam2().getScore() > 3 || - reqDto.getTeam1().getScore() + reqDto.getTeam2().getScore() < 2 || - reqDto.getTeam1().getScore() == reqDto.getTeam2().getScore()) { - throw new ScoreNotInvalidException(); - } - Tournament tournament = tournamentRepository.findById(tournamentId) - .orElseThrow(TournamentNotFoundException::new); - if (tournament.getStatus() == TournamentStatus.BEFORE) { - throw new TournamentUpdateException(ErrorCode.TOURNAMENT_IS_BEFORE); - } - TournamentGame tournamentGame = tournament.getTournamentGames().stream(). - filter(t->t.getId().equals(reqDto.getTournamentGameId())).findAny() - .orElseThrow(TournamentGameNotFoundException::new); - Game game = tournamentGame.getGame(); - if (game == null){ - throw new TournamentGameNotFoundException(); - } - if (!canUpdateScore(tournamentGame,reqDto)){ - throw new TournamentUpdateException(ErrorCode.TOURNAMENT_INVALID_SCORE); - } - updateTeamScore(game, reqDto); - TournamentMatchStatus matchStatus = matchTournamentService.checkTournamentGame(game); - TournamentRound nextRound = tournamentGame.getTournamentRound().getNextRound(); - List teamUsers = new ArrayList<>(); - for(Team team : game.getTeams()){ - teamUsers.add(team.getTeamUsers().get(0)); - } - gameService.savePChange(game, teamUsers, teamUsers.get(0).getUser().getId()); - if (POSSIBLE.equals(matchStatus)) { - matchTournamentService.matchGames(tournament, nextRound); - } else if (ALREADY_MATCHED.equals(matchStatus)) { - Game nextMatchedGame = tournamentGameRepository.findByTournamentIdAndTournamentRound(tournament.getId(), nextRound) - .orElseThrow(TournamentGameNotFoundException::new) - .getGame(); - matchTournamentService.updateMatchedGameUser(game, nextMatchedGame); - } - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ˆ˜์ •

- * @param game ์ˆ˜์ •๋  ๊ฒŒ์ž„ - * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด - */ - private void updateTeamScore(Game game, TournamentGameUpdateRequestDto reqDto){ - - List teams = game.getTeams(); - Team team1 = teams.stream().filter(t->t.getId().equals(reqDto.getTeam1().getTeamId())).findAny().orElseThrow(TournamentGameNotFoundException::new); - Team team2 = teams.stream().filter(t->t.getId().equals(reqDto.getTeam2().getTeamId())).findAny().orElseThrow(TournamentGameNotFoundException::new); - team1.updateScore(reqDto.getTeam1().getScore(), reqDto.getTeam1().getScore() > reqDto.getTeam2().getScore()); - team2.updateScore(reqDto.getTeam2().getScore(), reqDto.getTeam2().getScore() > reqDto.getTeam1().getScore()); - if (game.getStatus() == StatusType.LIVE){ - game.updateStatus(); - } - game.updateStatus(); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ˆ˜์ • ๊ฐ€๋Šฅ ์—ฌ๋ถ€

- * @param reqDto ์ˆ˜์ •ํ•  ๊ฒŒ์ž„ ์ •๋ณด - * @return ์ˆ˜์ • ๊ฐ€๋Šฅ ์—ฌ๋ถ€ - */ - private boolean canUpdateScore(TournamentGame tournamentGame, TournamentGameUpdateRequestDto reqDto) { - if (tournamentGame.getGame().getStatus() == StatusType.BEFORE) { - return false; - } - if (reqDto.getNextTournamentGameId() == null){ - return tournamentGame.getTournamentRound() == TournamentRound.THE_FINAL; - } - TournamentGame nextTournamentGame = tournamentGameRepository.findById(reqDto.getNextTournamentGameId()) - .orElseThrow(TournamentGameNotFoundException::new); - if (nextTournamentGame.getGame() == null){ - return true; - } - if (nextTournamentGame.getGame().getStatus() == StatusType.BEFORE){ - return true; - } - return false; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java b/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java deleted file mode 100644 index 69a870aff..000000000 --- a/src/main/java/com/gg/server/admin/user/controller/UserAdminController.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.gg.server.admin.user.controller; - -import com.gg.server.admin.user.dto.*; -import com.gg.server.admin.user.service.UserAdminService; -import com.gg.server.domain.user.exception.UserImageLargeException; -import com.gg.server.domain.user.exception.UserImageTypeException; -import com.gg.server.global.dto.PageRequestDto; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.validation.Valid; -import java.io.IOException; - -@RestController -@AllArgsConstructor -@RequestMapping(value = "/pingpong/admin/users") -public class UserAdminController { - - private final UserAdminService userAdminService; - - @GetMapping - public UserSearchAdminResponseDto userSearchAll(@ModelAttribute @Valid UserSearchAdminRequestDto searchRequestDto) { - Pageable pageable = PageRequest.of(searchRequestDto.getPage() - 1, - searchRequestDto.getSize(), - Sort.by("intraId").ascending()); - if (searchRequestDto.getUserFilter() != null) - return userAdminService.searchByIntraId(pageable, searchRequestDto.getUserFilter()); - else if (searchRequestDto.getIntraId() != null) - return userAdminService.findByPartsOfIntraId(searchRequestDto.getIntraId(), pageable); - else - return userAdminService.searchAll(pageable); - } - - @GetMapping("/{intraId}") - public UserDetailAdminResponseDto userGetDetail(@PathVariable String intraId) { - return userAdminService.getUserDetailByIntraId(intraId); - } - - @PutMapping("/{intraId}") - public ResponseEntity userUpdateDetail(@PathVariable String intraId, - @RequestPart UserUpdateAdminRequestDto updateUserInfo, - @RequestPart(required = false) MultipartFile imgData) throws IOException { - if (imgData != null) { - if (imgData.getSize() > 50000) { - throw new UserImageLargeException(); - } else if (imgData.getContentType() == null || !imgData.getContentType().equals("image/jpeg")) { - throw new UserImageTypeException(); - } - } - userAdminService.updateUserDetail(intraId, updateUserInfo, imgData); - - return ResponseEntity.noContent().build(); - } - - @DeleteMapping("/images/{intraId}") - public ResponseEntity deleteUserProfileImage(@PathVariable String intraId) { - userAdminService.deleteUserProfileImage(intraId); - return ResponseEntity.noContent().build(); - } - - @GetMapping("/delete-list") - public UserImageListAdminResponseDto getUserImageDeleteList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize(), - Sort.by("id").descending()); - return userAdminService.getUserImageDeleteList(pageable); - } - - @GetMapping("/delete-list/{intraId}") - public UserImageListAdminResponseDto getUserImageDeleteListByIntraId(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize()); - return userAdminService.getUserImageDeleteListByIntraId(pageable, intraId); - } - - @GetMapping("/images") - public UserImageListAdminResponseDto getUserImageList(@ModelAttribute @Valid PageRequestDto pageRequestDto) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize()); - return userAdminService.getUserImageList(pageable); - } - - @GetMapping("/images/{intraId}") - public UserImageListAdminResponseDto getUserImage(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize()); - return userAdminService.getUserImageListByIntraId(pageable, intraId); - } - - @GetMapping("/images/current") - public UserImageListAdminResponseDto getUserImageCurrent(@ModelAttribute @Valid PageRequestDto pageRequestDto) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize()); - return userAdminService.getUserImageCurrent(pageable); - } - - @GetMapping("/images/current/{intraId}") - public UserImageListAdminResponseDto getUserImageCurrentByIntraId(@ModelAttribute @Valid PageRequestDto pageRequestDto, @PathVariable String intraId) { - Pageable pageable = PageRequest.of(pageRequestDto.getPage() - 1, - pageRequestDto.getSize()); - return userAdminService.getUserImageCurrentByIntraId(pageable, intraId); - } -} diff --git a/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java b/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java deleted file mode 100644 index 3eb4712ea..000000000 --- a/src/main/java/com/gg/server/admin/user/data/UserAdminRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.admin.user.data; - -import com.gg.server.domain.user.data.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserAdminRepository extends JpaRepository { - Optional findByIntraId(String intraId); - Page findByIntraIdContains(Pageable pageable, String intraId); - Page findByIntraId(Pageable pageable, String intraId); - Page findAll(Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java b/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java deleted file mode 100644 index c18eb09dd..000000000 --- a/src/main/java/com/gg/server/admin/user/data/UserImageAdminRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.admin.user.data; - -import com.gg.server.domain.user.data.User; -import org.springframework.data.repository.query.Param; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import com.gg.server.domain.user.data.UserImage; -import org.springframework.data.jpa.repository.Query; - - -import java.util.Optional; - -public interface UserImageAdminRepository extends JpaRepository{ - Optional findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(User user); - - Optional findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(User user); - - Page findAllByDeletedAtNotNullOrderByDeletedAtDesc(Pageable pageable); - - @Query(value = "SELECT ui FROM UserImage ui WHERE ui.user.id = :user_id " + - "AND ui.deletedAt != NULL ORDER BY ui.deletedAt DESC") - Page findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc(@Param("user_id") Long userId, Pageable pageable); - - @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + - "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + - ") ORDER BY ui.createdAt DESC") - Page findAllChangedOrderByCreatedAtDesc(Pageable pageable); - - @Query(value = "SELECT ui FROM UserImage ui WHERE ui.id NOT IN (" + - "SELECT MIN(ui.id) FROM UserImage ui GROUP BY ui.user.id" + - ") AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") - Page findAllByUserOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); - - @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS TRUE" + - " ORDER BY ui.createdAt DESC") - Page findAllByIsCurrentTrueOrderByCreatedAtDesc(Pageable pageable); - - @Query(value = "SELECT ui FROM UserImage ui WHERE ui.isCurrent IS True" + - " AND ui.user.id = :user_id ORDER BY ui.createdAt DESC") - Page findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc(@Param("user_id") Long userId, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java deleted file mode 100644 index 521f0c36e..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserAdminDto.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class UserAdminDto { - private Long id; - private String intraId; - private String eMail; - private String imageUri; - private RacketType racketType; - private RoleType roleType; - private Integer totalExp; - private SnsType snsNotiOpt; - - static public UserAdminDto from (User user, UserImage userImage) { - UserAdminDto userDto; - if (user == null) { - userDto = null; - } else { - userDto = UserAdminDto.builder() - .id(user.getId()) - .intraId(user.getIntraId()) - .eMail(user.getEMail()) - .imageUri(userImage.getImageUri()) - .racketType(user.getRacketType()) - .roleType(user.getRoleType()) - .totalExp(user.getTotalExp()) - .snsNotiOpt(user.getSnsNotiOpt()) - .build(); - } - return userDto; - } - - @Override - public String toString() { - return "UserDto{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", eMail='" + eMail + '\'' + - ", imageUri='" + imageUri + '\'' + - ", racketType=" + racketType + '\'' + - ", roleType=" + roleType + '\'' + - ", totalExp=" + totalExp + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java deleted file mode 100644 index 819134d75..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserDetailAdminResponseDto.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.user.data.User; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserDetailAdminResponseDto { - private Long userId; - private String intraId; - private String userImageUri; - private String racketType; - private String statusMessage; - private Integer wins; - private Integer losses; - private Integer ppp; - private String email; - private String roleType; - private Integer exp; - private Integer coin; - - public UserDetailAdminResponseDto(User user, RankRedis rank) { - this.userId = user.getId(); - this.intraId = user.getIntraId(); - this.userImageUri = user.getImageUri(); - this.racketType = user.getRacketType().getCode(); - this.statusMessage = rank.getStatusMessage(); - this.wins = rank.getWins(); - this.losses = rank.getLosses(); - this.ppp = rank.getPpp(); - this.email = user.getEMail(); - this.roleType = user.getRoleType().getKey(); - this.exp = user.getTotalExp(); - this.coin = user.getGgCoin(); - } - - public UserDetailAdminResponseDto(User user) { - this.userId = user.getId(); - this.intraId = user.getIntraId(); - this.userImageUri = user.getImageUri(); - this.racketType = user.getRacketType().getCode(); - this.statusMessage = ""; - this.wins = 0; - this.losses = 0; - this.ppp = 0; - this.email = user.getEMail() == null ? "" : user.getEMail(); - this.roleType = user.getRoleType().getKey(); - this.exp = user.getTotalExp(); - this.coin = user.getGgCoin(); - } - - @Override - public String toString() { - return "UserDetailResponseDto{" + - "intraId='" + intraId + '\'' + - ", userImageUri='" + userImageUri + '\'' + - ", racketType='" + racketType + '\'' + - ", statusMessage='" + statusMessage + '\'' + - ", wins='" + wins.toString() + '\'' + - ", losses='" + losses.toString() + '\'' + - ", ppp='" + ppp.toString() + '\'' + - ", email='" + email + '\'' + - ", roleType='" + roleType + '\'' + - ", coin='" + coin + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java deleted file mode 100644 index a0a90fda1..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserImageAdminDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.data.UserImage; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserImageAdminDto { - Long id; - String userIntraId; - String imageUri; - LocalDateTime createdAt; - LocalDateTime deletedAt; - Boolean isCurrent; - - public UserImageAdminDto(UserImage userImage) { - this.id = userImage.getId(); - this.userIntraId = userImage.getUser().getIntraId(); - this.imageUri = userImage.getImageUri(); - this.createdAt = userImage.getCreatedAt(); - this.deletedAt = userImage.getDeletedAt(); - this.isCurrent = userImage.getIsCurrent(); - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java deleted file mode 100644 index 1c07d01a2..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserImageListAdminResponseDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserImageListAdminResponseDto { - private List userImageList; - private int totalPage; -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java deleted file mode 100644 index 7acb80653..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RoleType; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UserSearchAdminDto { - private Long id; - private String intraId; - private String statusMessage; - private RoleType roleType; - - public UserSearchAdminDto (User user, String statusMessage) { - this.id = user.getId(); - this.intraId = user.getIntraId(); - this.statusMessage = statusMessage; - this.roleType = user.getRoleType(); - } - - @Override - public String toString() { - return "{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", statusMessage='" + statusMessage + '\'' + - ", roleType=" + roleType + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminRequestDto.java b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminRequestDto.java deleted file mode 100644 index bcde2e7ff..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminRequestDto.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - - -@Getter -@Setter -public class UserSearchAdminRequestDto extends PageRequestDto { - private String intraId; - private String userFilter; - - public UserSearchAdminRequestDto(Integer page, Integer size, String intraId, String userFilter) { - super(page, size); - this.intraId = intraId; - this.userFilter = userFilter; - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java b/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java deleted file mode 100644 index c0fb57ef6..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserSearchAdminResponseDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.admin.user.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; -import java.util.stream.Collectors; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class UserSearchAdminResponseDto { - private List userSearchAdminDtos; - private Integer totalPage; - - public void filterUser(String filterString) { - if (filterString == null) - return ; - this.userSearchAdminDtos = this.userSearchAdminDtos.stream() - .filter(userSearchAdminDto -> userSearchAdminDto.getIntraId().equals(filterString)) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java b/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java deleted file mode 100644 index 7175be106..000000000 --- a/src/main/java/com/gg/server/admin/user/dto/UserUpdateAdminRequestDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.admin.user.dto; - -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class UserUpdateAdminRequestDto { - private RacketType racketType; - private String statusMessage; - private Integer wins; - private Integer losses; - private Integer ppp; - private String email; - private String roleType; - private Integer coin; - - @Override - public String toString() { - return "UserUpdateRequestAdminDto{" + '\'' + - ", racketType=" + racketType + - ", statusMessage='" + statusMessage + '\'' + - ", wins='" + wins + '\'' + - ", losses'" + losses + '\'' + - ", ppp='" + ppp + '\'' + - ", email='" + email + '\'' + - ", roleType='" + roleType + '\'' + - ", coin='" + coin + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/admin/user/service/UserAdminService.java b/src/main/java/com/gg/server/admin/user/service/UserAdminService.java deleted file mode 100644 index 65ce4f42d..000000000 --- a/src/main/java/com/gg/server/admin/user/service/UserAdminService.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.gg.server.admin.user.service; -import com.gg.server.admin.rank.service.RankRedisAdminService; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.admin.user.data.UserImageAdminRepository; -import com.gg.server.admin.user.dto.*; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.service.UserFindService; -import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -@Service -@AllArgsConstructor -public class UserAdminService { - - private final UserAdminRepository userAdminRepository; - private final SeasonAdminRepository seasonAdminRepository; - private final RankRepository rankRepository; - private final RankRedisRepository rankRedisRepository; - private final RankRedisAdminService rankRedisAdminService; - private final AsyncNewUserImageUploader asyncNewUserImageUploader; - private final UserFindService userFindService; - private final UserImageAdminRepository userImageAdminRepository; - - @Transactional(readOnly = true) - public UserSearchAdminResponseDto searchAll(Pageable pageable) { - Page userPage = userAdminRepository.findAll(pageable); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserSearchAdminResponseDto searchByIntraId(Pageable pageable, String intraId) { - Page userPage = userAdminRepository.findByIntraId(pageable, intraId); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - /* ๋ฌธ์ž์—ด์„ ํฌํ•จํ•˜๋Š” intraId๋ฅผ ๊ฐ€์ง„ ์œ ์ € ์ฐพ๊ธฐ */ - @Transactional(readOnly = true) - public UserSearchAdminResponseDto findByPartsOfIntraId(String intraId, Pageable pageable) { - Page userPage = userAdminRepository.findByIntraIdContains(pageable, intraId); - List userSearchAdminDtos = new ArrayList(); - for (User user : userPage.getContent()) - userSearchAdminDtos.add(new UserSearchAdminDto(user, userFindService.getUserStatusMessage(user))); - return new UserSearchAdminResponseDto(userSearchAdminDtos, userPage.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserDetailAdminResponseDto getUserDetailByIntraId(String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); - try { - RankRedis userCurrRank = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeason.getId()), - user.getId()); - return new UserDetailAdminResponseDto(user, userCurrRank); - } catch (RedisDataNotFoundException e){ - return new UserDetailAdminResponseDto(user); - } - } - - @Transactional - public void updateUserDetail(String intraId, - UserUpdateAdminRequestDto userUpdateAdminRequestDto, - MultipartFile userImageFile) throws IOException{ - Season currSeason = seasonAdminRepository.findCurrentSeason(LocalDateTime.now()).orElseThrow(() -> new SeasonNotFoundException()); - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - - user.modifyUserDetail(userUpdateAdminRequestDto); - if (userImageFile != null) - asyncNewUserImageUploader.update(intraId, userImageFile); - updateUserRank(user.getId(), currSeason.getId(), userUpdateAdminRequestDto); - } - - private void updateUserRank(Long userId, Long currSeasonId, UserUpdateAdminRequestDto updateReq) { - Rank userCurrRank = rankRepository.findByUserIdAndSeasonId(userId, currSeasonId).orElseThrow(() -> new RankNotFoundException()); - RankRedis userCurrRankRedis = rankRedisRepository.findRankByUserId(RedisKeyManager.getHashKey(currSeasonId), - userId); - - userCurrRank.modifyUserRank(updateReq); - userCurrRank.setStatusMessage(updateReq.getStatusMessage()); - - userCurrRankRedis.changedRank(updateReq.getPpp(), - updateReq.getWins(), - updateReq.getLosses()); - userCurrRankRedis.setStatusMessage(updateReq.getStatusMessage()); - rankRedisAdminService.updateRankUser(RedisKeyManager.getHashKey(currSeasonId), - RedisKeyManager.getZSetKey(currSeasonId), - userId, userCurrRankRedis); - } - - public String getUserImageToString(User user) { - UserImage userImage = userImageAdminRepository.findTopByUserAndDeletedAtIsNullOrderByCreatedAtDesc(user).orElse(null); - if (userImage == null) - return "null"; - else { - userImage.updateIsCurrent(); - return userImage.getImageUri(); - } - } - - @Transactional - public void deleteUserProfileImage(String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - UserImage userImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); - userImage.updateDeletedAt(LocalDateTime.now()); - String userImageUri = getUserImageToString(user); - user.updateImageUri(userImageUri); - } - - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageDeleteList(Pageable pageable) { - Page userImagePage = userImageAdminRepository.findAllByDeletedAtNotNullOrderByDeletedAtDesc(pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageDeleteListByIntraId(Pageable pageable, String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - Page userImagePage = userImageAdminRepository.findAllByUserAndDeletedAtNotNullOrderByDeletedAtDesc(user.getId(), pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageList(Pageable pageable) { - Page userImagePage = userImageAdminRepository.findAllChangedOrderByCreatedAtDesc(pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageListByIntraId(Pageable pageable, String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - Page userImagePage = userImageAdminRepository.findAllByUserOrderByCreatedAtDesc(user.getId(), pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageCurrent(Pageable pageable) { - Page userImagePage = userImageAdminRepository.findAllByIsCurrentTrueOrderByCreatedAtDesc(pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } - - @Transactional(readOnly = true) - public UserImageListAdminResponseDto getUserImageCurrentByIntraId(Pageable pageable, String intraId) { - User user = userAdminRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - Page userImagePage = userImageAdminRepository.findAllByUserAndIsCurrentTrueOrderByCreatedAtDesc(user.getId(), pageable); - Page userImageAdminDto = userImagePage.map(UserImageAdminDto::new); - - return new UserImageListAdminResponseDto(userImageAdminDto.getContent(), userImageAdminDto.getTotalPages()); - } -} diff --git a/src/main/java/com/gg/server/domain/announcement/controller/AnnouncementController.java b/src/main/java/com/gg/server/domain/announcement/controller/AnnouncementController.java deleted file mode 100644 index 53359d37f..000000000 --- a/src/main/java/com/gg/server/domain/announcement/controller/AnnouncementController.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.announcement.controller; - -import com.gg.server.domain.announcement.dto.AnnouncementResponseDto; -import com.gg.server.domain.announcement.service.AnnouncementService; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping(value = "/pingpong/announcement") -public class AnnouncementController { - private final AnnouncementService announcementService; - - @GetMapping - public AnnouncementResponseDto findLastAnnounceContent() { - return new AnnouncementResponseDto(announcementService.findLastAnnouncement().getContent()); - } -} diff --git a/src/main/java/com/gg/server/domain/announcement/data/Announcement.java b/src/main/java/com/gg/server/domain/announcement/data/Announcement.java deleted file mode 100644 index 6f6532a4b..000000000 --- a/src/main/java/com/gg/server/domain/announcement/data/Announcement.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gg.server.domain.announcement.data; - -import com.gg.server.admin.announcement.dto.AnnouncementAdminAddDto; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class Announcement extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @NotNull - @Column(name = "content", length=1000) - private String content; - @NotNull - @Column(name = "creator_intra_id", length = 30) - private String creatorIntraId; - @Column(name = "deleter_intra_id", length = 30) - private String deleterIntraId; - @Column(name = "deleted_at") - private LocalDateTime deletedAt; - - @Builder - public Announcement(String content, String creatorIntraId){ - this.content = content; - this.creatorIntraId = creatorIntraId; - } - - public void update(String deleterIntraId, LocalDateTime deletedAt) { - this.deleterIntraId = deleterIntraId; - this.deletedAt = deletedAt; - } - - static public Announcement from(AnnouncementAdminAddDto addDto) { - return Announcement.builder() - .content(addDto.getContent()) - .creatorIntraId(addDto.getCreatorIntraId()) - .build(); - } -} diff --git a/src/main/java/com/gg/server/domain/announcement/data/AnnouncementRepository.java b/src/main/java/com/gg/server/domain/announcement/data/AnnouncementRepository.java deleted file mode 100644 index 60e58d2b7..000000000 --- a/src/main/java/com/gg/server/domain/announcement/data/AnnouncementRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.domain.announcement.data; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface AnnouncementRepository extends JpaRepository { - Optional findFirstByOrderByIdDesc(); -} diff --git a/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementDto.java b/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementDto.java deleted file mode 100644 index 32aeefade..000000000 --- a/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.domain.announcement.dto; - -import com.gg.server.domain.announcement.data.Announcement; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class AnnouncementDto { - private String content; - - public static AnnouncementDto from(Announcement announcement) { - return new AnnouncementDto(announcement.getContent()); - } -} diff --git a/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementResponseDto.java b/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementResponseDto.java deleted file mode 100644 index c6d9a5734..000000000 --- a/src/main/java/com/gg/server/domain/announcement/dto/AnnouncementResponseDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.announcement.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class AnnouncementResponseDto { - private String content; -} diff --git a/src/main/java/com/gg/server/domain/announcement/exception/AnnounceDupException.java b/src/main/java/com/gg/server/domain/announcement/exception/AnnounceDupException.java deleted file mode 100644 index 7f2138ad8..000000000 --- a/src/main/java/com/gg/server/domain/announcement/exception/AnnounceDupException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.announcement.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class AnnounceDupException extends DuplicationException { - public AnnounceDupException() { - super(ErrorCode.ANNOUNCE_DUPLICATE.getMessage(), ErrorCode.ANNOUNCE_DUPLICATE); - } -} diff --git a/src/main/java/com/gg/server/domain/announcement/exception/AnnounceNotFoundException.java b/src/main/java/com/gg/server/domain/announcement/exception/AnnounceNotFoundException.java deleted file mode 100644 index 888897093..000000000 --- a/src/main/java/com/gg/server/domain/announcement/exception/AnnounceNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.announcement.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; - -public class AnnounceNotFoundException extends CustomRuntimeException { - public AnnounceNotFoundException() { - super(ErrorCode.ANNOUNCE_NOT_FOUND.getMessage(), ErrorCode.ANNOUNCE_NOT_FOUND); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/announcement/service/AnnouncementService.java b/src/main/java/com/gg/server/domain/announcement/service/AnnouncementService.java deleted file mode 100644 index 291ff7feb..000000000 --- a/src/main/java/com/gg/server/domain/announcement/service/AnnouncementService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.domain.announcement.service; - -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.announcement.data.AnnouncementRepository; -import com.gg.server.domain.announcement.dto.AnnouncementDto; -import com.gg.server.domain.announcement.exception.AnnounceNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class AnnouncementService { - private final AnnouncementRepository announcementRepository; - - @Transactional(readOnly = true) - public AnnouncementDto findLastAnnouncement() { - Announcement announcement = announcementRepository.findFirstByOrderByIdDesc().orElseThrow(() -> new AnnounceNotFoundException()); - if (announcement.getDeletedAt() != null) - return new AnnouncementDto(""); - - return AnnouncementDto.from(announcement); - } -} diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java b/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java deleted file mode 100644 index 96f746de4..000000000 --- a/src/main/java/com/gg/server/domain/coin/data/CoinHistory.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.gg.server.domain.coin.data; - -import com.gg.server.domain.user.data.User; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.CreatedDate; - -import javax.persistence.*; -import java.time.LocalDateTime; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class CoinHistory { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @Column(name = "history", length = 30) - private String history; - - @Column(name = "amount") - private int amount; - - @CreatedDate - @Column(name = "createdAt", updatable = false, nullable = false) - private LocalDateTime createdAt; - - public CoinHistory(User user, String history, int amount) { - this.user = user; - this.history = history; - this.amount = amount; - this.createdAt = LocalDateTime.now(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java b/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java deleted file mode 100644 index 358b6c162..000000000 --- a/src/main/java/com/gg/server/domain/coin/data/CoinHistoryRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.domain.coin.data; - -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.user.data.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -public interface CoinHistoryRepository extends JpaRepository { - @Query("SELECT CASE WHEN COUNT(ch) > 0 THEN true ELSE false END FROM CoinHistory ch WHERE ch.user = :user AND ch.history = :history AND ch.createdAt >= :startOfDay AND ch.createdAt < :endOfDay") - boolean existsUserAttendedCheckToday(@Param("user") User user, @Param("history") String history, @Param("startOfDay") LocalDateTime startOfDay, @Param("endOfDay") LocalDateTime endOfDay); - - Optional findFirstByOrderByIdDesc(); - - List findAllByUserOrderByIdDesc(User user); - - Page findAllByUserOrderByIdDesc(User user, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java b/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java deleted file mode 100644 index 28c884afd..000000000 --- a/src/main/java/com/gg/server/domain/coin/data/CoinPolicy.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gg.server.domain.coin.data; - -import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; -import com.gg.server.domain.user.data.User; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.CreatedDate; - -import javax.persistence.*; -import java.time.LocalDateTime; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class CoinPolicy { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @Column(name = "attendance") - private int attendance; - - @Column(name = "normal") - private int normal; - - @Column(name = "rankWin") - private int rankWin; - - @Column(name = "rankLose") - private int rankLose; - - @CreatedDate - @Column(name = "createdAt", updatable = false, nullable = false) - private LocalDateTime createdAt; - - @Builder - public CoinPolicy(User user, int attendance, int normal, int rankWin, int rankLose) { - this.user = user; - this.attendance = attendance; - this.normal = normal; - this.rankWin = rankWin; - this.rankLose = rankLose; - this.createdAt = LocalDateTime.now(); - } - - static public CoinPolicy from(User user, CoinPolicyAdminAddDto addDto) { - return CoinPolicy.builder() - .user(user) - .attendance(addDto.getAttendance()) - .normal(addDto.getNormal()) - .rankWin(addDto.getRankWin()) - .rankLose(addDto.getRankLose()) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java b/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java deleted file mode 100644 index 6e3eb8a77..000000000 --- a/src/main/java/com/gg/server/domain/coin/data/CoinPolicyRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.coin.data; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface CoinPolicyRepository extends JpaRepository { - Optional findTopByOrderByCreatedAtDesc(); - -} diff --git a/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java b/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java deleted file mode 100644 index 4030c370b..000000000 --- a/src/main/java/com/gg/server/domain/coin/dto/UserGameCoinResultDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.domain.coin.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UserGameCoinResultDto { - private int beforeCoin; - private int afterCoin; - private int coinIncrement; - - public UserGameCoinResultDto(int afterCoin, int coinIncrement) { - this.beforeCoin = afterCoin - coinIncrement; - this.afterCoin = afterCoin; - this.coinIncrement = coinIncrement; - } -} diff --git a/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java b/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java deleted file mode 100644 index c8e0710c5..000000000 --- a/src/main/java/com/gg/server/domain/coin/exception/CoinHistoryNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.coin.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; - -public class CoinHistoryNotFoundException extends CustomRuntimeException { - public CoinHistoryNotFoundException() { - super(ErrorCode.COIN_HISTORY_NOT_FOUND.getMessage(), ErrorCode.COIN_HISTORY_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java b/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java deleted file mode 100644 index 5e857eeab..000000000 --- a/src/main/java/com/gg/server/domain/coin/exception/CoinPolicyNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.coin.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; - -public class CoinPolicyNotFoundException extends CustomRuntimeException { - public CoinPolicyNotFoundException() { - super(ErrorCode.CoinPolicy_NOT_FOUND.getMessage(), ErrorCode.CoinPolicy_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java b/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java deleted file mode 100644 index 36962a1f9..000000000 --- a/src/main/java/com/gg/server/domain/coin/service/CoinHistoryService.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.gg.server.domain.coin.service; - -import com.gg.server.domain.coin.data.CoinHistory; -import com.gg.server.domain.coin.data.CoinHistoryRepository; -import com.gg.server.domain.coin.data.CoinPolicyRepository; -import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; -import com.gg.server.domain.coin.type.HistoryType; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.user.data.User; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -public class CoinHistoryService { - private final CoinHistoryRepository coinHistoryRepository; - private final CoinPolicyRepository coinPolicyRepository; - - @Transactional - public void addAttendanceCoinHistory(User user) { - int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getAttendance(); - addCoinHistory(new CoinHistory(user, HistoryType.ATTENDANCECOIN.getHistory(), amount)); - } - - @Transactional - public void addPurchaseItemCoinHistory(User user, Item item, Integer price) { - addCoinHistory(new CoinHistory(user, item.getName() + " ๊ตฌ๋งค", price * (-1))); - } - - @Transactional - public void addGiftItemCoinHistory(User user, User giftTarget, Item item, Integer price) { - addCoinHistory(new CoinHistory(user, giftTarget.getIntraId() + "์—๊ฒŒ " + item.getName() + " ์„ ๋ฌผ", price * (-1))); - } - - @Transactional - public void addNormalCoin(User user) { - int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal(); - addCoinHistory(new CoinHistory(user, HistoryType.NORMAL.getHistory(), amount)); - } - - @Transactional - public int addRankWinCoin(User user) { - int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankWin(); - addCoinHistory(new CoinHistory(user, HistoryType.RANKWIN.getHistory(), amount)); - return amount; - } - - @Transactional - public int addRankLoseCoin(User user) { - int amount = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankLose(); - if (amount == 0) - return amount; - addCoinHistory(new CoinHistory(user, HistoryType.RANKLOSE.getHistory(), amount)); - return amount; - } - - @Transactional(readOnly = true) - public boolean hasAttendedToday(User user) { - LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); - LocalDateTime endOfDay = startOfDay.plusDays(1); - return coinHistoryRepository.existsUserAttendedCheckToday( - user, HistoryType.ATTENDANCECOIN.getHistory(), startOfDay, endOfDay); - } - - public void addCoinHistory(CoinHistory coinHistory) { - coinHistoryRepository.save(coinHistory); - } - -} diff --git a/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java b/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java deleted file mode 100644 index b30dbc385..000000000 --- a/src/main/java/com/gg/server/domain/coin/service/UserCoinChangeService.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.gg.server.domain.coin.service; - -import com.gg.server.domain.coin.data.CoinPolicyRepository; -import com.gg.server.domain.coin.dto.UserGameCoinResultDto; -import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; -import com.gg.server.domain.game.service.GameFindService; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserAlreadyAttendanceException; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class UserCoinChangeService { - private final CoinPolicyRepository coinPolicyRepository; - private final CoinHistoryService coinHistoryService; - private final UserRepository userRepository; - private final GameFindService gameFindService; - - @Transactional - public int addAttendanceCoin(User user){ - if (coinHistoryService.hasAttendedToday(user)) - throw new UserAlreadyAttendanceException(); - int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(CoinPolicyNotFoundException::new).getAttendance(); - user.addGgCoin(coinIncrement); - coinHistoryService.addAttendanceCoinHistory(user); - return coinIncrement; - } - - @Transactional - public void purchaseItemCoin(Item item, Integer price, Long userId){ - - User user = userRepository.findById(userId) - .orElseThrow(UserNotFoundException::new); - - user.payGgCoin(price); - - coinHistoryService.addPurchaseItemCoinHistory(user, item, price); - } - - @Transactional - public void giftItemCoin(Item item, Integer price, User user, User giftTarget){ - user.payGgCoin(price); - - coinHistoryService.addGiftItemCoinHistory(user, giftTarget, item, price); - } - - - @Transactional - public UserGameCoinResultDto addNormalGameCoin(Long userId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - int coinIncrement = coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(CoinPolicyNotFoundException::new).getNormal(); - - user.addGgCoin(coinIncrement); - coinHistoryService.addNormalCoin(user); - return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); - } - - @Transactional - public UserGameCoinResultDto addRankGameCoin(Long gameId, Long userId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - int coinIncrement; - - if (userIsWinner(gameId, user)) - coinIncrement = coinHistoryService.addRankWinCoin(user); - else - coinIncrement = coinHistoryService.addRankLoseCoin(user); - - user.addGgCoin(coinIncrement); - return new UserGameCoinResultDto(user.getGgCoin(), coinIncrement); - } - - private boolean userIsWinner(Long gameId, User user) { - List teams = gameFindService.findByGameId(gameId).getTeams(); - - for(Team team: teams) { - for (TeamUser teamUser : team.getTeamUsers()){ - if (teamUser.getUser().getId() == user.getId() && team.getWin()) - return true; - else if (teamUser.getUser().getId() == user.getId() && !team.getWin()) - return false; - } - } - - return false; - } -} diff --git a/src/main/java/com/gg/server/domain/coin/type/HistoryType.java b/src/main/java/com/gg/server/domain/coin/type/HistoryType.java deleted file mode 100644 index 8144c712a..000000000 --- a/src/main/java/com/gg/server/domain/coin/type/HistoryType.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.coin.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum HistoryType { - - ATTENDANCECOIN("์ถœ์„"), - NORMAL("์ผ๋ฐ˜์ „ ์ฐธ๊ฐ€"), - RANKWIN("๋žญํฌ์ „ ์Šน๋ฆฌ"), - RANKLOSE("๋žญํฌ์ „ ํŒจ๋ฐฐ"); - - private final String history; -} diff --git a/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java b/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java deleted file mode 100644 index b18bd2edd..000000000 --- a/src/main/java/com/gg/server/domain/feedback/controller/FeedbackController.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.feedback.controller; - - -import com.gg.server.domain.feedback.dto.FeedbackRequestDto; -import com.gg.server.domain.feedback.service.FeedbackService; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping(value = "/pingpong") -public class FeedbackController { - private final FeedbackService feedbackService; - private final UserRepository userRepository; - - @PostMapping(value = "/feedback") - public ResponseEntity feedbackSave(@Valid @RequestBody FeedbackRequestDto feedbackRequestDto, - @Parameter(hidden = true) @Login UserDto user) { - feedbackService.addFeedback(feedbackRequestDto, user.getId()); - return new ResponseEntity(HttpStatus.CREATED); - } -} diff --git a/src/main/java/com/gg/server/domain/feedback/data/Feedback.java b/src/main/java/com/gg/server/domain/feedback/data/Feedback.java deleted file mode 100644 index f70d61947..000000000 --- a/src/main/java/com/gg/server/domain/feedback/data/Feedback.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.domain.feedback.data; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@Entity -@Getter -public class Feedback extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "category", length = 15) - private FeedbackType category; - - @NotNull - @Column(name = "content", length = 600) - private String content; - - @Setter - @NotNull - @Column(name = "is_solved") - private Boolean isSolved; - - @Builder - public Feedback(User user, FeedbackType category, String content) { - this.user = user; - this.category = category; - this.content = content; - this.isSolved = false; - } -} diff --git a/src/main/java/com/gg/server/domain/feedback/data/FeedbackRepository.java b/src/main/java/com/gg/server/domain/feedback/data/FeedbackRepository.java deleted file mode 100644 index 08a4a89e6..000000000 --- a/src/main/java/com/gg/server/domain/feedback/data/FeedbackRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gg.server.domain.feedback.data; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface FeedbackRepository extends JpaRepository { - Feedback findFirstByOrderByIdDesc(); -} diff --git a/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java b/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java deleted file mode 100644 index 3bccca5d5..000000000 --- a/src/main/java/com/gg/server/domain/feedback/dto/FeedbackRequestDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.domain.feedback.dto; - -import com.gg.server.domain.feedback.type.FeedbackType; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -public class FeedbackRequestDto { - @NotNull(message = "plz. not null FeedbackType") - private FeedbackType category; - @NotNull(message = "plz. not null content") - @Length(max = 600, message = "plz. maxSizeMessage 600") - private String content; - - @Builder - public FeedbackRequestDto(FeedbackType category, String content) { - this.category = category; - this.content = content; - } -} diff --git a/src/main/java/com/gg/server/domain/feedback/exception/FeedbackNotFoundException.java b/src/main/java/com/gg/server/domain/feedback/exception/FeedbackNotFoundException.java deleted file mode 100644 index cc1375d6f..000000000 --- a/src/main/java/com/gg/server/domain/feedback/exception/FeedbackNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.feedback.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; - -public class FeedbackNotFoundException extends CustomRuntimeException { - public FeedbackNotFoundException() { - super(ErrorCode.FEEDBACK_NOT_FOUND.getMessage(), ErrorCode.FEEDBACK_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java b/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java deleted file mode 100644 index 22df6d097..000000000 --- a/src/main/java/com/gg/server/domain/feedback/service/FeedbackService.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.domain.feedback.service; - -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.data.FeedbackRepository; -import com.gg.server.domain.feedback.dto.FeedbackRequestDto; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class FeedbackService { - private final FeedbackRepository feedbackRepository; - private final UserRepository userRepository; - - @Transactional - public void addFeedback(FeedbackRequestDto feedbackRequestDto, Long userId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - - Feedback feedback = new Feedback(user, feedbackRequestDto.getCategory(), feedbackRequestDto.getContent()); - feedbackRepository.save(feedback); - } -} diff --git a/src/main/java/com/gg/server/domain/feedback/type/FeedbackType.java b/src/main/java/com/gg/server/domain/feedback/type/FeedbackType.java deleted file mode 100644 index bc63018df..000000000 --- a/src/main/java/com/gg/server/domain/feedback/type/FeedbackType.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.feedback.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum FeedbackType { - BUG("bug"), - GAMERESULT("gameresult"), - COMPLAINT("complaint"), - CHEERS("cheers"), - OPINION("opinion"), - ETC("etc"); - - private final String code; - - @JsonCreator - public static FeedbackType getEnumFromValue(String value) { - for(FeedbackType e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/game/GameController.java b/src/main/java/com/gg/server/domain/game/GameController.java deleted file mode 100644 index 542940400..000000000 --- a/src/main/java/com/gg/server/domain/game/GameController.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.gg.server.domain.game; - -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GamePChangeResultResDto; -import com.gg.server.domain.game.dto.GameTeamInfo; -import com.gg.server.domain.game.dto.request.GameListReqDto; -import com.gg.server.domain.game.dto.request.NormalGameListReqDto; -import com.gg.server.domain.game.dto.request.NormalResultReqDto; -import com.gg.server.domain.game.dto.request.RankGameListReqDto; -import com.gg.server.domain.game.dto.request.RankResultReqDto; -import com.gg.server.domain.game.dto.request.TournamentResultReqDto; -import com.gg.server.domain.game.exception.ScoreNotMatchedException; -import com.gg.server.domain.game.service.GameFindService; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import com.gg.server.global.exception.custom.InvalidParameterException; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import javax.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -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; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/games") -public class GameController { - private final GameService gameService; - private final GameFindService gameFindService; - private final RankRedisService rankRedisService; - - /** - * ์ „์ฒด ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ API - * @param gameReq - page size [status] [intraId] - *

status๊ฐ€ "LIVE" -> ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„๋„ ํฌํ•จํ•ด์„œ ์กฐํšŒ

- *

null -> ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„๋งŒ ์กฐํšŒ

- * @return GameListResDto - games isLast - * @throws InvalidParameterException - status๊ฐ€ "LIVE"๊ฐ€ ์•„๋‹Œ๋ฐ ๋‹ค๋ฅธ ๊ฐ’์ด ๋“ค์–ด์˜ฌ ๊ฒฝ์šฐ - */ - @GetMapping - GameListResDto allGameList(@Valid GameListReqDto gameReq) { - if (gameReq.getStatus() != null && !gameReq.getStatus().name().equals("LIVE")) { - throw new InvalidParameterException("status not valid", ErrorCode.VALID_FAILED); - } - Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), Sort.by(Sort.Direction.DESC, "startTime")); - if (gameReq.getIntraId() != null) { - return gameFindService.allGameListUser(pageable, gameReq.getIntraId(), gameReq.getStatus() != null ? gameReq.getStatus().name() : "NULL"); - } - return gameFindService.allGameList(pageable, gameReq.getStatus() != null ? gameReq.getStatus().name() : "NULL"); - } - - @GetMapping("/normal") - GameListResDto normalGameList(@ModelAttribute @Valid NormalGameListReqDto gameReq) { - Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), Sort.by(Sort.Direction.DESC, "startTime")); - if (gameReq.getIntraId() == null) { - return gameFindService.getNormalGameList(pageable); - } - return gameFindService.normalGameListByIntra(pageable, gameReq.getIntraId()); - } - - @GetMapping("/rank") - GameListResDto rankGameList(@ModelAttribute @Valid RankGameListReqDto gameReq) { - Pageable pageable = PageRequest.of(gameReq.getPage() - 1, gameReq.getSize(), Sort.by(Sort.Direction.DESC, "startTime")); - if (gameReq.getIntraId() == null) { - return gameFindService.rankGameList(pageable, gameReq.getSeasonId()); - } - return gameFindService.rankGameListByIntra(pageable, gameReq.getSeasonId(), gameReq.getIntraId()); - } - - @GetMapping("/{gameId}") - GameTeamInfo getGameInfo(@PathVariable Long gameId, @Parameter(hidden = true) @Login UserDto userDto) { - return gameService.getUserGameInfo(gameId, userDto.getId()); - } - - @PostMapping("/rank") - synchronized ResponseEntity createRankResult(@Valid @RequestBody RankResultReqDto reqDto, @Parameter(hidden = true) @Login UserDto user) { - if (reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() > 3 || reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() < 2 || - reqDto.getMyTeamScore() == reqDto.getEnemyTeamScore()) { - throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); - } - if (!gameService.createRankResult(reqDto, user.getId())) { - throw new ScoreNotMatchedException(); - } - rankRedisService.updateAllTier(reqDto.getGameId()); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @PostMapping("/normal") - ResponseEntity createNormalResult(@Valid @RequestBody NormalResultReqDto reqDto, @Parameter(hidden = true) @Login UserDto user) { - if (gameService.normalExpResult(reqDto, user.getId())) - return new ResponseEntity<>(HttpStatus.CREATED); - return new ResponseEntity<>(HttpStatus.ACCEPTED); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋“ฑ๋ก - * @param reqDto ์š”์ฒญ Dto - * @param user ์‚ฌ์šฉ์ž - * @exception InvalidParameterException ์œ ํšจํ•˜์ง€ ์•Š์€ ์ ์ˆ˜ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ - * @return 201 created - */ - @PostMapping("/tournament") - synchronized ResponseEntity createTournamentGameResult(@Valid @RequestBody TournamentResultReqDto reqDto, @Parameter(hidden = true) @Login UserDto user) { - if (reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() > 3 || reqDto.getMyTeamScore() + reqDto.getEnemyTeamScore() < 2 || - reqDto.getMyTeamScore() == reqDto.getEnemyTeamScore()) { - throw new InvalidParameterException("์ ์ˆ˜๋ฅผ ์ž˜๋ชป ์ž…๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); - } - gameService.createTournamentGameResult(reqDto, user.getId()); - return ResponseEntity.status(HttpStatus.CREATED).build(); - } - - /** - * RANK, NORMAL, TOURNAMENT ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜. - */ - @GetMapping("/{gameId}/pchange/result") - ResponseEntity getGamePChangeResult(@PathVariable Long gameId, - @Parameter(hidden = true) @Login UserDto user, @RequestParam Mode mode) { - if (mode == Mode.RANK) - return ResponseEntity.ok(gameService.pppChangeResult(gameId, user.getId())); - else if (mode == Mode.NORMAL || mode == Mode.TOURNAMENT) - return ResponseEntity.ok(gameService.expChangeResult(gameId, user.getId())); - throw new BusinessException(ErrorCode.BAD_ARGU); - } -} diff --git a/src/main/java/com/gg/server/domain/game/data/Game.java b/src/main/java/com/gg/server/domain/game/data/Game.java deleted file mode 100644 index c8ab0972a..000000000 --- a/src/main/java/com/gg/server/domain/game/data/Game.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.gg.server.domain.game.data; - -import com.gg.server.domain.match.dto.GameAddDto; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.team.data.Team; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.utils.BusinessChecker; -import java.util.ArrayList; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class Game { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "season_id") - private Season season; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "status", length = 10) - private StatusType status; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "mode", length = 10) - private Mode mode; - - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @Column(name = "end_time") - private LocalDateTime endTime; - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL) - private List teams = new ArrayList<>(); - - public Game(Season season, StatusType status, Mode mode, LocalDateTime startTime, LocalDateTime endTime) { - this.season = season; - this.status = status; - this.mode = mode; - this.startTime = startTime; - this.endTime = endTime; - } - - public Game(GameAddDto dto, Integer interval) { - this.season = dto.getSeason(); - this.status = StatusType.BEFORE; - this.mode = dto.getMode(); - this.startTime = dto.getStartTime(); - this.endTime = dto.getStartTime().plusMinutes(interval); - } - - @Override - public String toString() { - return "Game{" + - "id=" + id + - ", season=" + season + - ", status=" + status + - ", mode=" + mode + - ", startTime=" + startTime + - ", endTime=" + endTime + - '}'; - } - - public void updateStatus() { - if (status == StatusType.BEFORE) { - this.status = StatusType.LIVE; - } else if (status == StatusType.LIVE) { - this.status = StatusType.WAIT; - } else { - this.status = StatusType.END; - } - } - - public void addTeam(Team team) { - BusinessChecker.mustNotNull(team, ErrorCode.NULL_POINT); - BusinessChecker.mustNotExceed(1, teams, ErrorCode.TEAM_SIZE_EXCEED); - BusinessChecker.mustNotContains(team, teams, ErrorCode.TEAM_DUPLICATION); - this.teams.add(team); - } - -} diff --git a/src/main/java/com/gg/server/domain/game/data/GameRepository.java b/src/main/java/com/gg/server/domain/game/data/GameRepository.java deleted file mode 100644 index 4d9efc2e1..000000000 --- a/src/main/java/com/gg/server/domain/game/data/GameRepository.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.gg.server.domain.game.data; - -import com.gg.server.domain.game.dto.GameTeamUserInfo; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; - -import java.time.LocalDateTime; -import java.util.Optional; - -import com.gg.server.domain.team.dto.GameUser; -import javax.persistence.LockModeType; - -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import com.gg.server.domain.game.dto.GameTeamUser; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.jpa.repository.Lock; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; - -public interface GameRepository extends JpaRepository, GameRepositoryCustom { - Slice findAllByModeAndStatus(Mode mode, StatusType status, Pageable pageable); - - /* - Slice findAllByStatus(StatusType status, Pageable pageable); - - Slice findAllByStatusIn(List statusList, Pageable pageable); - */ - - - Slice findAllByModeAndStatusAndSeasonId(Mode mode, StatusType status, Long season, Pageable pageable); - - Slice findAllByModeInAndStatusIn(List modeList, List statusList, Pageable pageable); - - Slice findAllByModeInAndStatus(List modeList, StatusType status, Pageable pageable); - - @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + - "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + - "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + - "from v_rank_game_detail t1, v_rank_game_detail t2 " + - "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsIn(@Param("games") List games); - - @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + - "t1.intraId t1IntraId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, " + - "t2.win t2IsWin, t2.score t2Score, t2.intraId t2IntraId, t2.image t2Image, t2.total_exp t2Exp " + - "from v_teamuser t1, v_teamuser t2 " + - "where t1.gameId IN (:games) and t1.teamId findTeamsByGameIsInAndNormalMode(@Param("games") List games); - - @Query(value = "select t1.gameId, t1.startTime, t1.status, t1.mode, " + - "t1.intraId t1IntraId, t1.teamId t1TeamId, t1.win t1IsWin, t1.score t1Score, t1.image t1Image, t1.total_exp t1Exp, t1.wins t1Wins, t1.losses t1Losses, " + - "t2.win t2IsWin, t2.teamId t2TeamId, t2.score t2Score, t2.intraId t2IntraId, t2.wins t2Wins, t2.losses t2Losses, t2.image t2Image, t2.total_exp t2Exp " + - "from v_rank_game_detail t1, v_rank_game_detail t2 " + - "where t1.gameId = (:gameId) and t1.teamId findTeamsByGameId(@Param("gameId") Long gameId); - - @Query(value = "SELECT teamId, gameId, score, startTime, status, mode, userId, intraId, image, total_exp exp" + - " FROM v_teamuser where gameId = :gameId", nativeQuery = true) - List findTeamGameUser(@Param("gameId") Long gameId); - - Optional findByStartTime(LocalDateTime startTime); - - @Query(value = "select g from Game g where g.startTime > :startTime and g.startTime < :endTime") - List findAllBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); - - @Query(value = "select g from Game g where (g.startTime between :startTime and :endTime) " - + "or (g.endTime between :startTime and :endTime) " - + "or (:startTime between g.startTime and g.endTime) " - + "or (:endTime between g.startTime and g.endTime)") - List findAllBetweenTournament(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); - - @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.startTime > :startTime AND g.startTime < :endTime " - + "AND g.id = t.game.id AND t.id = tu.team.id AND tu.user.id = :userId") - Optional findByUserInSlots(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("userId") Long userId); - - @Query(value = "SELECT g FROM Game g, Team t, TeamUser tu WHERE g.status = :status AND g.id = t.game.id" - + " AND t.id = tu.team.id AND tu.user.id = :userId") - Optional findByStatusTypeAndUserId(@Param("status") StatusType status, @Param("userId") Long userId); - - @Query(value = "select gameId " + - "from v_teamuser " + - "where intraId = :intra and mode in (:mode) and status in(:status)", nativeQuery = true) - Slice findGamesByUserAndModeInAndStatusIn(@Param("intra") String intra, @Param("mode") List mode, @Param("status") List status, Pageable pageable); - - @Query(value = "select gameId " + - "from v_teamuser " + - "where intraId=:intra and mode=:mode and status=:status", nativeQuery = true) - Slice findGamesByUserAndModeAndStatus(@Param("intra") String intra, @Param("mode") String mode, @Param("status") String status, Pageable pageable); - - @Query(value = "select gameId " + - "from v_teamuser " + - "where intraId = :intra and mode=:mode and seasonId = :seasonId and status = :status", nativeQuery = true) - Slice findGamesByUserAndModeAndSeason(@Param("intra") String intra, @Param("mode") String mode, @Param("seasonId") Long seasonId, @Param("status") String status, Pageable pageable); - - List findAllByStatusAndStartTimeLessThanEqual(StatusType status, LocalDateTime startTime); - - List findAllByStatusAndEndTimeLessThanEqual(StatusType status, LocalDateTime endTime); - - @Query(value = "SELECT u.id userId, u.e_mail email, u.intra_id intraId, u.sns_noti_opt snsNotiOpt, g.id gameId " + - "FROM " + - "(SELECT id, status FROM game where start_time<=:time) g, " + - "team t, team_user tu, user u " + - "WHERE g.id=t.game_id AND t.id = tu.team_id AND tu.user_id=u.id AND g.status = 'BEFORE'", nativeQuery = true) - List findAllByStartTimeLessThanEqual(@Param("time") LocalDateTime time); - - @Lock(LockModeType.PESSIMISTIC_WRITE) - Optional findWithPessimisticLockById(Long gameId); - - @Override - @EntityGraph(attributePaths = {"season"}) - Optional findById(Long gameId); -} diff --git a/src/main/java/com/gg/server/domain/game/data/GameRepositoryCustom.java b/src/main/java/com/gg/server/domain/game/data/GameRepositoryCustom.java deleted file mode 100644 index af8f83fc1..000000000 --- a/src/main/java/com/gg/server/domain/game/data/GameRepositoryCustom.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.gg.server.domain.game.data; - -import java.util.Optional; - -public interface GameRepositoryCustom { - Optional getLatestGameByUser(Long userId); -} diff --git a/src/main/java/com/gg/server/domain/game/data/GameRepositoryImpl.java b/src/main/java/com/gg/server/domain/game/data/GameRepositoryImpl.java deleted file mode 100644 index b72787d38..000000000 --- a/src/main/java/com/gg/server/domain/game/data/GameRepositoryImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.domain.game.data; - -import com.gg.server.domain.team.data.TeamUser; -import lombok.RequiredArgsConstructor; - -import javax.persistence.EntityManager; -import javax.persistence.NoResultException; -import java.util.Optional; - -@RequiredArgsConstructor -public class GameRepositoryImpl implements GameRepositoryCustom{ - private final EntityManager em; - @Override - public Optional getLatestGameByUser(Long userId) { - String sql = "select tu from TeamUser tu join fetch tu.user join fetch tu.team " + - "join tu.team.game g where tu.user.id =: userId order by g.startTime desc"; - - try{ - TeamUser teamUser = em.createQuery(sql, TeamUser.class).setParameter("userId", userId) - .setFirstResult(0) - .setMaxResults(1) - .getSingleResult(); - return Optional.of(teamUser.getTeam().getGame()); - } catch (NoResultException e){ - return Optional.empty(); - } - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GameListResDto.java b/src/main/java/com/gg/server/domain/game/dto/GameListResDto.java deleted file mode 100644 index d8d4d65a7..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GameListResDto.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.domain.game.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.*; - -@Getter -@NoArgsConstructor -public class GameListResDto { - private List games; - Boolean isLast; - - public GameListResDto(List games, Boolean isLast) { - this.games = games; - this.isLast = isLast; - } - - @Override - public String toString() { - return "GameListResDto{" + - "games=" + games + - ", isLast=" + isLast + - '}'; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof GameListResDto)) { - return false; - } else { - GameListResDto other = (GameListResDto) obj; - return this.isLast == other.getIsLast() - && this.games.equals(other.getGames()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GamePChangeResultResDto.java b/src/main/java/com/gg/server/domain/game/dto/GamePChangeResultResDto.java deleted file mode 100644 index 1802d34ca..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GamePChangeResultResDto.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.gg.server.domain.coin.dto.UserGameCoinResultDto; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@JsonInclude(Include.NON_NULL) -public class GamePChangeResultResDto { - private Integer beforeExp; - private Integer beforeMaxExp; - private Integer beforeLevel; - private Integer increasedExp; - private Integer increasedLevel; - private Integer afterMaxExp; - private int beforeCoin; - private int afterCoin; - private int coinIncrement; - protected Integer changedPpp; - protected Integer beforePpp; - - public GamePChangeResultResDto(Integer beforeExp, Integer currentExp, UserGameCoinResultDto userGameCoinResultDto) { - this.beforeExp = ExpLevelCalculator.getCurrentLevelMyExp(beforeExp); - this.beforeLevel = ExpLevelCalculator.getLevel(beforeExp); - this.beforeMaxExp = ExpLevelCalculator.getLevelMaxExp(beforeLevel); - this.increasedExp = currentExp - beforeExp; - this.increasedLevel = ExpLevelCalculator.getLevel(currentExp) - this.beforeLevel; - this.afterMaxExp = ExpLevelCalculator.getLevelMaxExp(this.beforeLevel + this.increasedLevel); - this.beforeCoin = userGameCoinResultDto.getBeforeCoin(); - this.afterCoin = userGameCoinResultDto.getAfterCoin(); - this.coinIncrement = userGameCoinResultDto.getCoinIncrement(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof GamePChangeResultResDto)) { - return false; - } else { - GamePChangeResultResDto other = (GamePChangeResultResDto) obj; - return this.beforeExp.equals(other.getBeforeExp()) - && this.beforeLevel.equals(other.getBeforeLevel()) - && this.beforeMaxExp.equals(other.getBeforeMaxExp()) - && this.increasedExp.equals(other.getIncreasedExp()) - && this.increasedLevel.equals(other.getIncreasedLevel()) - && this.afterMaxExp.equals(other.getAfterMaxExp()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GamePPPChangeResultResDto.java b/src/main/java/com/gg/server/domain/game/dto/GamePPPChangeResultResDto.java deleted file mode 100644 index dfe67560e..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GamePPPChangeResultResDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.gg.server.domain.coin.dto.UserGameCoinResultDto; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -public class GamePPPChangeResultResDto extends GamePChangeResultResDto { - - public GamePPPChangeResultResDto(Integer beforeExp, Integer currentExp, Integer beforePpp, - Integer afterPpp, UserGameCoinResultDto userGameCoinResultDto) { - super(beforeExp, currentExp, userGameCoinResultDto); - this.changedPpp = afterPpp - beforePpp; - this.beforePpp = beforePpp; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof GamePPPChangeResultResDto)) { - return false; - } else { - GamePPPChangeResultResDto other = (GamePPPChangeResultResDto) obj; - return this.changedPpp.equals(other.getChangedPpp()) - && this.beforePpp.equals(other.getBeforePpp()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GameResultResDto.java b/src/main/java/com/gg/server/domain/game/dto/GameResultResDto.java deleted file mode 100644 index 531dca551..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GameResultResDto.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.team.dto.TeamUserInfoDto; -import com.gg.server.domain.team.dto.TeamUserListDto; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.time.LocalDateTime; -import java.util.Arrays; - -@Getter -@NoArgsConstructor -public class GameResultResDto { - private Long gameId; - private String status; - private Mode mode; - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime time; - private TeamUserListDto team1; - private TeamUserListDto team2; - - public GameResultResDto(GameTeamUser game) { - this.gameId = game.getGameId(); - this.status = game.getStatus().name();//name -> ๋Œ€๋ฌธ์ž - this.time = game.getStartTime(); - this.mode = game.getMode(); - if (mode == Mode.NORMAL) { - team1 = new TeamUserListDto(Arrays.asList( - new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), null, null)), null, null); - team2 = new TeamUserListDto(Arrays.asList( - new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), null, null)), null, null); - } else if (mode == Mode.RANK) { - team1 = new TeamUserListDto(Arrays.asList( - new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), game.getT1Wins(), game.getT1Losses())), game.getT1IsWin(), game.getT1Score()); - team2 = new TeamUserListDto(Arrays.asList( - new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), game.getT2Wins(), game.getT2Losses())), game.getT2IsWin(), game.getT2Score()); - } else if (mode == Mode.TOURNAMENT) { - team1 = new TeamUserListDto( - game.getT1TeamId(), - Arrays.asList(new TeamUserInfoDto(game.getT1IntraId(), game.getT1Image(), game.getT1Exp(), game.getT1Wins(), game.getT1Losses())), - game.getT1IsWin(), game.getT1Score()); - team2 = new TeamUserListDto(game.getT2TeamId(), - Arrays.asList(new TeamUserInfoDto(game.getT2IntraId(), game.getT2Image(), game.getT2Exp(), game.getT2Wins(), game.getT2Losses())), - game.getT2IsWin(), game.getT2Score()); - } - } - - @Override - public String toString() { - return "NormalGameResDto{" + - "gameId=" + gameId + - ", status='" + status + '\'' + - ", time=" + time + - ", team1=" + team1 + - ", team2=" + team2 + - '}'; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof GameResultResDto)) { - return false; - } else { - GameResultResDto other = (GameResultResDto) obj; - return this.gameId.equals(other.getGameId()) - && this.status.equals(other.getStatus()) - && this.mode.equals(other.getMode()) - && this.time.equals(other.getTime()) - && this.team1.equals(other.getTeam1()) - && this.team2.equals(other.getTeam2()); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/game/dto/GameTeamInfo.java b/src/main/java/com/gg/server/domain/game/dto/GameTeamInfo.java deleted file mode 100644 index 8a65012e0..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GameTeamInfo.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.gg.server.domain.game.exception.GameDataConsistencyException; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.team.dto.MatchTeamsInfoDto; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; -import lombok.extern.slf4j.Slf4j; - -import java.time.LocalDateTime; -import java.util.List; - -@Getter -@NoArgsConstructor -@ToString -@Slf4j -public class GameTeamInfo { - private Mode mode; - private Long gameId; - private LocalDateTime startTime; - private StatusType status; - private Boolean isScoreExist; - private MatchTeamsInfoDto matchTeamsInfo; - - public GameTeamInfo(List infos, Long userId) { - this.mode = infos.get(0).getMode(); - this.gameId = infos.get(0).getGameId(); - this.startTime = infos.get(0).getStartTime(); - this.status = infos.get(0).getStatus(); - Long myTeamId = null; - for (GameTeamUserInfo info : - infos) { - if (info.getScore() > -1) { - this.isScoreExist = true; - } - if (!this.mode.equals(info.getMode()) || !this.gameId.equals(info.getGameId()) - || !this.startTime.equals(info.getStartTime()) || !this.status.equals(info.getStatus())) { - log.error("data error: gid 1: ", infos.get(0).getGameId(), ", gid 2:", infos.get(1).getGameId()); - throw new GameDataConsistencyException(); - } - if (info.getUserId().equals(userId)) - myTeamId = info.getTeamId(); - } - this.matchTeamsInfo = new MatchTeamsInfoDto(infos, myTeamId); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof GameTeamInfo)) { - return false; - } else { - GameTeamInfo other = (GameTeamInfo) obj; - return this.status.equals(other.getStatus()) - && this.gameId.equals(other.getGameId()) - && this.isScoreExist.equals(other.getIsScoreExist()) - && this.mode.equals(other.getMode()) - && this.startTime.equals(other.getStartTime()) - && this.matchTeamsInfo.equals(other.getMatchTeamsInfo()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GameTeamUser.java b/src/main/java/com/gg/server/domain/game/dto/GameTeamUser.java deleted file mode 100644 index 3d572a4a3..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GameTeamUser.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; - -import java.time.LocalDateTime; - -public interface GameTeamUser { - Long getGameId(); - LocalDateTime getStartTime(); - LocalDateTime getEndTime(); - StatusType getStatus(); - Mode getMode(); - Long getT1TeamId(); - Integer getT1Wins(); - Integer getT1Losses(); - String getT1IntraId(); - String getT1Image(); - Integer getT1Exp(); - Integer getT1Score(); - Boolean getT1IsWin(); - Long getT2TeamId(); - Integer getT2Wins(); - Integer getT2Losses(); - String getT2IntraId(); - String getT2Image(); - Integer getT2Exp(); - Integer getT2Score(); - Boolean getT2IsWin(); -} diff --git a/src/main/java/com/gg/server/domain/game/dto/GameTeamUserInfo.java b/src/main/java/com/gg/server/domain/game/dto/GameTeamUserInfo.java deleted file mode 100644 index 6601f4650..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/GameTeamUserInfo.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.game.dto; - -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; - -import java.time.LocalDateTime; - -public interface GameTeamUserInfo { - Long getGameId(); - LocalDateTime getStartTime(); - StatusType getStatus(); - Mode getMode(); - Long getTeamId(); - Integer getScore(); - Long getUserId(); - String getIntraId(); - Integer getExp(); - String getImage(); - -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/GameListReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/GameListReqDto.java deleted file mode 100644 index c6fac2b0c..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/GameListReqDto.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import com.gg.server.domain.game.type.StatusType; -import lombok.Getter; - -@Getter -public class GameListReqDto extends NormalGameListReqDto { - private StatusType status; - public GameListReqDto(Integer pageNum, Integer pageSize, String nickname, StatusType status) { - super(pageNum, pageSize, nickname); - this.status = status; - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/NormalGameListReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/NormalGameListReqDto.java deleted file mode 100644 index 0bfa71b3c..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/NormalGameListReqDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class NormalGameListReqDto extends PageRequestDto { - private String intraId; - - public NormalGameListReqDto(Integer page, Integer size, String intraId) { - super(page, size); - this.intraId = intraId; - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/NormalResultReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/NormalResultReqDto.java deleted file mode 100644 index 827c74b1b..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/NormalResultReqDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import lombok.Getter; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; - -@Getter -public class NormalResultReqDto { - @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @Positive(message = "gameId ๋Š” ์–‘์ˆ˜๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.") - private Long gameId; - -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/RankGameListReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/RankGameListReqDto.java deleted file mode 100644 index 28d7398ca..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/RankGameListReqDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import lombok.Getter; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; - -@Getter -public class RankGameListReqDto extends NormalGameListReqDto { - @Positive - @NotNull(message = "seasonId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - private Long seasonId; - - public RankGameListReqDto(Integer pageNum, Integer pageSize, String nickname, Long seasonId) { - super(pageNum, pageSize, nickname); - this.seasonId = seasonId; - } -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/RankResultReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/RankResultReqDto.java deleted file mode 100644 index e76d4ac48..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/RankResultReqDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import javax.validation.constraints.PositiveOrZero; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class RankResultReqDto { - - @Positive - @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - private Long gameId; - @NotNull(message = "myTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @Positive - private Long myTeamId; - @NotNull(message = "myTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int myTeamScore; - @NotNull(message = "enemyTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @Positive - private Long enemyTeamId; - @NotNull(message = "enemyTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int enemyTeamScore; -} diff --git a/src/main/java/com/gg/server/domain/game/dto/request/TournamentResultReqDto.java b/src/main/java/com/gg/server/domain/game/dto/request/TournamentResultReqDto.java deleted file mode 100644 index 915edf74e..000000000 --- a/src/main/java/com/gg/server/domain/game/dto/request/TournamentResultReqDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.game.dto.request; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import javax.validation.constraints.Positive; - -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PositiveOrZero; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class TournamentResultReqDto { - @Positive - @NotNull(message = "gameId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - private Long gameId; - @NotNull(message = "myTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @javax.validation.constraints.Positive - private Long myTeamId; - @NotNull(message = "myTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int myTeamScore; - @NotNull(message = "enemyTeamId ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @javax.validation.constraints.Positive - private Long enemyTeamId; - @NotNull(message = "enemyTeamScore ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - @PositiveOrZero - @Max(2) - private int enemyTeamScore; -} diff --git a/src/main/java/com/gg/server/domain/game/exception/GameAlreadyExistException.java b/src/main/java/com/gg/server/domain/game/exception/GameAlreadyExistException.java deleted file mode 100644 index f9f879b12..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/GameAlreadyExistException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class GameAlreadyExistException extends DuplicationException { - public GameAlreadyExistException() { - super("๊ฒŒ์ž„์ด ์ด๋ฏธ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_DUPLICATION_EXCEPTION); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/GameDataConsistencyException.java b/src/main/java/com/gg/server/domain/game/exception/GameDataConsistencyException.java deleted file mode 100644 index b9e0acdb2..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/GameDataConsistencyException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; -import com.gg.server.global.exception.custom.DBConsistencyException; - -public class GameDataConsistencyException extends DBConsistencyException { - public GameDataConsistencyException() { - super("game db ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_DB_NOT_VALID); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/GameNotExistException.java b/src/main/java/com/gg/server/domain/game/exception/GameNotExistException.java deleted file mode 100644 index 37f69d0c4..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/GameNotExistException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class GameNotExistException extends NotExistException { - public GameNotExistException() { - super("game ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.GAME_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/GameStatusNotMatchedException.java b/src/main/java/com/gg/server/domain/game/exception/GameStatusNotMatchedException.java deleted file mode 100644 index a101bfc4b..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/GameStatusNotMatchedException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class GameStatusNotMatchedException extends BusinessException { - public GameStatusNotMatchedException() { - super("๊ฒŒ์ž„ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.GAME_STATUS_NOT_MATCHED); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/ScoreAlreadyEnteredException.java b/src/main/java/com/gg/server/domain/game/exception/ScoreAlreadyEnteredException.java deleted file mode 100644 index 14492f0c7..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/ScoreAlreadyEnteredException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class ScoreAlreadyEnteredException extends DuplicationException { - public ScoreAlreadyEnteredException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/ScoreNotInvalidException.java b/src/main/java/com/gg/server/domain/game/exception/ScoreNotInvalidException.java deleted file mode 100644 index 614e8b7aa..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/ScoreNotInvalidException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; - -public class ScoreNotInvalidException extends InvalidParameterException { - public ScoreNotInvalidException() { - super(ErrorCode.SCORE_NOT_INVALID.getMessage(), ErrorCode.SCORE_NOT_INVALID); - } -} diff --git a/src/main/java/com/gg/server/domain/game/exception/ScoreNotMatchedException.java b/src/main/java/com/gg/server/domain/game/exception/ScoreNotMatchedException.java deleted file mode 100644 index f2d48afbf..000000000 --- a/src/main/java/com/gg/server/domain/game/exception/ScoreNotMatchedException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.game.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; -import com.gg.server.global.exception.custom.InvalidParameterException; - -public class ScoreNotMatchedException extends DuplicationException { - public ScoreNotMatchedException() { - super(ErrorCode.SCORE_NOT_MATCHED.getMessage(), ErrorCode.SCORE_NOT_MATCHED); - } -} diff --git a/src/main/java/com/gg/server/domain/game/service/GameFindService.java b/src/main/java/com/gg/server/domain/game/service/GameFindService.java deleted file mode 100644 index 3c7d45904..000000000 --- a/src/main/java/com/gg/server/domain/game/service/GameFindService.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.gg.server.domain.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GameResultResDto; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class GameFindService { - private final GameRepository gameRepository; - - /** - * ํŠน์ • User์˜ NORMAL ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - * @param pageable - * @param intra - ์กฐํšŒํ•  ์œ ์ €์˜ intraId - * @return GameListResDto - games isLast - */ - @Transactional(readOnly = true) - @Cacheable(value = "normalGameListByIntra", cacheManager = "gameCacheManager") - public GameListResDto normalGameListByIntra(Pageable pageable, String intra) { - Slice games = gameRepository.findGamesByUserAndModeAndStatus(intra, Mode.NORMAL.name(), StatusType.END.name(), pageable); - return new GameListResDto(getNormalGameResultList(games.getContent()), games.isLast()); - } - - /** - * NORMAL ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - * @param pageable - * @return - */ - @Transactional(readOnly = true) - @Cacheable(value = "normalGameList", cacheManager = "gameCacheManager") - public GameListResDto getNormalGameList(Pageable pageable) { - Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); - return new GameListResDto(getNormalGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); - } - - /** - * ํŠน์ • User์˜ RANK ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - * @param pageable - * @param seasonId - ์กฐํšŒํ•  ์‹œ์ฆŒ์˜ id - * @param intra - ์กฐํšŒํ•  ์œ ์ €์˜ intraId - * @return GameListResDto - games isLast - */ - @Transactional(readOnly = true) - @Cacheable(value = "rankGameListByIntra", cacheManager = "gameCacheManager") - public GameListResDto rankGameListByIntra(Pageable pageable, Long seasonId, String intra) { - Slice games = gameRepository.findGamesByUserAndModeAndSeason(intra, Mode.RANK.name(), seasonId, StatusType.END.name(), pageable); - return new GameListResDto(getGameResultList(games.getContent()), games.isLast()); - } - - /** - * RANK ๋ชจ๋“œ์˜ END ์ƒํƒœ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - * @param pageable - * @param seasonId - ์กฐํšŒํ•  ์‹œ์ฆŒ์˜ id - * @return GameListResDto - games isLast - */ - @Transactional(readOnly = true) - @Cacheable(value = "rankGameList", cacheManager = "gameCacheManager") - public GameListResDto rankGameList(Pageable pageable, Long seasonId) { - Slice games = gameRepository.findAllByModeAndStatusAndSeasonId(Mode.RANK, StatusType.END, seasonId, pageable); - return new GameListResDto(getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); - } - - /** - * NORMAL, RANDOM ๋ชจ๋“œ์˜ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - *

- * status๊ฐ€ "LIVE" -> ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„๋„ ํฌํ•จํ•ด์„œ ์กฐํšŒ (END, LIVE, WAIT)
- * status๊ฐ€ null -> ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„๋งŒ ์กฐํšŒ (END) - *

- * @param pageable - * @param status - "LIVE" or null - * @return GameListResDto - games isLast - */ - @Transactional(readOnly = true) - @Cacheable(value = "allGameList", cacheManager = "gameCacheManager", key = "#pageable.pageNumber + #pageable.pageSize + #pageable.sort.toString() + #status") - public GameListResDto allGameList(Pageable pageable, String status) { - Slice games; - if (status != null && status.equals("LIVE")) { - games = gameRepository.findAllByModeInAndStatusIn(Arrays.asList(Mode.RANK, Mode.NORMAL), Arrays.asList(StatusType.END, StatusType.LIVE, StatusType.WAIT), pageable); - } else { - games = gameRepository.findAllByModeInAndStatus(Arrays.asList(Mode.RANK, Mode.NORMAL), StatusType.END, pageable); - } - return new GameListResDto(getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); - } - - /** - * allGameList()์™€ ๋™์ผํ•œ ๋กœ์ง + intraId๋กœ ์กฐํšŒ - * @param pageable - * @param intra - ์กฐํšŒํ•  intraId - * @param status - "LIVE" or null - * @return GameListResDto - games isLast - * @throws GameNotExistException - intraId๋กœ ์กฐํšŒํ•œ ๊ฒŒ์ž„์ด ์—†์„ ๊ฒฝ์šฐ - */ - @Transactional(readOnly = true) - @Cacheable(value = "allGameListByUser", cacheManager = "gameCacheManager", key = "#pageable.pageNumber + #pageable.pageSize + #pageable.sort.toString() + #status + #intra") - public GameListResDto allGameListUser(Pageable pageable, String intra, String status) { - List statusTypes = Arrays.asList(StatusType.END.name()); - if (status != null && status.equals("LIVE")) { - statusTypes.add(StatusType.LIVE.name()); - statusTypes.add(StatusType.WAIT.name()); - } - Slice games = gameRepository.findGamesByUserAndModeInAndStatusIn(intra, Arrays.asList(Mode.RANK.name(), Mode.NORMAL.name()), statusTypes, pageable); - return new GameListResDto(getGameResultList(games.getContent()), games.isLast()); - } - public Game findByGameId(Long gameId) { - return gameRepository.findById(gameId) - .orElseThrow(GameNotExistException::new); - } - - public Game findGameWithPessimisticLockById(Long id) { - return gameRepository.findWithPessimisticLockById(id) - .orElseThrow(GameNotExistException::new); - } - - /** - * private method - */ - private List getGameResultList(List games) { - List teamViews = gameRepository.findTeamsByGameIsIn(games); - return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); - } - private List getNormalGameResultList(List games) { - List teamViews = gameRepository.findTeamsByGameIsInAndNormalMode(games); - return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/gg/server/domain/game/service/GameService.java b/src/main/java/com/gg/server/domain/game/service/GameService.java deleted file mode 100644 index b74f62f9d..000000000 --- a/src/main/java/com/gg/server/domain/game/service/GameService.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.gg.server.domain.game.service; - -import com.gg.server.domain.coin.dto.UserGameCoinResultDto; -import com.gg.server.domain.coin.service.UserCoinChangeService; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.*; -import com.gg.server.domain.game.dto.request.NormalResultReqDto; -import com.gg.server.domain.game.dto.request.RankResultReqDto; -import com.gg.server.domain.game.dto.request.TournamentResultReqDto; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.game.exception.GameStatusNotMatchedException; -import com.gg.server.domain.game.exception.ScoreAlreadyEnteredException; -import com.gg.server.domain.match.service.MatchTournamentService; -import com.gg.server.domain.match.type.TournamentMatchStatus; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import com.gg.server.domain.pchange.service.PChangeService; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.team.exception.TeamIdNotMatchException; -import com.gg.server.domain.tier.service.TierService; -import com.gg.server.domain.tournament.data.*; -import com.gg.server.domain.tournament.exception.TournamentGameNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Caching; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.*; - -@Service -@RequiredArgsConstructor -public class GameService { - private final GameRepository gameRepository; - private final TeamUserRepository teamUserRepository; - private final RankRedisService rankRedisService; - private final PChangeService pChangeService; - private final PChangeRepository pChangeRepository; - private final GameFindService gameFindService; - private final UserCoinChangeService userCoinChangeService; - private final TierService tierService; - private final TournamentGameRepository tournamentGameRepository; - private final MatchTournamentService matchTournamentService; - - /** - * ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - * - * @param gameId - * @param userId - * @return GameTeamInfo ๊ฒŒ์ž„ ์ •๋ณด - * @throws GameNotExistException ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ - */ - @Transactional(readOnly = true) - public GameTeamInfo getUserGameInfo(Long gameId, Long userId) { - List infos = gameRepository.findTeamGameUser(gameId); - if (infos.isEmpty()) { - throw new GameNotExistException(); - } - return new GameTeamInfo(infos, userId); - } - - /** - * rank ๊ฒŒ์ž„ ๊ฒฐ๊ณผ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค. - * WAIT, LIVE ์ƒํƒœ์ผ ๋•Œ๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅ - * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€ - */ - @Transactional - @Caching(evict = { - @CacheEvict(value = "rankGameListByIntra", allEntries = true), - @CacheEvict(value = "rankGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true), - @CacheEvict(value = "ranking", allEntries = true), - @CacheEvict(value = "expRanking", allEntries = true) - }) - public Boolean createRankResult(RankResultReqDto scoreDto, Long userId) { - // ํ˜„์žฌ ๊ฒŒ์ž„ id - Game game = gameFindService.findGameWithPessimisticLockById(scoreDto.getGameId()); - if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { - return false; - } - return updateRankGameScore(game, scoreDto, userId); - } - - /** - * tournament ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ๋“ฑ๋ก - * @param scoreDto ์š”์ฒญ Dto - * @param userId ์‚ฌ์šฉ์ž Id - * @exception GameStatusNotMatchedException ๊ฒŒ์ž„ ์ƒํƒœ๊ฐ€ WAIT, LIVE๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ - * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€ - */ - @Transactional - public void createTournamentGameResult(TournamentResultReqDto scoreDto, Long userId) { - Game game = gameFindService.findGameWithPessimisticLockById(scoreDto.getGameId()); - if (game.getStatus() != StatusType.WAIT && game.getStatus() != StatusType.LIVE) { - throw new GameStatusNotMatchedException(); - } - updateTournamentGameScore(game, scoreDto, userId); - if (TournamentMatchStatus.POSSIBLE.equals(matchTournamentService.checkTournamentGame(game))) { - TournamentGame tournamentGame = tournamentGameRepository.findByGameId(game.getId()) - .orElseThrow(TournamentGameNotFoundException::new); - Tournament tournament = tournamentGame.getTournament(); - matchTournamentService.matchGames(tournament, tournamentGame.getTournamentRound().getNextRound()); - } - } - - /** - * normal ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•˜๊ณ  exp(๊ฒฝํ—˜์น˜)๋ฅผ ๋ถ€์—ฌํ•œ๋‹ค. - * @return Boolean ์ž…๋ ฅ ์„ฑ๊ณต ์—ฌ๋ถ€: false - * @throws InvalidParameterException team ์ •๋ณด๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์„ ๋•Œ - * @throws PChangeNotExistException pchange ์ •๋ณด๊ฐ€ ์—†์„ ๋•Œ - */ - @Transactional - @Caching(evict = { - @CacheEvict(value = "normalGameListByIntra", allEntries = true), - @CacheEvict(value = "normalGameList", allEntries = true), - @CacheEvict(value = "allGameList", allEntries = true), - @CacheEvict(value = "allGameListByUser", allEntries = true), - @CacheEvict(value = "ranking", allEntries = true), - @CacheEvict(value = "expRanking", allEntries = true) - }) - public Boolean normalExpResult(NormalResultReqDto normalResultReqDto, Long loginUserId) { - Game game = gameFindService.findGameWithPessimisticLockById(normalResultReqDto.getGameId()); - List teamUsers = teamUserRepository.findAllByGameId(game.getId()); - if (teamUsers.size() == 2 && - (game.getStatus() == StatusType.WAIT || game.getStatus() == StatusType.LIVE)) { - expUpdates(game, teamUsers); - savePChange(game, teamUsers, loginUserId); - return true; - } else if (teamUsers.size() == 2 && game.getStatus() == StatusType.END) { - updatePchangeIsChecked(game, loginUserId); - return true; - } else if (teamUsers.size() != 2) { - throw new InvalidParameterException("team ์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); - } - // BEFORE ์ƒํƒœ์ผ ๋•Œ false - return false; - } - - /** - * normal ๊ฒŒ์ž„์— ๋Œ€ํ•œ exp ๋ณ€ํ™” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - * @param gameId - * @param userId - * @return GamePChangeResultResDto ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ๊ฒฐ๊ณผ - */ - @Transactional - public GamePChangeResultResDto expChangeResult(Long gameId, Long userId) { - List pChanges = pChangeService.findExpChangeHistory(gameId, userId); - UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); - - if (pChanges.size() == 1) { - return new GamePChangeResultResDto(0, pChanges.get(0).getExp(), userGameCoinResultDto); - } else { - return new GamePChangeResultResDto(pChanges.get(1).getExp(), pChanges.get(0).getExp(), userGameCoinResultDto); - } - } - - /** - * rank ๊ฒŒ์ž„์— ๋Œ€ํ•œ exp, ppp ๋ณ€ํ™” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. - * @param gameId ๊ฒŒ์ž„ id - * @param userId ๊ฒŒ์ž„์— ์ฐธ์—ฌํ•œ ์œ ์ € id - * @return GamePPPChangeResultResDto ๊ฒฝํ—˜์น˜ ๋ณ€ํ™” ๊ฒฐ๊ณผ - * @throws PChangeNotExistException - */ - @Transactional - public GamePPPChangeResultResDto pppChangeResult(Long gameId, Long userId) throws PChangeNotExistException { - Season season = gameFindService.findByGameId(gameId).getSeason(); - List pppHistory = pChangeService.findPPPChangeHistory(gameId, userId, season.getId()); - List expHistory = pChangeService.findExpChangeHistory(gameId, userId); - UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addRankGameCoin(gameId, userId); - return new GamePPPChangeResultResDto(expHistory.size() <= 1 ? 0 : expHistory.get(1).getExp(), - pppHistory.get(0).getExp(), - pppHistory.size() <= 1 ? season.getStartPpp() : pppHistory.get(1).getPppResult(), - pppHistory.get(0).getPppResult(), userGameCoinResultDto); - } - - public void expUpdates(Game game, List teamUsers) { - LocalDateTime time = getToday(game.getStartTime()); - for (TeamUser tu : - teamUsers) { - expUpdate(tu, time); - } - if (game.getStatus() == StatusType.LIVE) { - game.updateStatus(); - } - game.updateStatus(); - } - - /** - * PRIVATE METHOD - */ - private void updatePchangeIsChecked(Game game, Long loginUserId) { - pChangeRepository.findPChangeByUserIdAndGameId(loginUserId, game.getId()) - .ifPresentOrElse(pChange -> { - pChange.checkPChange(); - pChangeRepository.save(pChange); - }, () -> { - throw new PChangeNotExistException(); - }); - } - - public void savePChange(Game game, List teamUsers, Long loginUserId) { - if (!pChangeRepository.findPChangesByGameId(game.getId()).isEmpty()){ - return ; - } - Long team1UserId = teamUsers.get(0).getUser().getId(); - Long team2UserId = teamUsers.get(1).getUser().getId(); - pChangeService.addPChange(game, teamUsers.get(0).getUser(), - rankRedisService.getUserPpp(team1UserId, game.getSeason().getId()), team1UserId.equals(loginUserId)); - pChangeService.addPChange(game, teamUsers.get(1).getUser(), - rankRedisService.getUserPpp(team2UserId, game.getSeason().getId()), team2UserId.equals(loginUserId)); - } - - private void expUpdate(TeamUser teamUser, LocalDateTime time) { - Integer gamePerDay = teamUserRepository.findByDateAndUser(time, teamUser.getUser().getId()); - teamUser.getUser().addExp(ExpLevelCalculator.getExpPerGame() + (ExpLevelCalculator.getExpBonus() * gamePerDay)); - } - - private static LocalDateTime getToday(LocalDateTime gameTime) { - return LocalDateTime.of(gameTime.getYear(), gameTime.getMonthValue(), gameTime.getDayOfMonth(), 0, 0); - } - - private void setTeamScore(TeamUser tu, int teamScore, Boolean isWin) { - tu.getTeam().updateScore(teamScore, isWin); - } - - private TeamUser findTeamId(Long teamId, List teamUsers) { - for (TeamUser tu : - teamUsers) { - if (tu.getTeam().getId().equals(teamId)) { - return tu; - } - } - throw new TeamIdNotMatchException(); - } - - private Boolean updateRankGameScore(Game game, RankResultReqDto scoreDto, Long userId) { - List teams = teamUserRepository.findAllByGameId(game.getId()); - TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); - TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); - if (!myTeam.getUser().getId().equals(userId)) { - throw new InvalidParameterException("team user ์ •๋ณด ๋ถˆ์ผ์น˜.", ErrorCode.VALID_FAILED); - } else { - if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)){ - setTeamScore(myTeam, scoreDto.getMyTeamScore(), scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); - setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); - expUpdates(game, teams); - rankRedisService.updateRankRedis(myTeam, enemyTeam, game); - tierService.updateAllTier(game.getSeason()); - } else { - // score ๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋จ - return false; - } - return true; - } - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์—…๋ฐ์ดํŠธ ๋ฉ”์†Œ๋“œ - * @param game - * @param scoreDto - * @param userId - * @exception InvalidParameterException ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ userId๊ฐ€ myTeam์˜ userId์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - * @exception ScoreAlreadyEnteredException ๊ฒŒ์ž„ ์ ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ž‘์„ฑ๋˜์–ด ์žˆ์„ ๊ฒฝ์šฐ - */ - private void updateTournamentGameScore(Game game, TournamentResultReqDto scoreDto, Long userId) { - List teams = teamUserRepository.findAllByGameId(game.getId()); - TeamUser myTeam = findTeamId(scoreDto.getMyTeamId(), teams); - TeamUser enemyTeam = findTeamId(scoreDto.getEnemyTeamId(), teams); - if (!myTeam.getUser().getId().equals(userId)) { - throw new InvalidParameterException("team user ์ •๋ณด๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.VALID_FAILED); - } - if (myTeam.getTeam().getScore().equals(-1) && enemyTeam.getTeam().getScore().equals(-1)){ - setTeamScore(myTeam, scoreDto.getMyTeamScore(), scoreDto.getMyTeamScore() > scoreDto.getEnemyTeamScore()); - setTeamScore(enemyTeam, scoreDto.getEnemyTeamScore(), scoreDto.getMyTeamScore() < scoreDto.getEnemyTeamScore()); - expUpdates(game, teams); - savePChange(game, teams, userId); - } else { - // score ๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋จ - throw new ScoreAlreadyEnteredException(ErrorCode.SCORE_ALREADY_ENTERED.getMessage(), ErrorCode.SCORE_ALREADY_ENTERED); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/game/service/GameStatusService.java b/src/main/java/com/gg/server/domain/game/service/GameStatusService.java deleted file mode 100644 index 67e1f66bf..000000000 --- a/src/main/java/com/gg/server/domain/game/service/GameStatusService.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.gg.server.domain.game.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.GameDataConsistencyException; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.dto.UserNotiDto; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.noti.service.SnsNotiService; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.dto.GameUser; -import com.gg.server.domain.user.service.UserService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.weaver.patterns.ConcreteCflowPointcut.Slot; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Caching; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -@Service -@RequiredArgsConstructor -@Slf4j -public class GameStatusService { - - private final GameRepository gameRepository; - private final SnsNotiService snsNotiService; - private final NotiService notiService; - private final UserService userService; - private final SlotManagementRepository slotManagementRepository; - - @Transactional - @Caching(evict = { - @CacheEvict(value = "allGameList", allEntries = true), - }) - public void updateBeforeToLiveStatus() { - // game before ์ค‘์— ํ˜„์žฌ ์‹œ์ž‘ ์‹œ๊ฐ„์ธ ๊ฒฝ์šฐ LIVE๋กœ update - List game = gameRepository.findAllByStatusAndStartTimeLessThanEqual(StatusType.BEFORE, getTime(0)); - if (!game.isEmpty()) { - cacheDelete(); - } - for (Game g : game) { - g.updateStatus(); - } - } - - void cacheDelete() {} - - @Transactional - @Caching(evict = { - @CacheEvict(value = "allGameList", allEntries = true), - }) - public void updateLiveToWaitStatus() { - // game live ์ค‘์— ์ข…๋ฃŒ ์‹œ๊ฐ„์ธ ๊ฒฝ์šฐ wait ๋กœ update - LocalDateTime endTime = getTime(1); - List game = gameRepository.findAllByStatusAndEndTimeLessThanEqual(StatusType.LIVE, endTime); - if (!game.isEmpty()) { - cacheDelete(); - } - for (Game g : game) { - g.updateStatus(); - } - } - - @Transactional - public void imminentGame() { - SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) - .orElseThrow(SlotNotFoundException::new); - List games = gameRepository.findAllByStartTimeLessThanEqual(getTime(slotManagement.getOpenMinute())); - if (games.size() > 2) { - log.error("imminent game size is not 2 -> size: " + games.size() + ", check time: " + getTime(slotManagement.getOpenMinute())); - throw new GameDataConsistencyException(); - } else if (games.isEmpty()) { - log.info("์‹œ์ž‘ " + slotManagement.getOpenMinute() + "๋ถ„ ์ „์ธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); - return; - } else { - notiProcess(games.get(0), games.get(1).getIntraId(), slotManagement.getOpenMinute()); - notiProcess(games.get(1), games.get(0).getIntraId(), slotManagement.getOpenMinute()); - } - } - - /** - * private method - */ - private void notiProcess(GameUser game, String enemyIntra, Integer gameOpenMinute) { - Noti noti = notiService.createImminentNoti(userService.getUser(game.getUserId()), enemyIntra, NotiType.IMMINENT, gameOpenMinute); - snsNotiService.sendSnsNotification(noti, new UserNotiDto(game)); - } - - private LocalDateTime getTime(int plusMiniute) { - LocalDateTime now = LocalDateTime.now(); - LocalDateTime endTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), - now.getHour(), now.getMinute(), 10); - return endTime.plusMinutes(plusMiniute); - } -} diff --git a/src/main/java/com/gg/server/domain/game/type/Mode.java b/src/main/java/com/gg/server/domain/game/type/Mode.java deleted file mode 100644 index 1af186b63..000000000 --- a/src/main/java/com/gg/server/domain/game/type/Mode.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.domain.game.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.type.Option; -import java.util.List; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum Mode { - NORMAL("normal"), RANK("rank"), TOURNAMENT("tournament"); - private final String code; - - @JsonCreator(mode = JsonCreator.Mode.DELEGATING) - public static Mode getEnumValue(String code) { - for(Mode e : values()) { - if(e.code.equals(code)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(code.toUpperCase(Locale.ROOT))) - return e; - } - return null; - } - - public static Mode ofPlayers(List players, Integer pppGap) { - if (players.stream().allMatch(player -> player.getOption().equals(Option.BOTH))) { - if (Math.abs(players.get(0).getPpp() - players.get(1).getPpp()) <= pppGap) { - return Mode.RANK; - } - return Mode.NORMAL; - } - if (!players.get(0).getOption().equals(Option.BOTH)) { - return Mode.getEnumValue(players.get(0).getOption().getCode()); - } - return Mode.getEnumValue(players.get(1).getOption().getCode()); - } -} diff --git a/src/main/java/com/gg/server/domain/game/type/StatusType.java b/src/main/java/com/gg/server/domain/game/type/StatusType.java deleted file mode 100644 index af6d4c199..000000000 --- a/src/main/java/com/gg/server/domain/game/type/StatusType.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.game.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum StatusType { - - BEFORE("before", "๊ฒŒ์ž„ ์‹œ์ž‘ ์ „"), - LIVE("live", "๊ฒŒ์ž„ ์ง„ํ–‰ ์ค‘"), - WAIT("wait", "๊ฒŒ์ž„ ๋๋‚˜๊ณ  ์ ์ˆ˜์ž…๋ ฅ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ"), - END("end", "๊ฒŒ์ž„์ด ๋๋‚˜๊ณ  ์ ์ˆ˜์ž…๋ ฅ๋„ ์™„๋ฃŒ"); - - private final String code; - private final String desc; - - @JsonCreator - public static StatusType getEnumFromValue(String value) { - for(StatusType e : values()) { - if(e.name().equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/item/controller/ItemController.java b/src/main/java/com/gg/server/domain/item/controller/ItemController.java deleted file mode 100644 index 9b3d7df3a..000000000 --- a/src/main/java/com/gg/server/domain/item/controller/ItemController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gg.server.domain.item.controller; - -import com.gg.server.domain.item.dto.ItemGiftRequestDto; -import com.gg.server.domain.item.dto.ItemStoreListResponseDto; -import com.gg.server.domain.item.dto.UserItemListResponseDto; -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/items") -public class ItemController { - - private final ItemService itemService; - - @GetMapping("/store") - public ItemStoreListResponseDto getAllItems() { - return itemService.getAllItems(); - } - - @PostMapping("/purchases/{itemId}") - public ResponseEntity purchaseItem(@PathVariable Long itemId, - @Parameter(hidden = true) @Login UserDto userDto) { - itemService.purchaseItem(itemId, userDto); - return new ResponseEntity(HttpStatus.CREATED); - } - - @PostMapping("/gift/{itemId}") - public ResponseEntity giftItem(@PathVariable Long itemId, - @RequestBody ItemGiftRequestDto recipient, - @Parameter(hidden = true) @Login UserDto userDto) { - itemService.giftItem(itemId, recipient.getOwnerId(), userDto); - return new ResponseEntity(HttpStatus.CREATED); - } - - @GetMapping - public UserItemListResponseDto getItemByUser(@ModelAttribute @Valid PageRequestDto req, - @Parameter(hidden = true) @Login UserDto userDto) { - Pageable pageable = PageRequest.of(req.getPage() - 1, req.getSize(), - Sort.by("createdAt").descending()); - return itemService.getItemByUser(userDto, pageable); - } - -} diff --git a/src/main/java/com/gg/server/domain/item/data/Item.java b/src/main/java/com/gg/server/domain/item/data/Item.java deleted file mode 100644 index 651de5fb6..000000000 --- a/src/main/java/com/gg/server/domain/item/data/Item.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.gg.server.domain.item.data; - -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.domain.item.type.ItemType; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -public class Item { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "name", length = 30) - private String name; - - @Column(name = "main_content", length = 255) - private String mainContent; - - @Column(name = "sub_content", length = 255) - private String subContent; - - @Column(name = "image_uri", length = 255) - private String imageUri; - - @NotNull - @Column(name = "price") - private Integer price; - - @NotNull - @Column(name = "is_visible") - private Boolean isVisible; - - @Column(name = "discount") - private Integer discount; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "type") - private ItemType type; - - @NotNull - @Column(name = "created_at") - private LocalDateTime createdAt; - - @NotNull - @Column(name = "creator_intra_id", length = 10) - private String creatorIntraId; - - @Column(name = "deleter_intra_id", length = 10) - private String deleterIntraId; - - public Item(String name, String mainContent, String subContent, String imageUri, Integer price, - Boolean isVisible, Integer discount, ItemType type, LocalDateTime createdAt, String creatorIntraId) { - this.name = name; - this.mainContent = mainContent; - this.subContent = subContent; - this.imageUri = imageUri; - this.price = price; - this.isVisible = isVisible; - this.discount = discount; - this.type = type; - this.createdAt = createdAt; - this.creatorIntraId = creatorIntraId; - } - - @Builder - public Item(ItemUpdateRequestDto updateRequestDto, String creatorIntraId, String itemImageUri) { - this.name = updateRequestDto.getName(); - this.mainContent = updateRequestDto.getMainContent(); - this.subContent = updateRequestDto.getSubContent(); - this.imageUri = itemImageUri; - this.price = updateRequestDto.getPrice(); - this.discount = updateRequestDto.getDiscount(); - this.isVisible = true; - this.creatorIntraId = creatorIntraId; - this.createdAt = LocalDateTime.now(); - this.type = updateRequestDto.getItemType(); - } - - public void imageUpdate(String imageUri) { - this.imageUri = imageUri; - } - - public void setVisibility(String intraId) { - this.isVisible = false; - this.deleterIntraId = intraId; - } - - @Override - public String toString() { - return "Item{" + - "id=" + id + - ", name='" + name + '\'' + - ", mainContent='" + mainContent + '\'' + - ", subContent='" + subContent + '\'' + - ", imageUri='" + imageUri + '\'' + - ", price=" + price + - ", isVisible=" + isVisible + - ", discount=" + discount + - ", createdAt=" + createdAt + - ", creatorIntraId='" + creatorIntraId + '\'' + - ", deleterIntraId='" + deleterIntraId + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/data/ItemRepository.java b/src/main/java/com/gg/server/domain/item/data/ItemRepository.java deleted file mode 100644 index ef6f26fd8..000000000 --- a/src/main/java/com/gg/server/domain/item/data/ItemRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.data; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import java.util.List; - -public interface ItemRepository extends JpaRepository { - @Query("SELECT i FROM Item i WHERE i.isVisible = true ORDER BY i.createdAt DESC") - List findAllByCreatedAtDesc(); -} diff --git a/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java b/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java deleted file mode 100644 index 6fcab5174..000000000 --- a/src/main/java/com/gg/server/domain/item/data/UserItemRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.item.data; - -import com.gg.server.domain.receipt.data.Receipt; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface UserItemRepository extends JpaRepository { - - @Query("select r from Receipt r where r.ownerIntraId = :intraId " + - "and (r.status = 'BEFORE' or r.status = 'USING' or r.status = 'WAITING') order by r.createdAt desc") - Page findByOwnerIntraId(@Param("intraId") String intraId, Pageable pageable); -} diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java deleted file mode 100644 index 4085b5eac..000000000 --- a/src/main/java/com/gg/server/domain/item/dto/ItemGiftRequestDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.domain.item.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class ItemGiftRequestDto { - private String ownerId; -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java deleted file mode 100644 index 702ac6950..000000000 --- a/src/main/java/com/gg/server/domain/item/dto/ItemStoreListResponseDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.item.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@NoArgsConstructor -@Getter -public class ItemStoreListResponseDto { - private List itemList; - - public ItemStoreListResponseDto(List itemList){ - this.itemList = itemList; - } -} diff --git a/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java deleted file mode 100644 index 4ecc4bb46..000000000 --- a/src/main/java/com/gg/server/domain/item/dto/ItemStoreResponseDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.domain.item.dto; - -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.type.ItemType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class ItemStoreResponseDto { - private Long itemId; - private String itemName; - private String mainContent; - private String subContent; - private ItemType itemType; - private String imageUri; - private Integer originalPrice; - private Integer discount; - private Integer salePrice; - - public ItemStoreResponseDto(Item item) { - this.itemId = item.getId(); - this.itemName = item.getName(); - this.mainContent = item.getMainContent(); - this.subContent = item.getSubContent(); - this.itemType = item.getType(); - this.imageUri = item.getImageUri(); - this.originalPrice = item.getPrice(); - this.discount = item.getDiscount(); - this.salePrice = this.originalPrice - (this.originalPrice * this.discount / 100); - } -} diff --git a/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java deleted file mode 100644 index 230d00524..000000000 --- a/src/main/java/com/gg/server/domain/item/dto/UserItemListResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.item.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class UserItemListResponseDto { - private List storageItemList; - private Integer totalPage; - - public UserItemListResponseDto(List storageItemList, Integer totalPage){ - this.storageItemList = storageItemList; - this.totalPage = totalPage; - } - -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java b/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java deleted file mode 100644 index a2e5d49bd..000000000 --- a/src/main/java/com/gg/server/domain/item/dto/UserItemResponseDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.item.dto; - -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.type.ItemStatus; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserItemResponseDto { - private Long receiptId; - private String itemName; - private String imageUri; - private String purchaserIntra; - private ItemStatus itemStatus; - private ItemType itemType; - - public UserItemResponseDto(Receipt receipt) { - Item item = receipt.getItem(); - this.receiptId = receipt.getId(); - this.itemName = item.getName(); - this.imageUri = item.getImageUri(); - this.purchaserIntra = receipt.getPurchaserIntraId(); - this.itemStatus = receipt.getStatus(); - this.itemType = item.getType(); - } - -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java b/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java deleted file mode 100644 index aefb4d198..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/InsufficientGgcoinException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class InsufficientGgcoinException extends BusinessException { - public InsufficientGgcoinException() { - super("GGcoin์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค.", ErrorCode.INSUFFICIENT_GGCOIN); - } -} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java deleted file mode 100644 index 8c8dd7561..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemImageLargeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class ItemImageLargeException extends FileException { - public ItemImageLargeException() { - super("์ด๋ฏธ์ง€ ํŒŒ์ผ 50KB ์ดˆ๊ณผ", ErrorCode.USER_IMAGE_TOO_LARGE); - } -} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java deleted file mode 100644 index 34955934f..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemImageTypeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class ItemImageTypeException extends FileException { - public ItemImageTypeException() { - super("์ด๋ฏธ์ง€ ํƒ€์ž…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค", ErrorCode.ITEM_IMAGE_WRONG_TYPE); - } -} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java deleted file mode 100644 index ab807ed84..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemNotAvailableException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class ItemNotAvailableException extends FileException { - public ItemNotAvailableException() { - super("์•„์ดํ…œ ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค", ErrorCode.ITEM_NOT_AVAILABLE); - } -} diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java deleted file mode 100644 index 88e74d13f..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class ItemNotFoundException extends NotExistException { - public ItemNotFoundException() { - super("ํ•ด๋‹น ์•„์ดํ…œ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.ITEM_NOT_FOUND); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java b/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java deleted file mode 100644 index 170bfc7b5..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemNotPurchasableException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class ItemNotPurchasableException extends BusinessException { - public ItemNotPurchasableException() { - super("์ง€๊ธˆ์€ ๊ตฌ๋งคํ•  ์ˆ˜ ์—†๋Š” ์•„์ดํ…œ ์ž…๋‹ˆ๋‹ค.", ErrorCode.ITEM_NOT_PURCHASABLE); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java b/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java deleted file mode 100644 index 4e39acfe5..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/ItemTypeException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class ItemTypeException extends BusinessException { - public ItemTypeException() {super("์•„์ดํ…œ ํƒ€์ž… ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.ITEM_TYPE_NOT_MATCHED);} -} diff --git a/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java b/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java deleted file mode 100644 index e85c4190e..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/KakaoGiftException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class KakaoGiftException extends BusinessException { - public KakaoGiftException() { - super("์นด์นด์˜ค ๊ฒŒ์ŠคํŠธ๋Š” ์„ ๋ฌผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.GUEST_ROLE_GIFT_FORBIDDEN); - } -} diff --git a/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java b/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java deleted file mode 100644 index 2164fb165..000000000 --- a/src/main/java/com/gg/server/domain/item/exception/KakaoPurchaseException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.item.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class KakaoPurchaseException extends BusinessException { - public KakaoPurchaseException() { - super("์นด์นด์˜ค ๊ฒŒ์ŠคํŠธ๋Š” ๊ตฌ๋งคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.GUEST_ROLE_PURCHASE_FORBIDDEN); - } -} - diff --git a/src/main/java/com/gg/server/domain/item/service/ItemService.java b/src/main/java/com/gg/server/domain/item/service/ItemService.java deleted file mode 100644 index 71268b568..000000000 --- a/src/main/java/com/gg/server/domain/item/service/ItemService.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.gg.server.domain.item.service; - -import com.gg.server.domain.coin.service.UserCoinChangeService; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.data.ItemRepository; -import com.gg.server.domain.item.data.UserItemRepository; -import com.gg.server.domain.item.dto.ItemStoreListResponseDto; -import com.gg.server.domain.item.dto.ItemStoreResponseDto; -import com.gg.server.domain.item.dto.UserItemListResponseDto; -import com.gg.server.domain.item.dto.UserItemResponseDto; -import com.gg.server.domain.item.exception.*; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.data.ReceiptRepository; -import com.gg.server.domain.receipt.exception.ItemStatusException; -import com.gg.server.domain.receipt.exception.ReceiptNotOwnerException; -import com.gg.server.domain.receipt.type.ItemStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RoleType; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class ItemService { - - private final ItemRepository itemRepository; - private final ReceiptRepository receiptRepository; - private final UserRepository userRepository; - private final UserItemRepository userItemRepository; - private final NotiService notiService; - private final UserCoinChangeService userCoinChangeService; - - @Transactional(readOnly = true) - public ItemStoreListResponseDto getAllItems() { - - List itemStoreListResponseDto = itemRepository.findAllByCreatedAtDesc() - .stream().map(ItemStoreResponseDto::new).collect(Collectors.toList()); - return new ItemStoreListResponseDto(itemStoreListResponseDto); - } - - @Transactional - public void purchaseItem(Long itemId, UserDto userDto) { - Item item = itemRepository.findById(itemId) - .orElseThrow(() -> { - throw new ItemNotFoundException(); - }); - if (!item.getIsVisible()) { - throw new ItemNotPurchasableException(); - } - - //์„ธ์ผ๊ฐ€๊ฒฉ ์กด์žฌํ• ๋•Œ ์„ธ์ผ๊ฐ€๋กœ ๊ฒฐ์ • - Integer finalPrice; - if (item.getDiscount() != null && item.getDiscount() > 0) { - finalPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); - } else { - finalPrice = item.getPrice(); - } - - User payUser = userRepository.findById(userDto.getId()) - .orElseThrow(() -> new UserNotFoundException()); - - if (payUser.getRoleType() == RoleType.GUEST) { - throw new KakaoPurchaseException(); - } - - userCoinChangeService.purchaseItemCoin(item, finalPrice, userDto.getId()); - - Receipt receipt = new Receipt(item, userDto.getIntraId(), userDto.getIntraId(), - ItemStatus.BEFORE, LocalDateTime.now()); - receiptRepository.save(receipt); - } - - @Transactional - public void giftItem(Long itemId, String ownerId, UserDto userDto) { - Item item = itemRepository.findById(itemId) - .orElseThrow(() -> { - throw new ItemNotFoundException(); - }); - if (!item.getIsVisible()) { - throw new ItemNotPurchasableException(); - } - - //์„ธ์ผ๊ฐ€๊ฒฉ ์กด์žฌํ• ๋•Œ ์„ธ์ผ๊ฐ€๋กœ ๊ฒฐ์ • - Integer finalPrice; - if (item.getDiscount() != null && item.getDiscount() > 0) { - finalPrice = item.getPrice() - (item.getPrice() * item.getDiscount() / 100); - } else { - finalPrice = item.getPrice(); - } - - User payUser = userRepository.findById(userDto.getId()) - .orElseThrow(UserNotFoundException::new); - - if (payUser.getRoleType() == RoleType.GUEST) { - throw new KakaoPurchaseException(); - } - - User owner = userRepository.findByIntraId(ownerId) - .orElseThrow(UserNotFoundException::new); - - if (owner.getRoleType() == RoleType.GUEST) { - throw new KakaoGiftException(); - } - - userCoinChangeService.giftItemCoin(item, finalPrice, payUser, owner); - - Receipt receipt = new Receipt(item, userDto.getIntraId(), ownerId, - ItemStatus.BEFORE, LocalDateTime.now()); - receiptRepository.save(receipt); - notiService.createGiftNoti(owner, payUser, item.getName()); - } - - @Transactional(readOnly = true) - public UserItemListResponseDto getItemByUser(UserDto userDto, Pageable pageable) { - Page receipts = userItemRepository.findByOwnerIntraId(userDto.getIntraId(), pageable); - Page responseDtos = receipts.map(UserItemResponseDto::new); - return new UserItemListResponseDto(responseDtos.getContent(), responseDtos.getTotalPages()); - } - - public void checkItemOwner(User loginUser, Receipt receipt) { - if (!receipt.getOwnerIntraId().equals(loginUser.getIntraId())) - throw new ReceiptNotOwnerException(); - } - - public void checkItemType(Receipt receipt, ItemType itemType) { - if (!receipt.getItem().getType().equals(itemType)) - throw new ItemTypeException(); - } - - public void checkItemStatus(Receipt receipt) { - if (receipt.getItem().getType().equals(ItemType.MEGAPHONE)) { - if (!(receipt.getStatus().equals(ItemStatus.WAITING) || receipt.getStatus().equals(ItemStatus.USING))) throw new ItemStatusException(); - } else { - if (!receipt.getStatus().equals(ItemStatus.BEFORE)) throw new ItemStatusException(); - } - } -} diff --git a/src/main/java/com/gg/server/domain/item/type/ItemType.java b/src/main/java/com/gg/server/domain/item/type/ItemType.java deleted file mode 100644 index 1bfafaae1..000000000 --- a/src/main/java/com/gg/server/domain/item/type/ItemType.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.domain.item.type; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public enum ItemType { - MEGAPHONE, BACKGROUND, EDGE, TEXT_COLOR, PROFILE_IMAGE - -} diff --git a/src/main/java/com/gg/server/domain/match/controller/MatchController.java b/src/main/java/com/gg/server/domain/match/controller/MatchController.java deleted file mode 100644 index afbc4bade..000000000 --- a/src/main/java/com/gg/server/domain/match/controller/MatchController.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.gg.server.domain.match.controller; - -import com.gg.server.domain.match.dto.MatchRequestDto; -import com.gg.server.domain.match.dto.MatchStatusResponseListDto; -import com.gg.server.domain.match.dto.SlotStatusResponseListDto; -import com.gg.server.domain.match.service.MatchService; -import com.gg.server.domain.match.service.MatchFindService; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import java.time.LocalDateTime; -import javax.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -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; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/match") -public class MatchController { - private final MatchService matchService; - private final MatchFindService matchFindService; - - /** - * ์œ ์ € ์Šฌ๋กฏ ์ž…์žฅ ์š”์ฒญ API (== ๋งค์นญ ์š”์ฒญ API) - * @param matchRequestDto - * @param user ๋งค์นญ ์š”์ฒญํ•œ ์œ ์ € - * @return 201 (Created) - */ - @PostMapping - public ResponseEntity createUserMatch(@RequestBody @Valid MatchRequestDto matchRequestDto, - @Parameter(hidden = true) @Login UserDto user) { - matchService.makeMatch(user, matchRequestDto.getOption(), matchRequestDto.getStartTime()); - return ResponseEntity.status(HttpStatus.CREATED).build(); - } - @DeleteMapping - public ResponseEntity deleteUserMatch(@RequestParam("startTime") - @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") LocalDateTime startTime, - @Parameter(hidden = true) @Login UserDto user) { - matchService.cancelMatch(user, startTime); - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } - - /** - * ํŠน์ • ์‹œ๊ฐ„๋Œ€์˜ ๊ฒฝ๊ธฐ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ์กฐํšŒ API - * @param mode : BOTH, NORMAL, RANK - * @param user - * @return - */ - @GetMapping("/time/scope") - public SlotStatusResponseListDto getMatchTimeScope(@RequestParam (required = true) String mode, - @Parameter(hidden = true) @Login UserDto user){ - return matchFindService.getAllMatchStatus(user, Option.getEnumValue(mode)); - } - - @GetMapping - public MatchStatusResponseListDto getCurrentMatch(@Parameter(hidden = true) @Login UserDto user) { - return matchFindService.getCurrentMatch(user); - } - -} diff --git a/src/main/java/com/gg/server/domain/match/data/RedisMatchTime.java b/src/main/java/com/gg/server/domain/match/data/RedisMatchTime.java deleted file mode 100644 index 8d9f887a7..000000000 --- a/src/main/java/com/gg/server/domain/match/data/RedisMatchTime.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.domain.match.data; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import com.gg.server.domain.match.type.Option; -import java.io.Serializable; -import java.time.LocalDateTime; -import javax.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.redis.core.RedisHash; - -@Getter -@RedisHash("matchTime") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RedisMatchTime implements Serializable { - @Id - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime startTime; - private Option option; - - public RedisMatchTime(LocalDateTime startTime, Option option) { - this.startTime = startTime; - this.option = option; - } -} diff --git a/src/main/java/com/gg/server/domain/match/data/RedisMatchTimeRepository.java b/src/main/java/com/gg/server/domain/match/data/RedisMatchTimeRepository.java deleted file mode 100644 index 5e4bf8dd3..000000000 --- a/src/main/java/com/gg/server/domain/match/data/RedisMatchTimeRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.domain.match.data; - -import com.gg.server.domain.match.type.MatchKey; -import com.gg.server.domain.user.exception.UserNotFoundException; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class RedisMatchTimeRepository { - private final RedisTemplate redisTemplate; - - public void addMatchUser(LocalDateTime startTime, RedisMatchUser redisMatchUser) { - redisTemplate.opsForList().rightPush(MatchKey.getTime(startTime), redisMatchUser); - } - public List getAllMatchUsers(LocalDateTime startTime) { - ListOperations listOperations = redisTemplate.opsForList(); - return listOperations.range(MatchKey.getTime(startTime), 0, - 1); - } - - public void setMatchTimeWithExpiry(LocalDateTime startTime) { - LocalDateTime now = LocalDateTime.now(); - Duration duration = Duration.between(now, startTime); - redisTemplate.expire(MatchKey.getTime(startTime), duration.getSeconds(), TimeUnit.SECONDS); - } - - public void deleteMatchTime(LocalDateTime startTime) {//๋งค์นญ์ด ๋˜๊ฑฐ๋‚˜ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด key๋ฅผ ์ง€์›Œ์ค€๋‹ค. - redisTemplate.delete(MatchKey.getTime(startTime)); - } - - public void deleteMatchUser(LocalDateTime startTime, RedisMatchUser matchUser) { - redisTemplate.opsForList().remove(MatchKey.getTime(startTime),0, matchUser); - } - - public Set getAllEnrolledStartTimes() { - Set keys = redisTemplate.keys(MatchKey.getAllTime() + "*"); - Integer prefixIdx = MatchKey.getAllTime().length(); - return keys.stream().map(str -> LocalDateTime.parse(str.substring(prefixIdx))) - .collect(Collectors.toSet()); - } - -} diff --git a/src/main/java/com/gg/server/domain/match/data/RedisMatchUser.java b/src/main/java/com/gg/server/domain/match/data/RedisMatchUser.java deleted file mode 100644 index fddaee444..000000000 --- a/src/main/java/com/gg/server/domain/match/data/RedisMatchUser.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.domain.match.data; - -import com.gg.server.domain.match.type.Option; -import java.io.Serializable; -import javax.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.redis.core.RedisHash; - -@Getter -@RedisHash("matchUser") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RedisMatchUser implements Serializable { - @Id - private Long userId; - private Integer ppp; - private Option option; - - public RedisMatchUser(Long userId, Integer ppp, Option option) { - this.userId = userId; - this.ppp = ppp; - this.option = option; - } -} diff --git a/src/main/java/com/gg/server/domain/match/data/RedisMatchUserRepository.java b/src/main/java/com/gg/server/domain/match/data/RedisMatchUserRepository.java deleted file mode 100644 index 198bcd39d..000000000 --- a/src/main/java/com/gg/server/domain/match/data/RedisMatchUserRepository.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gg.server.domain.match.data; - -import com.gg.server.domain.match.exception.PastSlotException; -import com.gg.server.domain.match.type.MatchKey; -import com.gg.server.domain.match.type.Option; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class RedisMatchUserRepository { - private final RedisTemplate redisTemplate; - - /** - * key : userId : startTime - * value : startTime - * slot์˜ startTime ๊ฐ๊ฐ์˜ ๋งŒ๋ฃŒ๊ธฐํ•œ ์„ค์ • - * **/ - public void addMatchTime(Long userId, LocalDateTime startTime, Option option) { - Duration duration = Duration.between(LocalDateTime.now(), startTime); - if (duration.isNegative()) { - throw new PastSlotException(); - } - redisTemplate.opsForValue().set(MatchKey.getUserTime(userId, startTime), - new RedisMatchTime(startTime, option), duration.getSeconds(), TimeUnit.SECONDS); - - } - public void deleteMatchUser(Long userId) { - Set keys = redisTemplate.keys(MatchKey.getUser(userId) + "*"); - keys.stream().forEach(key -> redisTemplate.delete(key)); - } - - public void deleteMatchTime(Long userId, LocalDateTime startTime) { - redisTemplate.delete(MatchKey.getUserTime(userId, startTime)); - } - public int countMatchTime(Long userId) { - return redisTemplate.keys(MatchKey.getUser(userId) + "*").size(); - } - - public Set getAllMatchTime(Long userId){ - Set keys = redisTemplate.keys(MatchKey.getUser(userId) + "*"); - return keys.stream().map(key -> redisTemplate.opsForValue().get(key)).collect(Collectors.toSet()); - } - - public Optional getUserTime(Long userId, LocalDateTime startTime) { - return Optional.ofNullable(redisTemplate.opsForValue().get(MatchKey.getUserTime(userId, startTime))); - } -} diff --git a/src/main/java/com/gg/server/domain/match/dto/GameAddDto.java b/src/main/java/com/gg/server/domain/match/dto/GameAddDto.java deleted file mode 100644 index 1b49f0054..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/GameAddDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gg.server.domain.match.dto; - -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.dto.UserDto; -import java.time.LocalDateTime; -import java.util.List; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor (access = AccessLevel.PROTECTED) -public class GameAddDto { - private LocalDateTime startTime; - private Season season; - private Long playerId; - private Long enemyId; - private Mode mode; - - public GameAddDto(LocalDateTime startTime, Season season, RedisMatchUser player, - RedisMatchUser enemy) { - this.startTime = startTime; - this.season = season; - this.playerId = player.getUserId(); - this.enemyId = enemy.getUserId(); - this.mode = Mode.ofPlayers(List.of(player, enemy), season.getPppGap()); - } - -} diff --git a/src/main/java/com/gg/server/domain/match/dto/MatchRequestDto.java b/src/main/java/com/gg/server/domain/match/dto/MatchRequestDto.java deleted file mode 100644 index 6ccf4a96c..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/MatchRequestDto.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.match.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.gg.server.domain.match.type.Option; -import java.time.LocalDateTime; -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class MatchRequestDto { - - @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") - private LocalDateTime startTime; - @NotNull - @JsonProperty("mode") - private Option option; - - public MatchRequestDto(LocalDateTime startTime, Option option) { - this.startTime = startTime; - this.option = option; - } -} diff --git a/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java b/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java deleted file mode 100644 index d5fd38774..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/MatchStatusDto.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.gg.server.domain.match.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.data.RedisMatchTime; -import com.gg.server.domain.slotmanagement.SlotManagement; - -import java.time.LocalDateTime; -import java.util.List; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class MatchStatusDto { - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime startTime; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime endTime; - private Boolean isMatched; - private Boolean isImminent; - private List myTeam; - private List enemyTeam; - - public MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement) { - this.startTime = game.getStartTime(); - this.endTime = game.getEndTime(); - this.isMatched = true; - this.isImminent = game.getStartTime().minusMinutes(slotManagement.getOpenMinute()) - .isBefore(LocalDateTime.now()); - if (game.getMode() == Mode.TOURNAMENT) isImminent = true; - this.myTeam = List.of(userIntraId); - this.enemyTeam = List.of(enemyIntraId); - - } - - public MatchStatusDto(RedisMatchTime redisMatchTime, Integer interval) { - this.startTime = redisMatchTime.getStartTime(); - this.endTime = redisMatchTime.getStartTime().plusMinutes(interval); - this.isMatched = false; - this.isImminent = false; - this.myTeam = List.of(); - this.enemyTeam = List.of(); - } - - @Override - public String toString() { - return "CurrentMatchResponseDto{" + - "startTime=" + startTime + - "endTIme=" + endTime + - ", myTeam=" + myTeam + - ", enemyTeam=" + enemyTeam + - ", isMatched=" + isMatched + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/match/dto/MatchStatusResponseListDto.java b/src/main/java/com/gg/server/domain/match/dto/MatchStatusResponseListDto.java deleted file mode 100644 index d7e149071..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/MatchStatusResponseListDto.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.domain.match.dto; - -import java.util.List; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -public class MatchStatusResponseListDto { - private List match; - - @Override - public String toString() { - return "MatchStatusResponseListDto{" + - "match=" + match + - '}'; - } - - public MatchStatusResponseListDto(List match) { - this.match = match; - } -} diff --git a/src/main/java/com/gg/server/domain/match/dto/SlotStatusDto.java b/src/main/java/com/gg/server/domain/match/dto/SlotStatusDto.java deleted file mode 100644 index 01e42d247..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/SlotStatusDto.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.domain.match.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.gg.server.domain.match.type.SlotStatus; -import java.time.LocalDateTime; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class SlotStatusDto { - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime startTime; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm", timezone = "Asia/Seoul") - private LocalDateTime endTime; - private String status; - - public SlotStatusDto(LocalDateTime startTime, LocalDateTime endTime, SlotStatus status) { - this.startTime = startTime; - this.endTime = endTime; - this.status = status.getCode(); - } - - public SlotStatusDto(LocalDateTime startTime, SlotStatus status, Integer interval) { - this.startTime = startTime; - this.endTime = startTime.plusMinutes(interval); - this.status = status.getCode(); - } - - @Override - public String toString() { - return "SlotStatusDto{" + - "startTime = " + startTime + - "endTime = " + endTime + - "status = " + status + - "}"; - } -} diff --git a/src/main/java/com/gg/server/domain/match/dto/SlotStatusResponseListDto.java b/src/main/java/com/gg/server/domain/match/dto/SlotStatusResponseListDto.java deleted file mode 100644 index e315c4736..000000000 --- a/src/main/java/com/gg/server/domain/match/dto/SlotStatusResponseListDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.domain.match.dto; - -import java.util.List; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class SlotStatusResponseListDto { - private List> matchBoards; - - @Override - public String toString() { - return "MatchStatusResponseListDto{" + - "matchBoards=" + matchBoards + - '}'; - } - - public SlotStatusResponseListDto(List> matchBoards) { - this.matchBoards = matchBoards; - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/EnrolledSlotException.java b/src/main/java/com/gg/server/domain/match/exception/EnrolledSlotException.java deleted file mode 100644 index 630dec02e..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/EnrolledSlotException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class EnrolledSlotException extends DuplicationException { - public EnrolledSlotException() { - super("์ด๋ฏธ ๋“ฑ๋ก๋œ ์Šฌ๋กฏ์ž…๋‹ˆ๋‹ค.", ErrorCode.SLOT_ENROLLED); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/LosingTeamNotFoundException.java b/src/main/java/com/gg/server/domain/match/exception/LosingTeamNotFoundException.java deleted file mode 100644 index c751aab43..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/LosingTeamNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class LosingTeamNotFoundException extends NotExistException { - public LosingTeamNotFoundException() { - super(ErrorCode.LOSING_TEAM_NOT_FOUND.getMessage(), ErrorCode.LOSING_TEAM_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/OptionInvalidException.java b/src/main/java/com/gg/server/domain/match/exception/OptionInvalidException.java deleted file mode 100644 index a55b9ae83..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/OptionInvalidException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; - -public class OptionInvalidException extends InvalidParameterException { - public OptionInvalidException() { - super("์กด์žฌํ•˜์ง€ ์•Š์€ mode ์ž…๋‹ˆ๋‹ค", ErrorCode.MODE_INVALID); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/PastSlotException.java b/src/main/java/com/gg/server/domain/match/exception/PastSlotException.java deleted file mode 100644 index 256e289f8..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/PastSlotException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ExpiredException; - -public class PastSlotException extends ExpiredException { - public PastSlotException() { - super("ํ˜„์žฌ ์‹œ๊ฐ ์ด์ „ ์Šฌ๋กฏ์€ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_PAST); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/PenaltyUserSlotException.java b/src/main/java/com/gg/server/domain/match/exception/PenaltyUserSlotException.java deleted file mode 100644 index 6f024302f..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/PenaltyUserSlotException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class PenaltyUserSlotException extends BusinessException { - public PenaltyUserSlotException() { - super("ํŒจ๋„ํ‹ฐ ๋ฐ›์€ ์œ ์ €๋Š” ๊ฒŒ์ž„์„ ๋“ฑ๋กํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.PENALTY_USER_ENROLLED); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/SlotCountException.java b/src/main/java/com/gg/server/domain/match/exception/SlotCountException.java deleted file mode 100644 index ec13b9825..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/SlotCountException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class SlotCountException extends BusinessException { - public SlotCountException() { - super("์Šฌ๋กฏ ๋“ฑ๋ก ํšŸ์ˆ˜ 3ํšŒ๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_COUNT_EXCEEDED); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/SlotNotFoundException.java b/src/main/java/com/gg/server/domain/match/exception/SlotNotFoundException.java deleted file mode 100644 index e54043199..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/SlotNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class SlotNotFoundException extends NotExistException { - public SlotNotFoundException() { - super("์œ ์ €๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SLOT_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/match/exception/WinningTeamNotFoundException.java b/src/main/java/com/gg/server/domain/match/exception/WinningTeamNotFoundException.java deleted file mode 100644 index 4b296b88f..000000000 --- a/src/main/java/com/gg/server/domain/match/exception/WinningTeamNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.match.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class WinningTeamNotFoundException extends NotExistException { - public WinningTeamNotFoundException() { - super(ErrorCode.WINNING_TEAM_NOT_FOUND.getMessage(), ErrorCode.WINNING_TEAM_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java b/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java deleted file mode 100644 index 2876bae0b..000000000 --- a/src/main/java/com/gg/server/domain/match/service/GameUpdateService.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.match.dto.GameAddDto; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.noti.service.SnsNotiService; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class GameUpdateService { - private final GameRepository gameRepository; - private final TeamRepository teamRepository; - private final UserRepository userRepository; - private final TeamUserRepository teamUserRepository; - private final SlotManagementRepository slotManagementRepository; - private final NotiService notiService; - private final SnsNotiService snsNotiService; - - /** - * ๊ฒŒ์ž„ ์ƒ์„ฑ ๋ฉ”์„œ๋“œ - * 1) ๊ฒŒ์ž„ ์ทจ์†Œํ–ˆ์„ ๊ฒฝ์šฐ, 2) ๊ฒŒ์ž„ ๋งค์นญ๋์„ ๊ฒฝ์šฐ, 3) ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ƒ์„ฑ - * @param addDto ๊ฒŒ์ž„ ์ƒ์„ฑ์— ํ•„์š”ํ•œ ์ •๋ณด - * @param recoveredUserId ๊ฒŒ์ž„ ์ทจ์†Œ ๋‹นํ•œ ์œ ์ €์˜ id, -1์ด๋ฉด ๋ฌด์˜๋ฏธํ•จ - */ - public void make(GameAddDto addDto, Long recoveredUserId) { - SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) - .orElseThrow(SlotNotFoundException::new); - Game game = new Game(addDto, slotManagement.getGameInterval()); - gameRepository.save(game); - Team enemyTeam = new Team(game, -1, false); - Team myTeam = new Team(game, -1, false); - List matchPair = List.of(enemyTeam, myTeam); - teamRepository.saveAll(matchPair); - User playerUser = userRepository.findById(addDto.getPlayerId()).orElseThrow(UserNotFoundException::new); - User enemyUser = userRepository.findById(addDto.getEnemyId()).orElseThrow(UserNotFoundException::new); - TeamUser myTeamUser = new TeamUser(myTeam, playerUser); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - List matchTeamUser = List.of(enemyTeamUser, myTeamUser); - teamUserRepository.saveAll(matchTeamUser); - if (!playerUser.getId().equals(recoveredUserId)) { - Noti playerNoti = notiService.createMatched(playerUser, addDto.getStartTime()); - snsNotiService.sendSnsNotification(playerNoti, UserDto.from(playerUser)); - } - if (!enemyUser.getId().equals(recoveredUserId)) { - Noti enemyNoti = notiService.createMatched(enemyUser, addDto.getStartTime()); - snsNotiService.sendSnsNotification(enemyNoti, UserDto.from(enemyUser)); - } - } - - public void delete(Game game, List enemyTeam) { - enemyTeam.forEach(enemy -> { - Noti noti = notiService.createMatchCancel(enemy, game.getStartTime()); - snsNotiService.sendSnsNotification(noti, UserDto.from(enemy)); - }); - gameRepository.delete(game); - } - - public void delete(Game game) { - gameRepository.delete(game); - } -} diff --git a/src/main/java/com/gg/server/domain/match/service/MatchFindService.java b/src/main/java/com/gg/server/domain/match/service/MatchFindService.java deleted file mode 100644 index 16ddb0543..000000000 --- a/src/main/java/com/gg/server/domain/match/service/MatchFindService.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.data.RedisMatchTime; -import com.gg.server.domain.match.data.RedisMatchTimeRepository; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.match.dto.MatchStatusDto; -import com.gg.server.domain.match.dto.MatchStatusResponseListDto; -import com.gg.server.domain.match.dto.SlotStatusResponseListDto; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.match.utils.SlotGenerator; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.type.RoleType; -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class MatchFindService { - private final SlotManagementRepository slotManagementRepository; - private final GameRepository gameRepository; - private final UserRepository userRepository; - private final RedisMatchUserRepository redisMatchUserRepository; - private final SeasonFindService seasonFindService; - private final RankRedisRepository rankRedisRepository; - private final RedisMatchTimeRepository redisMatchTimeRepository; - private final TierRepository tierRepository; - private final TournamentRepository tournamentRepository; - - - @Transactional(readOnly = true) - public MatchStatusResponseListDto getCurrentMatch(UserDto userDto) { - SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) - .orElseThrow(SlotNotFoundException::new); - Optional myGame = gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()); - if (myGame.isPresent()) { - List enemyTeam = userRepository.findEnemyByGameAndUser(myGame.get().getId(), userDto.getId()); - return new MatchStatusResponseListDto(List.of(new MatchStatusDto( - myGame.get(), userDto.getIntraId(), enemyTeam.get(0).getIntraId(), slotManagement - ))); - } - Set enrolledSlots = redisMatchUserRepository.getAllMatchTime(userDto.getId()); - List dtos = enrolledSlots.stream() - .map(e -> new MatchStatusDto(e, slotManagement.getGameInterval())) - .sorted(Comparator.comparing(MatchStatusDto::getStartTime)) - .collect(Collectors.toList()); - return new MatchStatusResponseListDto(dtos); - } - - @Transactional(readOnly = true) - public SlotStatusResponseListDto getAllMatchStatus(UserDto userDto, Option option) { - SlotManagement slotManagement = slotManagementRepository.findCurrent(LocalDateTime.now()) - .orElseThrow(SlotNotFoundException::new); - Season season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - RankRedis user; - if (userDto.getRoleType().equals(RoleType.GUEST)) { - user = RankRedis.from(userDto, season.getStartPpp(), tier.getImageUri()); - } else { - user = rankRedisRepository. - findRankByUserId(RedisKeyManager.getHashKey(season.getId()), userDto.getId()); - } - SlotGenerator slotGenerator = new SlotGenerator(user, slotManagement, season, option); - List games = gameRepository.findAllBetween(slotGenerator.getNow(), slotGenerator.getMaxTime()); - slotGenerator.addPastSlots(); - slotGenerator.addMatchedSlots(games); - List tournaments = tournamentRepository.findAllByStatusIsNot(TournamentStatus.END); - slotGenerator.addTournamentSlots(tournaments); - - Optional myGame = gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()); - Set gameTimes = games.stream().map(Game::getStartTime).collect(Collectors.toSet()); - if (myGame.isPresent()) { - groupEnrolledSlots(slotGenerator, myGame.get(), gameTimes); - } else { - groupEnrolledSlots(slotGenerator, gameTimes); - } - return slotGenerator.getResponseListDto(); - } - - private void groupEnrolledSlots(SlotGenerator slotGenerator, Game myGame, Set gameTimes) { - Set enrolledTimes = redisMatchTimeRepository.getAllEnrolledStartTimes(); - slotGenerator.addMySlots(myGame); - Set notMyEnrolledTimes = enrolledTimes.stream() - .filter(e -> !e.equals(myGame.getStartTime()) && !gameTimes.contains(e)) - .collect(Collectors.toSet()); - notMyEnrolledTimes.stream().forEach(time -> { - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(time); - slotGenerator.groupEnrolledSlot(time, allMatchUsers); - } - ); - } - private void groupEnrolledSlots(SlotGenerator slotGenerator, Set gameTimes) { - Set enrolledTimes = redisMatchTimeRepository.getAllEnrolledStartTimes(); - Set allMatchTime = redisMatchUserRepository.getAllMatchTime(slotGenerator.getMatchUser().getUserId()); - slotGenerator.addMySlots(allMatchTime); - Set times = allMatchTime.stream().map(RedisMatchTime::getStartTime) - .collect(Collectors.toSet()); - Set notMyEnrolledTimes = enrolledTimes.stream() - .filter(e -> !times.contains(e) && !gameTimes.contains(e)) - .collect(Collectors.toSet()); - notMyEnrolledTimes.stream().forEach( - time -> { - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(time); - slotGenerator.groupEnrolledSlot(time, allMatchUsers); - } - ); - } -} diff --git a/src/main/java/com/gg/server/domain/match/service/MatchService.java b/src/main/java/com/gg/server/domain/match/service/MatchService.java deleted file mode 100644 index 8734f66d5..000000000 --- a/src/main/java/com/gg/server/domain/match/service/MatchService.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.GameAlreadyExistException; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.data.RedisMatchTime; -import com.gg.server.domain.match.data.RedisMatchTimeRepository; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.match.dto.GameAddDto; -import com.gg.server.domain.match.exception.EnrolledSlotException; -import com.gg.server.domain.match.exception.PenaltyUserSlotException; -import com.gg.server.domain.match.exception.SlotCountException; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.match.utils.MatchCalculator; -import com.gg.server.domain.penalty.service.PenaltyService; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class MatchService { - private final RedisMatchTimeRepository redisMatchTimeRepository; - private final RedisMatchUserRepository redisMatchUserRepository; - private final SeasonFindService seasonFindService; - private final RankRedisRepository rankRedisRepository; - private final GameRepository gameRepository; - private final PenaltyService penaltyService; - private final GameUpdateService gameUpdateService; - private final UserRepository userRepository; - private final TournamentRepository tournamentRepository; - private final SlotManagementRepository slotManagementRepository; - - /** - * 1) ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์œ ์ € ์žˆ์„ ๊ฒฝ์šฐ : ๊ฒŒ์ž„ ์ƒ์„ฑ - * 2) ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์œ ์ € ์—†์„ ๊ฒฝ์šฐ : ์œ ์ €๋ฅผ ํ์— ๋„ฃ์–ด์คŒ - */ - @Transactional - public synchronized void makeMatch(UserDto userDto, Option option, LocalDateTime startTime) { - checkValid(userDto, startTime); - Season season = seasonFindService.findCurrentSeason(startTime); - RankRedis rank = rankRedisRepository - .findRankByUserId(RedisKeyManager.getHashKey(season.getId()), userDto.getId()); - RedisMatchUser player = new RedisMatchUser(userDto.getId(), rank.getPpp(), option); - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); - MatchCalculator matchCalculator = new MatchCalculator(season.getPppGap(), player); - Optional enemy = matchCalculator.findEnemy(allMatchUsers); - if (enemy.isPresent()) { - GameAddDto gameDto = new GameAddDto(startTime, season, player, enemy.get()); - gameUpdateService.make(gameDto, -1L); - redisMatchTimeRepository.addMatchUser(startTime, player); - cancelEnrolledSlots(List.of(enemy.get(), player), startTime); - } else { - addUserToQueue(startTime, player, option); - } - } - - /** - * 1) ๋งค์นญ๋˜์–ด ๊ฒŒ์ž„ ์ƒ์„ฑ๋œ ํ›„ : ๊ฒŒ์ž„ ์‚ญ์ œํ•˜๊ณ  ์•Œ๋ฆผ ์ „์†ก, ์ทจ์†Œํ•œ ์œ ์ € ํŒจ๋„ํ‹ฐ ๋ถ€๊ณผ - * ๋ณต๊ท€ ์œ ์ €๋Š” ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€ ์กด์žฌํ•˜๋ฉด ๋‹ค์‹œ ๋งค์นญํ•ด์ฃผ๊ณ  ์•„๋‹ˆ๋ฉด ์ทจ์†Œ ์•Œ๋ฆผ ๋ณด๋‚ด๊ณ  ํ์— ๋“ฑ๋ก ์‹œํ‚ด - * 2) ๋งค์นญ ์ „ : ํ์—์„œ ์œ ์ € ์‚ญ์ œ - * game ๋งค์นญ๋œ user ์ด์™ธ์— ๋‹ค๋ฅธ user๊ฐ€ ์ทจ์†Œํ•  ๊ฒฝ์šฐ, ์—๋Ÿฌ ๋ฐœ์ƒ - */ - @Transactional - public synchronized void cancelMatch(UserDto userDto, LocalDateTime startTime) { - Optional game = gameRepository.findByStartTime(startTime); - if (game.isPresent()) { - List enemyTeam = userRepository.findEnemyByGameAndUser(game.get().getId(), userDto.getId()); - if (enemyTeam.size() > 1) { - throw new SlotNotFoundException(); - } - if (game.get().getMode().equals(Mode.TOURNAMENT)) { - throw new BusinessException(ErrorCode.TOURNAMENT_GAME_CAN_NOT_CANCELED); - } - cancelGame(userDto, startTime, game.get(), enemyTeam); - } else { - deleteUserFromQueue(userDto, startTime); - } - } - - private void cancelGame(UserDto userDto, LocalDateTime startTime, Game game, List enemyTeam) { - /*์ทจ์†Œํ•œ ์œ ์ € ํ์—์„œ ์‚ญ์ œ ํ›„ ํŒจ๋„ํ‹ฐ ๋ถ€๊ณผ*/ - Long recoveredUserId = enemyTeam.get(0).getId(); - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); - RedisMatchUser penaltyUser = allMatchUsers.stream() - .filter(ele -> ele.getUserId().equals(userDto.getId())) - .findFirst() - .orElseThrow(UserNotFoundException::new); - RedisMatchUser recoveredUser = allMatchUsers.stream() - .filter(ele -> ele.getUserId().equals(recoveredUserId)) - .findFirst() - .orElseThrow(UserNotFoundException::new); - redisMatchTimeRepository.deleteMatchUser(startTime, penaltyUser); - penaltyService.givePenalty(userDto, 30); - /*์ทจ์†Œ ๋‹นํ•œ ์œ ์ € ๋งค์นญ ์ƒ๋Œ€ ์ฐพ๊ณ  ์žˆ์œผ๋ฉด ๋‹ค์‹œ ๊ฒŒ์ž„ ์ƒ์„ฑ ์•„๋‹ˆ๋ฉด ์ทจ์†Œ ์•Œ๋ฆผ*/ - Season season = seasonFindService.findCurrentSeason(startTime); - MatchCalculator matchCalculator = new MatchCalculator(season.getPppGap(), recoveredUser); - List targetPlayers = allMatchUsers.stream() - .filter(ele -> !ele.getUserId().equals(userDto.getId()) - && !ele.getUserId().equals(recoveredUserId)) - .collect(Collectors.toList()); - Optional enemy = matchCalculator.findEnemy(targetPlayers); - if (enemy.isPresent()) { - gameUpdateService.delete(game); - GameAddDto gameDto = new GameAddDto(startTime, season, recoveredUser, enemy.get()); - gameUpdateService.make(gameDto, recoveredUserId); - } else { - gameUpdateService.delete(game, enemyTeam); - redisMatchUserRepository.addMatchTime(recoveredUserId, startTime, recoveredUser.getOption()); - } - } - - /** - * ๋งค์นญ ์š”์ฒญ ์‹œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ - * @param userDto ๋งค์นญ ์š”์ฒญํ•œ ์œ ์ € - * @param startTime ๋งค์นญ ์š”์ฒญ ์‹œ๊ฐ„ - * @throws PenaltyUserSlotException ํŒจ๋„ํ‹ฐ ์œ ์ €์ผ ๊ฒฝ์šฐ - * @throws TournamentConflictException ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ - * @throws GameAlreadyExistException ๊ฒŒ์ž„์ด ์ด๋ฏธ ์กด์žฌํ•  ๊ฒฝ์šฐ - * @throws EnrolledSlotException ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์ด๋ฏธ ์žˆ์„ ๊ฒฝ์šฐ || ์œ ์ € ์ด๋ฏธ ํ์— ๋“ฑ๋กํ•  ๊ฒฝ์šฐ - * @throws SlotCountException 4๋ฒˆ ์ด์ƒ ๋งค์น˜ ๋„ฃ์„ ๊ฒฝ์šฐ - * - */ - private void checkValid(UserDto userDto, LocalDateTime startTime) { - if (penaltyService.isPenaltyUser(userDto.getIntraId())) { - throw new PenaltyUserSlotException(); - } - if (isExistTournamentNotEnded(startTime)) { - throw new TournamentConflictException(); - } - if (gameRepository.findByStartTime(startTime).isPresent()) { - throw new GameAlreadyExistException(); - } - if (gameRepository.findByStatusTypeAndUserId(StatusType.BEFORE, userDto.getId()).isPresent()) { - throw new EnrolledSlotException(); - } - //์œ ์ € ์ด๋ฏธ ํ์— ๋“ฑ๋ก ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ - if (redisMatchUserRepository.getUserTime(userDto.getId(), startTime).isPresent()) { - throw new EnrolledSlotException(); - } - //4๋ฒˆ ์ด์ƒ ๋งค์น˜ ๋„ฃ์„ ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ - if (redisMatchUserRepository.countMatchTime(userDto.getId()) >= 3) { - throw new SlotCountException(); - } - } - - private void addUserToQueue(LocalDateTime startTime, RedisMatchUser matchUser, Option option) { - redisMatchTimeRepository.addMatchUser(startTime, matchUser); - redisMatchTimeRepository.setMatchTimeWithExpiry(startTime); - redisMatchUserRepository.addMatchTime(matchUser.getUserId(), startTime, option); - } - - private void cancelEnrolledSlots(List players, LocalDateTime targetTIme) { - for (RedisMatchUser player : players) { - Set matchTimes = redisMatchUserRepository - .getAllMatchTime(player.getUserId()) - .stream() - .filter(ele -> !ele.getStartTime().equals(targetTIme)) - .collect(Collectors.toSet()); - matchTimes.forEach(ele -> redisMatchTimeRepository.deleteMatchUser(ele.getStartTime(), player)); - redisMatchUserRepository.deleteMatchUser(player.getUserId()); - } - } - - private void deleteUserFromQueue(UserDto userDto, LocalDateTime startTime) { - if (redisMatchUserRepository.getUserTime(userDto.getId(), startTime).isEmpty()) { - throw new SlotNotFoundException(); - } - redisMatchUserRepository.deleteMatchTime(userDto.getId(), startTime); - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(startTime); - for (RedisMatchUser matchUser : allMatchUsers) { - if (matchUser.getUserId().equals(userDto.getId())) { - redisMatchTimeRepository.deleteMatchUser(startTime, matchUser); - break; - } - } - } - - /** - * LIVE, BEFORE ์ƒํƒœ์ธ ํ† ๋„ˆ๋จผํŠธ์™€ ์ง„ํ–‰ ์‹œ๊ฐ„์ด ๊ฒน์น˜์ง€ ์•Š์œผ๋ฉด true, ๊ฒน์น˜๋ฉด false - * @param startTime ํ˜„์žฌ ์‹œ๊ฐ„ - * @return ์ข…๋ฃŒ๋˜์ง€ ์•Š์€ ํ† ๋„ˆ๋จผํŠธ ์žˆ์œผ๋ฉด true, ์—†์œผ๋ฉด false - * @throws SlotNotFoundException ํ˜„์žฌ ์‹œ๊ฐ„์— ํ•ด๋‹นํ•˜๋Š” ์Šฌ๋กฏ์ด ์—†์„ ๊ฒฝ์šฐ - */ - private boolean isExistTournamentNotEnded(LocalDateTime startTime) { - List tournamentList = tournamentRepository.findAllByStatusIsNot(TournamentStatus.END); - int gameInterval = slotManagementRepository.findCurrent(startTime) - .orElseThrow(SlotNotFoundException::new) - .getGameInterval(); - LocalDateTime endTime = startTime.plusMinutes(gameInterval); - for (Tournament tournament : tournamentList) { - if (startTime.isAfter(tournament.getStartTime()) && startTime.isBefore(tournament.getEndTime()) || - endTime.isAfter(tournament.getStartTime()) && endTime.isBefore(tournament.getEndTime())) { - return true; - } - if (startTime.isEqual(tournament.getStartTime()) || endTime.isEqual(tournament.getEndTime()) || - endTime.isEqual(tournament.getStartTime()) || startTime.isEqual(tournament.getEndTime())) { - return true; - } - } - return false; - } -} diff --git a/src/main/java/com/gg/server/domain/match/service/MatchTournamentService.java b/src/main/java/com/gg/server/domain/match/service/MatchTournamentService.java deleted file mode 100644 index 376b7fc4a..000000000 --- a/src/main/java/com/gg/server/domain/match/service/MatchTournamentService.java +++ /dev/null @@ -1,266 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.exception.EnrolledSlotException; -import com.gg.server.domain.match.exception.LosingTeamNotFoundException; -import com.gg.server.domain.match.exception.WinningTeamNotFoundException; -import com.gg.server.domain.match.type.TournamentMatchStatus; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.data.TournamentGameRepository; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.exception.TournamentGameNotFoundException; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import com.gg.server.domain.match.exception.SlotNotFoundException; - -import javax.transaction.Transactional; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import static com.gg.server.domain.match.type.TournamentMatchStatus.*; - - -@Service -@RequiredArgsConstructor -public class MatchTournamentService { - private final TournamentGameRepository tournamentGameRepository; - private final GameRepository gameRepository; - private final SlotManagementRepository slotManagementRepository; - private final SeasonFindService seasonFindService; - private final NotiAdminService notiAdminService; - - /** - * ํ† ๋„ˆ๋จผํŠธ ์ง„ํ–‰์ค‘ ๋‹ค์Œ ๋ผ์šด๋“œ ๊ฒŒ์ž„ ๋งค์นญ์ด ํ•„์š”ํ•œ์ง€ ํ™•์ธ - *

๊ฒฐ์Šน์ „ ์ ์ˆ˜ ์ž…๋ ฅ ํ›„ ํ† ๋„ˆ๋จผํŠธ END ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธ

- * @param game ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - * @return TournamentMatchStatus - ๋งค์นญ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ - * @throws TournamentGameNotFoundException ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - */ - @Transactional - public TournamentMatchStatus checkTournamentGame(Game game) { - TournamentGame tournamentGame = tournamentGameRepository.findByGameId(game.getId()) - .orElseThrow(TournamentGameNotFoundException::new); - - // ํ† ๋„ˆ๋จผํŠธ ๊ฒฐ์Šน์ „ ๊ฒŒ์ž„์ผ ๊ฒฝ์šฐ, ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ END๋กœ ๋ณ€๊ฒฝ - if (TournamentRound.THE_FINAL.equals(tournamentGame.getTournamentRound())) { - closeTournament(tournamentGame.getTournament(), game); - return IMPOSSIBLE; - } - - // ๊ฐ™์€ round์˜ ๋ชจ๋“  ๊ฒŒ์ž„์ด END์ธ ๊ฒฝ์šฐ, ๋‹ค์Œ round์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋งค์นญ ๊ฐ€๋Šฅ - TournamentRound round = tournamentGame.getTournamentRound(); - List tournamentGames = tournamentGameRepository.findAllByTournamentId(tournamentGame.getTournament().getId()); - List sameRoundGames = tournamentGames.stream() - .filter(tg -> tg.getTournamentRound().getRoundNumber() == round.getRoundNumber()) - .collect(Collectors.toList()); - for (TournamentGame tg : sameRoundGames) { - if (!StatusType.END.equals(tg.getGame().getStatus())) { - return IMPOSSIBLE; - } - } - if (isAlreadyExistMatchedGame(tournamentGame.getTournament(), round.getNextRound())) { - return ALREADY_MATCHED; - } - return POSSIBLE; - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋งค์นญ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ์ƒˆ๋กœ ๋งค์นญํ•  ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ - * @throws EnrolledSlotException ์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ - * @throws SlotNotFoundException ์Šฌ๋กฏ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - */ - @Transactional - public void matchGames(Tournament tournament, TournamentRound round) { - if (isAlreadyExistMatchedGame(tournament, round)) { - throw new EnrolledSlotException(); - } - Season season = seasonFindService.findCurrentSeason(tournament.getStartTime()); - SlotManagement slotManagement = slotManagementRepository.findCurrent(tournament.getStartTime()) - .orElseThrow(SlotNotFoundException::new); - int gameInterval = slotManagement.getGameInterval(); - List allTournamentGames = tournamentGameRepository.findAllByTournamentId(tournament.getId()); - List tournamentGames = findSameRoundGames(allTournamentGames, round.getRoundNumber()); - List players = findSortedPlayers(tournament, round); - LocalDateTime startTime = calculateStartTime(tournament, round, gameInterval); - - for (int i = 0; i < tournamentGames.size(); ++i) { - Game game = new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, startTime, startTime.plusMinutes(gameInterval)); - Team team1 = new Team(game, -1, false); - Team team2 = new Team(game, -1, false); - User user1 = players.get(i * 2); - User user2 = players.get(i * 2 + 1); - new TeamUser(team1, user1); - new TeamUser(team2, user2); - gameRepository.save(game); - tournamentGames.get(i).updateGame(game); - startTime = startTime.plusMinutes((long) gameInterval); - } - players.stream().distinct() - .forEach(user -> notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(user.getIntraId(), NotiType.TOURNAMENT_GAME_MATCHED.getMessage()))); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์˜ ์Šน์ž๋ฅผ ํ† ๋„ˆ๋จผํŠธ ๋‹ค์Œ ๋ผ์šด๋“œ์˜ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด์–ด๋กœ ์—…๋ฐ์ดํŠธ - * @param modifiedGame ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ๊ฐ€ ์ˆ˜์ •๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - * @param nextMatchedGame ์ˆ˜์ •๋œ ์šฐ์Šน์ž๋กœ ์ˆ˜์ •ํ•  ๋‹ค์Œ ๊ฒŒ์ž„ - * @throws WinningTeamNotFoundException ์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - */ - @Transactional - public void updateMatchedGameUser(Game modifiedGame, Game nextMatchedGame) { - User winner = getWinningTeam(modifiedGame).getTeamUsers().get(0).getUser(); - User loser = getLosingTeam(modifiedGame).getTeamUsers().get(0).getUser(); - List players = modifiedGame.getTeams().stream() - .map(team -> team.getTeamUsers().get(0).getUser()) - .collect(Collectors.toList()); - List nextMatchedGameTeamUsers = nextMatchedGame.getTeams().stream() - .map(team -> team.getTeamUsers().get(0)) - .collect(Collectors.toList()); - for (TeamUser nextGameTeamUser : nextMatchedGameTeamUsers) { - if (players.contains(nextGameTeamUser.getUser())) { - nextGameTeamUser.updateUser(winner); - break; - } - } - notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(winner.getIntraId(), NotiType.TOURNAMENT_GAME_MATCHED.getMessage())); - notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(loser.getIntraId(), NotiType.TOURNAMENT_GAME_CANCELED.getMessage())); - } - - /** - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ - * @param gameInterval ๊ฒฝ๊ธฐ ๊ฐ„๊ฒฉ - * @return ๋งˆ์ง€๋ง‰ ๊ฒฝ๊ธฐ ์ข…๋ฃŒ ์‹œ๊ฐ„ + interval - *

8๊ฐ•์˜ ๊ฒฝ์šฐ ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„

- *

4๊ฐ•, ๊ฒฐ์Šน์ผ ๊ฒฝ์šฐ ์ด์ „ ๋ผ์šด๋“œ์˜ ๋งˆ์ง€๋ง‰ ๊ฒฝ๊ธฐ ์ข…๋ฃŒ ์‹œ๊ฐ„ + 15๋ถ„

- */ - private LocalDateTime calculateStartTime(Tournament tournament, TournamentRound round, int gameInterval) { - if (TournamentRound.QUARTER_FINAL_1.getRoundNumber() == round.getRoundNumber()) { - return tournament.getStartTime(); - } - List previousRoundTournamentGames = findSameRoundGames(tournament.getTournamentGames(), TournamentRound.getPreviousRoundNumber(round)); - TournamentGame lastGame = previousRoundTournamentGames.get(previousRoundTournamentGames.size() - 1); - return lastGame.getGame().getEndTime().plusMinutes(gameInterval); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ์— ๋งค์นญ๋  ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์ฐพ๋Š”๋‹ค. - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ๋งค์นญํ•  ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ - * @return ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ์— ๋งค์นญ๋  ํ”Œ๋ ˆ์ด์–ด List (์ •๋ ฌ๋œ ์ƒํƒœ) - */ - private List findSortedPlayers(Tournament tournament, TournamentRound round) { - List players = new ArrayList<>(); - - if (TournamentRound.QUARTER_FINAL_1.getRoundNumber() == round.getRoundNumber()) { - Map randomNumbers = new LinkedHashMap<>(); - Random random = new Random(); - while (randomNumbers.size() < Tournament.ALLOWED_JOINED_NUMBER) { - int randomNumber = random.nextInt(Tournament.ALLOWED_JOINED_NUMBER); - if (!randomNumbers.containsValue(randomNumber)) { - randomNumbers.put(randomNumbers.size(), randomNumber); - } - } - for (Integer randomNumber : randomNumbers.values()) { - List tournamentUsers = tournament.getTournamentUsers(); - User user = tournamentUsers.get(randomNumber).getUser(); - players.add(user); - } - } else { - List previousRoundTournamentGames = findSameRoundGames(tournament.getTournamentGames(), TournamentRound.getPreviousRoundNumber(round)); - int roundNum = round.getRoundNumber(); - for (int i = 0; i < roundNum; ++i) { - User user = getWinningTeam(previousRoundTournamentGames.get(i).getGame()) - .getTeamUsers().get(0).getUser(); - players.add(user); - } - } - return players; - } - - /** - * round์— ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ - * @return true - ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌ, false - ์•„์ง ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ - * @throws TournamentGameNotFoundException ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - */ - private boolean isAlreadyExistMatchedGame(Tournament tournament, TournamentRound round) { - TournamentGame tournamentGame = tournamentGameRepository.findByTournamentIdAndTournamentRound(tournament.getId(), round) - .orElseThrow(TournamentGameNotFoundException::new); - return tournamentGame.getGame() != null; - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ํ•จ์ˆ˜ - *

ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ END๋กœ ์—…๋ฐ์ดํŠธ

- *

ํ† ๋„ˆ๋จผํŠธ winner ์—…๋ฐ์ดํŠธ

- * @param tournament ์ข…๋ฃŒํ•  ํ† ๋„ˆ๋จผํŠธ - * @param finalGame ํ† ๋„ˆ๋จผํŠธ์˜ ๋งˆ์ง€๋ง‰ ๊ฒŒ์ž„ - * @throws WinningTeamNotFoundException ์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ - */ - private void closeTournament(Tournament tournament, Game finalGame) { - User winner = getWinningTeam(finalGame) - .getTeamUsers().get(0).getUser(); - tournament.updateStatus(TournamentStatus.END); - tournament.updateEndTime(finalGame.getEndTime()); - tournament.updateWinner(winner); - - } - - /** - * ๊ฐ™์€ round์˜ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์„ ์ฐพ๋Š”๋‹ค. - * @param tournamentGames ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ List - * @param roundNum ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ number (2, 4, 8, ...) (์ž˜๋ชป๋œ roundNum์ผ ๊ฒฝ์šฐ Empty List ๋ฐ˜ํ™˜ํ•œ๋‹ค.) - * @return tournamentGames ์ค‘ roundNum๊ณผ ๋™์ผํ•œ roundNum์„ ๊ฐ€์ง„ round ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ tournamentGame List ๋ฐ˜ํ™˜ - */ - private List findSameRoundGames(List tournamentGames, int roundNum) { - return tournamentGames.stream() - .filter(tournamentGame -> roundNum == tournamentGame.getTournamentRound().getRoundNumber()) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - } - - /** - * game์˜ ์Šน์ž๋ฅผ ์ฐพ๋Š”๋‹ค. - * @param game - * @return - */ - private Team getWinningTeam(Game game) { - return game.getTeams().stream() - .filter(team -> Boolean.TRUE.equals(team.getWin())) - .findAny() - .orElseThrow(WinningTeamNotFoundException::new); - } - - /** - * game์˜ ํŒจ์ž๋ฅผ ์ฐพ๋Š”๋‹ค. - * @param game - * @return - */ - private Team getLosingTeam(Game game) { - return game.getTeams().stream() - .filter(team -> Boolean.FALSE.equals(team.getWin())) - .findAny() - .orElseThrow(LosingTeamNotFoundException::new); - } -} diff --git a/src/main/java/com/gg/server/domain/match/type/MatchKey.java b/src/main/java/com/gg/server/domain/match/type/MatchKey.java deleted file mode 100644 index 95854d051..000000000 --- a/src/main/java/com/gg/server/domain/match/type/MatchKey.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.match.type; - -import java.time.LocalDateTime; -import lombok.Getter; - -@Getter -public class MatchKey { - public static final String USER = "MATCH:USER:"; - public static final String TIME = "MATCH:TIME:"; - private static final String conjunctive = ":"; - - public static String getUserTime(Long userId, LocalDateTime startTime) { - return USER + userId + conjunctive + startTime; - } - - public static String getUser(Long userId) { - return USER + userId; - } - - public static String getTime(LocalDateTime startTime) { - return TIME + startTime; - } - - public static String getAllTime() { - return TIME; - } -} diff --git a/src/main/java/com/gg/server/domain/match/type/Option.java b/src/main/java/com/gg/server/domain/match/type/Option.java deleted file mode 100644 index 567ffe1c6..000000000 --- a/src/main/java/com/gg/server/domain/match/type/Option.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.domain.match.type; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.gg.server.domain.match.exception.OptionInvalidException; -import java.util.Locale; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum Option { - //match์—์„œ๋Š” Both๋ฅผ ์จ์„œ ์ž๋ฃŒํ˜• ๋”ฐ๋กœ ๋งŒ๋“ฌ - BOTH(0,"both"), - NORMAL(1,"normal"), - RANK(2,"rank"), - TOURNAMENT(3,"tournament"); - - // ๋ชจ๋“œ๋Š” 4๊ฐ€์ง€๊ฐ€ ์žˆ์Œ. - - private final Integer value; - private final String code; - - @JsonCreator(mode = JsonCreator.Mode.DELEGATING) - public static Option getEnumValue(String code) { - for(Option e : values()) { - if(e.code.equals(code)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(code.toUpperCase(Locale.ROOT))) - return e; - } - throw new OptionInvalidException(); - } - - -} diff --git a/src/main/java/com/gg/server/domain/match/type/SlotStatus.java b/src/main/java/com/gg/server/domain/match/type/SlotStatus.java deleted file mode 100644 index 7d168f548..000000000 --- a/src/main/java/com/gg/server/domain/match/type/SlotStatus.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.domain.match.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import java.util.Locale; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum SlotStatus { - OPEN("open"), - CLOSE("close"), - MYTABLE("mytable"), - MATCH("match"); - private final String code; - @JsonCreator - public static SlotStatus getEnumFromValue(String value) { - for (SlotStatus e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/match/type/TournamentMatchStatus.java b/src/main/java/com/gg/server/domain/match/type/TournamentMatchStatus.java deleted file mode 100644 index 849d31d92..000000000 --- a/src/main/java/com/gg/server/domain/match/type/TournamentMatchStatus.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.match.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.gg.server.domain.match.exception.OptionInvalidException; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum TournamentMatchStatus { - // ํ† ๋„ˆ๋จผํŠธ ๋งค์น˜ ์ƒํƒœ - IMPOSSIBLE(0, "๋งค์นญ ๋ถˆ๊ฐ€๋Šฅ"), - POSSIBLE(1, "๋งค์นญ ๊ฐ€๋Šฅ"), - ALREADY_MATCHED(2, "์ด๋ฏธ ๋งค์นญ๋จ"); - - private final Integer value; - private final String code; -} diff --git a/src/main/java/com/gg/server/domain/match/utils/MatchCalculator.java b/src/main/java/com/gg/server/domain/match/utils/MatchCalculator.java deleted file mode 100644 index 98da3f58b..000000000 --- a/src/main/java/com/gg/server/domain/match/utils/MatchCalculator.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.gg.server.domain.match.utils; - -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.match.type.SlotStatus; -import java.util.List; -import java.util.Optional; - -public class MatchCalculator { - private final Integer pppGap; - private final RedisMatchUser matchUser; - - - public MatchCalculator(Integer pppGap, RedisMatchUser matchUser) { - this.pppGap = pppGap; - this.matchUser = matchUser; - } - - /**์œ ์ €๋“ค์ด ์ž…์žฅํ•  ๋•Œ๋งˆ๋‹ค Queue ๋งค์นญ ๊ฒ€์‚ฌ - * ๋งˆ์ง€๋ง‰์œผ๋กœ ์ž…์žฅํ•œ ์œ ์ €๋ž‘ ๊ทธ์ „ ์œ ์ €๋“ค๋งŒ ๋น„๊ตํ•˜๋ฉด ๋œ๋‹ค. - * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ both : normal ์ž…์žฅ ์œ ์ €์™€ ๊ฒฝ๊ธฐ ๊ฐ€๋Šฅํ•œ rank ์ž…์žฅ ์œ ์ € ๋งค์นญ - * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ normal : normal user ํƒ์ƒ‰ - * ๋งˆ์ง€๋ง‰ ์ž…์žฅ ์œ ์ €๊ฐ€ rank : ๊ฒฝ๊ธฐ ๊ฐ€๋Šฅํ•œ rank ์ž…์žฅ ์œ ์ € ๋งค์นญ - * ์ด๋•Œ ํƒ์ƒ‰ ์šฐ์„  ์œ„๋Š” ๋จผ์ € ๋“ค์–ด์˜จ ์‚ฌ๋žŒ๋ถ€ํ„ฐ**/ - public Optional findEnemy(List allMatchUsers) { - if (allMatchUsers.size() == 0) { - return Optional.empty(); - } - if (matchUser.getOption().equals(Option.NORMAL)) { - return allMatchUsers.stream() - .filter(player -> player.getOption().equals(Option.NORMAL) || - player.getOption().equals(Option.BOTH)) - .findFirst(); - } - if (matchUser.getOption().equals(Option.RANK)) { - return allMatchUsers.stream() - .filter(player -> (player.getOption().equals(Option.RANK) || - player.getOption().equals(Option.BOTH)) - && Math.abs(player.getPpp() - matchUser.getPpp()) <= pppGap) - .findFirst(); - } - return allMatchUsers.stream() - .filter(player -> player.getOption().equals(Option.NORMAL) || - player.getOption().equals(Option.BOTH) || - (player.getOption().equals(Option.RANK) && - Math.abs(player.getPpp() - matchUser.getPpp())<= pppGap)) - .findFirst(); - } - - /** - * - * @param allMatchUsers : ํ์— ๋“ค์–ด์žˆ๋Š” ํ”Œ๋ ˆ์ด์–ด๋“ค - * @return 1) ๋งค์นญ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ: SlotStatus.MATCH - * 2) ๋งค์นญ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ: SlotStatus.OPEN - */ - public SlotStatus findEnemyStatus(List allMatchUsers) - { - if (matchUser.getOption().equals(Option.NORMAL)) { - return getNormalSlotStatus(allMatchUsers); - } - if (matchUser.getOption().equals(Option.RANK)) { - return getRankSlotStatus(allMatchUsers); - } - return getBothSlotStatus(allMatchUsers); - } - - private SlotStatus getRankSlotStatus(List allMatchUsers) { - if (allMatchUsers.stream().anyMatch(e -> (e.getOption().equals(Option.RANK) - || e.getOption().equals(Option.BOTH)) && (e.getPpp() - matchUser.getPpp()) <= pppGap)) { - return SlotStatus.MATCH; - } - return SlotStatus.OPEN; - } - - private SlotStatus getNormalSlotStatus(List allMatchUsers) { - if (allMatchUsers.stream().anyMatch(e -> e.getOption().equals(Option.NORMAL) || - e.getOption().equals(Option.BOTH))) { - return SlotStatus.MATCH; - } - return SlotStatus.OPEN; - } - - private SlotStatus getBothSlotStatus(List allMatchUsers) { - if (allMatchUsers.stream().anyMatch(e -> - e.getOption().equals(Option.NORMAL) || e.getOption().equals(Option.BOTH) - || (e.getOption().equals(Option.RANK) && - e.getPpp() - matchUser.getPpp() <= pppGap))) { - return SlotStatus.MATCH; - } - return SlotStatus.OPEN; - } -} diff --git a/src/main/java/com/gg/server/domain/match/utils/SlotGenerator.java b/src/main/java/com/gg/server/domain/match/utils/SlotGenerator.java deleted file mode 100644 index 99918c179..000000000 --- a/src/main/java/com/gg/server/domain/match/utils/SlotGenerator.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.gg.server.domain.match.utils; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.data.RedisMatchTime; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.dto.SlotStatusDto; -import com.gg.server.domain.match.dto.SlotStatusResponseListDto; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.match.type.SlotStatus; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.slotmanagement.SlotManagement; -import java.time.LocalDateTime; -import java.util.*; - -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.type.TournamentStatus; -import lombok.Getter; - - -@Getter -public class SlotGenerator { - /** - * minTime ~ maxTime : ์Šฌ๋กฏ์ด ๋ณด์—ฌ์ง€๋Š” ์‹œ๊ฐ„ ๋ฒ”์œ„ - * matchUser : ํ˜„์žฌ ์œ ์ € ์ •๋ณด - * matchCalculator : ๋งค์นญ ๊ด€๋ จ ์Šฌ๋กฏ ์ƒํƒœ ๊ฒฐ์ • - * option : ์œ ์ €๊ฐ€ ํ˜„์žฌ ์„ ํƒํ•œ mode(random, normal, both) - */ - private final HashMap slots; - private final Integer interval; - private final LocalDateTime minTime; - private final LocalDateTime now; - private final LocalDateTime maxTime; - private final RedisMatchUser matchUser; - private final MatchCalculator matchCalculator; - private final Option option; - - public SlotGenerator(RankRedis user, SlotManagement slotManagement, Season season, Option option) { - this.interval = slotManagement.getGameInterval(); - this.now = LocalDateTime.now(); - this.minTime = LocalDateTime.of( - now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0) - .minusHours(slotManagement.getPastSlotTime()); - this.maxTime = setMaxTime(slotManagement); - this.option = option; - this.slots = new HashMap(); - this.matchUser = new RedisMatchUser(user.getUserId(), user.getPpp(), option); - this.matchCalculator = new MatchCalculator(season.getPppGap(), matchUser); - } - - public void addPastSlots() { - for (LocalDateTime time = minTime; time.isBefore(now); time = time.plusMinutes(interval)) { - slots.put(time, new SlotStatusDto(time, SlotStatus.CLOSE, interval)); - } - } - - public void addMatchedSlots(List games) { - games.stream().forEach(e -> slots.put(e.getStartTime(), - new SlotStatusDto(e.getStartTime(), SlotStatus.CLOSE, interval))); - } - - /** - * BEFORE, LIVE ์ƒํƒœ์˜ ํ† ๋„ˆ๋จผํŠธ ์ง„ํ–‰ ์‹œ๊ฐ„์— ์Šฌ๋กฏ์„ blockํ•จ - */ - public void addTournamentSlots(List tournaments) { - for (Tournament tournament : tournaments) { - LocalDateTime startTime = tournament.getStartTime(); - int startTimeMinute = startTime.getMinute(); - startTimeMinute = startTimeMinute - (startTimeMinute % interval); - startTime = startTime.withMinute(startTimeMinute); - LocalDateTime endTime = tournament.getEndTime(); - int endTimeMinute = endTime.getMinute(); - endTimeMinute = endTimeMinute + (interval - (endTimeMinute % interval)); - endTime = endTime.withMinute(endTimeMinute); - for (LocalDateTime time = startTime; time.isBefore(endTime); time = time.plusMinutes(interval)) { - slots.put(time, new SlotStatusDto(time, SlotStatus.CLOSE, interval)); - } - } - } - - public void addMySlots(Game myGame) { - slots.put(myGame.getStartTime(), - new SlotStatusDto(myGame.getStartTime(), myGame.getEndTime(), - getMySlotStatus(myGame.getMode(), option))); - } - public void addMySlots(Set allMatchTime) { - allMatchTime.stream().forEach(match -> slots.put(match.getStartTime(), - new SlotStatusDto(match.getStartTime(), - getMySlotStatus(match.getOption(), option), interval))); - } - - private SlotStatus getMySlotStatus(Option myOption, Option viewOption) { - if (myOption.equals(viewOption)) { - return SlotStatus.MYTABLE; - } - return SlotStatus.CLOSE; - } - - private SlotStatus getMySlotStatus(Mode myMode, Option viewOption) { - if (myMode.getCode().equals(viewOption.getCode())) { - return SlotStatus.MYTABLE; - } - return SlotStatus.CLOSE; - } - - public void groupEnrolledSlot(LocalDateTime startTime, List players) { - slots.put(startTime, new SlotStatusDto(startTime, matchCalculator.findEnemyStatus(players), interval)); - } - - public SlotStatusResponseListDto getResponseListDto() { - long slotCountPerHour = 60 / interval; - List> matchBoards = new ArrayList>(); - for (LocalDateTime time = minTime ; time.isBefore(maxTime) ; time = time.plusHours(1)) { - List hourBoard = new ArrayList(); - for (long i = 0; i < slotCountPerHour; i++) { - SlotStatusDto dto = slots.getOrDefault(time.plusMinutes(i * interval), - new SlotStatusDto(time.plusMinutes(i * interval), SlotStatus.OPEN, interval)); - hourBoard.add(dto); - } - matchBoards.add(hourBoard); - } - return new SlotStatusResponseListDto(matchBoards); - } - - private LocalDateTime setMaxTime(SlotManagement slotManagement) { - LocalDateTime compared = LocalDateTime.of( - now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0) - .plusHours(slotManagement.getFutureSlotTime()); - if (slotManagement.getEndTime() != null && slotManagement.getEndTime().isBefore(compared)) { - return slotManagement.getEndTime(); - } - return compared; - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java b/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java deleted file mode 100644 index e088b9946..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/controller/MegaphoneController.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gg.server.domain.megaphone.controller; - -import com.gg.server.domain.megaphone.dto.MegaphoneDetailResponseDto; -import com.gg.server.domain.megaphone.dto.MegaphoneTodayListResponseDto; -import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; -import com.gg.server.domain.megaphone.service.MegaphoneService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.List; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/megaphones") -public class MegaphoneController { - private final MegaphoneService megaphoneService; - - @PostMapping() - public ResponseEntity useMegaphone(@RequestBody @Valid MegaphoneUseRequestDto megaphoneUseRequestDto, - @Parameter(hidden = true) @Login UserDto user) { - megaphoneService.useMegaphone(megaphoneUseRequestDto, user); - return ResponseEntity.status(HttpStatus.CREATED).build(); - } - - @DeleteMapping("/{megaphoneId}") - public ResponseEntity deleteMegaphone(@PathVariable Long megaphoneId, - @Parameter(hidden = true) @Login UserDto user) { - megaphoneService.deleteMegaphone(megaphoneId, user); - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } - - @GetMapping("/receipt/{receiptId}") - public ResponseEntity getMegaphoneDetail(@PathVariable Long receiptId, @Parameter(hidden = true) @Login UserDto user) { - return ResponseEntity.ok(megaphoneService.getMegaphoneDetail(receiptId, user)); - } - - @GetMapping() - public ResponseEntity> getMegaphoneTodayList(@Parameter(hidden = true) @Login UserDto user) { - return ResponseEntity.ok(megaphoneService.getMegaphoneTodayList()); - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java b/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java deleted file mode 100644 index a5715c44d..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/data/Megaphone.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.domain.megaphone.data; - -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.user.data.User; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDate; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Megaphone { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "receipt_id") - private Receipt receipt; - - @Column(name = "content", length = 30) - private String content; - - @NotNull - @Column(name = "used_at") - private LocalDate usedAt; - - public Megaphone(User user, Receipt receipt, String content, LocalDate usedAt) { - this.user = user; - this.receipt = receipt; - this.content = content; - this.usedAt = usedAt; - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java b/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java deleted file mode 100644 index 3c3f33087..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/data/MegaphoneRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.megaphone.data; - -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.type.ItemStatus; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; - -public interface MegaphoneRepository extends JpaRepository { - List findAllByUsedAtAndReceiptStatus(LocalDate date, ItemStatus itemStatus); - - Megaphone findFirstByOrderByIdDesc(); - - Optional findByReceipt(Receipt receipt); -} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java deleted file mode 100644 index 25237287b..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneDetailResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.megaphone.dto; - -import com.gg.server.domain.megaphone.data.Megaphone; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class MegaphoneDetailResponseDto { - private Long megaphoneId; - private String content; - private String usedAt; - - public MegaphoneDetailResponseDto(Megaphone megaphone) { - this.megaphoneId = megaphone.getId(); - this.content = megaphone.getContent(); - this.usedAt = megaphone.getUsedAt().toString(); - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java deleted file mode 100644 index 67e0c33fa..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneTodayListResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.megaphone.dto; - -import com.gg.server.domain.megaphone.redis.MegaphoneRedis; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class MegaphoneTodayListResponseDto { - private Long megaphoneId; - private String content; - private String intraId; - - public MegaphoneTodayListResponseDto(MegaphoneRedis megaphoneRedis) { - this.megaphoneId = megaphoneRedis.getId(); - this.content = megaphoneRedis.getContent(); - this.intraId = megaphoneRedis.getIntraId(); - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java b/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java deleted file mode 100644 index 8b44b6175..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/dto/MegaphoneUseRequestDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.domain.megaphone.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class MegaphoneUseRequestDto { - @NotNull(message = "receiptId๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - private Long receiptId; - @NotNull(message = "content๋Š” null์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") @Size(max = 30) - private String content; -} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java deleted file mode 100644 index 8022d7bef..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneContentException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.megaphone.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class MegaphoneContentException extends BusinessException { - public MegaphoneContentException() { - super("ํ™•์„ฑ๊ธฐ ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_CONTENT); - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java deleted file mode 100644 index accd2759d..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneNotFoundException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.megaphone.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class MegaphoneNotFoundException extends NotExistException { - public MegaphoneNotFoundException() {super("ํ™•์„ฑ๊ธฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_TIME);} -} diff --git a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java b/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java deleted file mode 100644 index f11bd29f3..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/exception/MegaphoneTimeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.megaphone.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class MegaphoneTimeException extends BusinessException { - public MegaphoneTimeException() { - super("ํ™•์„ฑ๊ธฐ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.", ErrorCode.MEGAPHONE_TIME); - } -} diff --git a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java deleted file mode 100644 index bd560df0b..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedis.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.domain.megaphone.redis; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.redis.core.RedisHash; - -import javax.persistence.Id; -import java.time.LocalDateTime; - -@RedisHash("megaphone") -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class MegaphoneRedis { - @Id - private Long id; - private String intraId; - private String content; - - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime usedAt; -} diff --git a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java b/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java deleted file mode 100644 index d1fd99ed3..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/redis/MegaphoneRedisRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.megaphone.redis; - -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -import java.time.Duration; -import java.util.List; - - -@Repository -@RequiredArgsConstructor -public class MegaphoneRedisRepository { - private final RedisTemplate redisTemplate; - - public void addMegaphone(MegaphoneRedis megaphoneRedis) { - Duration duration = Duration.between(megaphoneRedis.getUsedAt(), megaphoneRedis.getUsedAt().plusDays(1)); - redisTemplate.opsForValue().set("megaphone" + megaphoneRedis.getId(), megaphoneRedis, duration); - } - - public List getAllMegaphone() { - return redisTemplate.opsForValue().multiGet(redisTemplate.keys("megaphone*")); - } - - public void deleteAllMegaphone() { - redisTemplate.delete(redisTemplate.keys("megaphone*")); - } - - public void deleteMegaphoneById(Long id) { - redisTemplate.delete("megaphone" + id); - } - -} diff --git a/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java b/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java deleted file mode 100644 index d3f258dde..000000000 --- a/src/main/java/com/gg/server/domain/megaphone/service/MegaphoneService.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.gg.server.domain.megaphone.service; - -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.megaphone.data.Megaphone; -import com.gg.server.domain.megaphone.data.MegaphoneRepository; -import com.gg.server.domain.megaphone.dto.MegaphoneDetailResponseDto; -import com.gg.server.domain.megaphone.dto.MegaphoneTodayListResponseDto; -import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; -import com.gg.server.domain.megaphone.exception.MegaphoneContentException; -import com.gg.server.domain.megaphone.exception.MegaphoneNotFoundException; -import com.gg.server.domain.megaphone.exception.MegaphoneTimeException; -import com.gg.server.domain.megaphone.redis.MegaphoneRedis; -import com.gg.server.domain.megaphone.redis.MegaphoneRedisRepository; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.data.ReceiptRepository; -import com.gg.server.domain.receipt.exception.ItemStatusException; -import com.gg.server.domain.receipt.exception.ReceiptNotFoundException; -import com.gg.server.domain.receipt.type.ItemStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RoleType; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class MegaphoneService { - private final UserRepository userRepository; - private final ReceiptRepository receiptRepository; - private final MegaphoneRepository megaphoneRepository; - private final MegaphoneRedisRepository megaphoneRedisRepository; - private final ItemService itemService; - - @Transactional - public void useMegaphone(MegaphoneUseRequestDto megaphoneUseRequestDto, UserDto user) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - if (LocalTime.now().isAfter(LocalTime.of(23, 55)) || LocalTime.now().isBefore(LocalTime.of(0, 5))) { - throw new MegaphoneTimeException(); - } - Receipt receipt = receiptRepository.findById(megaphoneUseRequestDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); - itemService.checkItemType(receipt, ItemType.MEGAPHONE); - itemService.checkItemOwner(loginUser, receipt); - if (!receipt.getStatus().equals(ItemStatus.BEFORE)) { - throw new ItemStatusException(); - } - if (megaphoneUseRequestDto.getContent().length() == 0) { - throw new MegaphoneContentException(); - } - receipt.updateStatus(ItemStatus.WAITING); - Megaphone megaphone = new Megaphone(loginUser, receipt, megaphoneUseRequestDto.getContent(), LocalDate.now().plusDays(1)); - megaphoneRepository.save(megaphone); - } - - @Transactional - public void setMegaphoneList(LocalDate today) { - megaphoneRepository.findAllByUsedAtAndReceiptStatus(today, ItemStatus.USING).forEach(megaphone -> megaphone.getReceipt().updateStatus(ItemStatus.USED)); - megaphoneRedisRepository.deleteAllMegaphone(); - List megaphones = megaphoneRepository.findAllByUsedAtAndReceiptStatus(today.plusDays(1), ItemStatus.WAITING); - for (Megaphone megaphone : megaphones) { - megaphone.getReceipt().updateStatus(ItemStatus.USING); - megaphoneRedisRepository.addMegaphone(new MegaphoneRedis(megaphone.getId(), megaphone.getUser().getIntraId(), megaphone.getContent(), - LocalDateTime.of(megaphone.getUsedAt(), LocalTime.of(0, 0)))); - } - } - - @Transactional - public void deleteMegaphone(Long megaphoneId, UserDto user) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - Megaphone megaphone = megaphoneRepository.findById(megaphoneId).orElseThrow(MegaphoneNotFoundException::new); - Receipt receipt = megaphone.getReceipt(); - if (!user.getRoleType().equals(RoleType.ADMIN)) { - itemService.checkItemOwner(loginUser, receipt); - } - itemService.checkItemStatus(receipt); - if (receipt.getStatus().equals(ItemStatus.USING)) { - megaphoneRedisRepository.deleteMegaphoneById(megaphone.getId()); - } - receipt.updateStatus(ItemStatus.DELETED); - } - - public MegaphoneDetailResponseDto getMegaphoneDetail(Long receiptId, UserDto user) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - Receipt receipt = receiptRepository.findById(receiptId).orElseThrow(ReceiptNotFoundException::new); - itemService.checkItemType(receipt, ItemType.MEGAPHONE); - itemService.checkItemOwner(loginUser, receipt); - itemService.checkItemStatus(receipt); - Megaphone megaphone = megaphoneRepository.findByReceipt(receipt).orElseThrow(MegaphoneNotFoundException::new); - return new MegaphoneDetailResponseDto(megaphone); - } - - public List getMegaphoneTodayList() { - return megaphoneRedisRepository.getAllMegaphone().stream().map(MegaphoneTodayListResponseDto::new).collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/controller/NotiController.java b/src/main/java/com/gg/server/domain/noti/controller/NotiController.java deleted file mode 100644 index 240633968..000000000 --- a/src/main/java/com/gg/server/domain/noti/controller/NotiController.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gg.server.domain.noti.controller; - -import com.gg.server.domain.noti.dto.NotiDto; -import com.gg.server.domain.noti.dto.NotiListResponseDto; -import com.gg.server.domain.noti.dto.NotiResponseDto; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@RestController -@AllArgsConstructor -@RequestMapping(value = "/pingpong/notifications") -public class NotiController { - private final NotiService notiService; - - @GetMapping - public NotiListResponseDto notiFindByUser(@Login UserDto user) { - List notiResponseDtoList = notiService.findNotiByUser(user); - return new NotiListResponseDto(notiResponseDtoList); - } - - @PutMapping(value = "/check") - public ResponseEntity checkNotiByUser(@Login UserDto user) { - notiService.modifyNotiCheckedByUser(user); - return ResponseEntity.status(204).build(); - } - - @DeleteMapping - public ResponseEntity notiRemoveAll(@Login UserDto user) { - notiService.removeAllNotisByUser(user); - return ResponseEntity.status(204).build(); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/data/Noti.java b/src/main/java/com/gg/server/domain/noti/data/Noti.java deleted file mode 100644 index bcaff10a7..000000000 --- a/src/main/java/com/gg/server/domain/noti/data/Noti.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gg.server.domain.noti.data; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Entity -public class Noti extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "noti_type", length = 30) - @Enumerated(EnumType.STRING) - private NotiType type; - - @Column(name = "message", length = 255) - private String message; - - @NotNull - @Column(name = "is_checked") - private Boolean isChecked; - - public Noti(User user, NotiType type, String message, Boolean isChecked) { - this.user = user; - this.type = type; - this.message = message; - this.isChecked = isChecked; - } - - public void update(User user, NotiType type, String message, Boolean isChecked) { - this.user = user; - this.type = type; - this.message = message; - this.isChecked = isChecked; - } - - public void modifyIsChecked(Boolean isChecked) { - this.isChecked = isChecked; - } -} diff --git a/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java b/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java deleted file mode 100644 index fb291af76..000000000 --- a/src/main/java/com/gg/server/domain/noti/data/NotiRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.noti.data; - -import com.gg.server.domain.user.data.User; -import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; -import java.util.Optional; - -public interface NotiRepository extends JpaRepository, NotiRepositoryCustom { - List findByUser(User user); - Optional findByIdAndUser(Long notiId, User user); - List findAllByUser(User user); - List findAllByUserOrderByIdDesc(User user); - void deleteAllByUser(User user); -} diff --git a/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryCustom.java b/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryCustom.java deleted file mode 100644 index 1fa0e6599..000000000 --- a/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryCustom.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.gg.server.domain.noti.data; - -public interface NotiRepositoryCustom { - int countNotCheckedNotiByUser(Long userId); -} diff --git a/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryImpl.java b/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryImpl.java deleted file mode 100644 index fda2ac825..000000000 --- a/src/main/java/com/gg/server/domain/noti/data/NotiRepositoryImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.noti.data; - -import lombok.RequiredArgsConstructor; - -import javax.persistence.EntityManager; - - -@RequiredArgsConstructor -public class NotiRepositoryImpl implements NotiRepositoryCustom{ - private final EntityManager em; - @Override - public int countNotCheckedNotiByUser(Long userId) { - String sql = "select count(n) from Noti n where n.isChecked=false and user.id =: userId"; - Long cntNoti = em.createQuery(sql, Long.class) - .setParameter("userId", userId) - .getSingleResult(); - return cntNoti.intValue(); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/dto/NotiDto.java b/src/main/java/com/gg/server/domain/noti/dto/NotiDto.java deleted file mode 100644 index f39187d0e..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/NotiDto.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gg.server.domain.noti.dto; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.noti.type.NotiType; -import lombok.Builder; -import lombok.Getter; - -import java.time.LocalDateTime; -import java.util.Objects; - -@Getter -@Builder -public class NotiDto { - private Long id; - private UserDto user; - private NotiType type; - private Boolean isChecked; - private String message; - private LocalDateTime createdAt; - - static public NotiDto from (Noti noti) - { - NotiDto notiDto; - if (noti == null) - notiDto = null; - else { - notiDto = NotiDto.builder() - .id(noti.getId()) - .user(UserDto.from(noti.getUser())) - .type(noti.getType()) - .isChecked(noti.getIsChecked()) - .message(noti.getMessage()) - .createdAt(noti.getCreatedAt()) - .build(); - } - return notiDto; - } - - @Override - public String toString() { - return "NotiDto{" + - "id=" + id + - ", user=" + user + - ", type=" + type + - ", isChecked=" + isChecked + - ", message='" + message + '\'' + - ", createdDate=" + createdAt + - '}'; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof NotiDto)) { - return false; - } - NotiDto other = (NotiDto) o; - return Objects.equals(id, other.id) - && Objects.equals(user, other.user) - && Objects.equals(type, other.type) - && Objects.equals(isChecked, other.isChecked) - && Objects.equals(message, other.message) - && Objects.equals(createdAt, other.createdAt); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserRequestDto.java b/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserRequestDto.java deleted file mode 100644 index 550652e94..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserRequestDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.gg.server.domain.noti.dto; - -public class NotiFindByUserRequestDto { -} diff --git a/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserResponseDto.java b/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserResponseDto.java deleted file mode 100644 index 02b1f52cb..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/NotiFindByUserResponseDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.gg.server.domain.noti.dto; - -public class NotiFindByUserResponseDto { -} diff --git a/src/main/java/com/gg/server/domain/noti/dto/NotiListResponseDto.java b/src/main/java/com/gg/server/domain/noti/dto/NotiListResponseDto.java deleted file mode 100644 index 7ff7ba7b4..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/NotiListResponseDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.domain.noti.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Objects; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class NotiListResponseDto { - private List notifications; - @Override - public String toString() { - return "NotiResponseDto{" + - "notifications=" + notifications + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NotiListResponseDto other = (NotiListResponseDto) o; - return Objects.equals(notifications, other.notifications); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/noti/dto/NotiResponseDto.java b/src/main/java/com/gg/server/domain/noti/dto/NotiResponseDto.java deleted file mode 100644 index 1586cbb05..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/NotiResponseDto.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.gg.server.domain.noti.dto; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.dto.UserDto; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class NotiResponseDto { - private Long id; - private NotiType type; - private Boolean isChecked; - private String message; - private LocalDateTime createdAt; - - static public NotiResponseDto from (Noti noti) - { - NotiResponseDto notiResponseDto; - if (noti == null) - notiResponseDto = null; - else { - notiResponseDto = NotiResponseDto.builder() - .id(noti.getId()) - .type(noti.getType()) - .isChecked(noti.getIsChecked()) - .message(noti.getMessage()) - .createdAt(noti.getCreatedAt()) - .build(); - } - return notiResponseDto; - } - - @Override - public String toString() { - return "NotiDto{" + - "id=" + id + - ", type=" + type + - ", isChecked=" + isChecked + - ", message='" + message + '\'' + - ", createdDate=" + createdAt + - '}'; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof NotiResponseDto)) { - return false; - } - NotiResponseDto other = (NotiResponseDto) o; - return Objects.equals(id, other.id) - && Objects.equals(type, other.type) - && Objects.equals(isChecked, other.isChecked) - && Objects.equals(message, other.message) - && Objects.equals(createdAt, other.createdAt); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/noti/dto/UserNotiDto.java b/src/main/java/com/gg/server/domain/noti/dto/UserNotiDto.java deleted file mode 100644 index f3b127aba..000000000 --- a/src/main/java/com/gg/server/domain/noti/dto/UserNotiDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.domain.noti.dto; - -import com.gg.server.domain.team.dto.GameUser; -import com.gg.server.domain.user.type.SnsType; -import lombok.Getter; - -@Getter -public class UserNotiDto { - private Long userId; - private Long gameId; - private String intraId; - private SnsType snsNotiOpt; - private String email; - - public UserNotiDto(GameUser gameUser) { - this.gameId = gameUser.getGameId(); - this.userId = gameUser.getUserId(); - this.intraId = gameUser.getIntraId(); - this.email = gameUser.getEmail(); - this.snsNotiOpt = gameUser.getSnsNotiOpt(); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/exception/SlackJsonParseException.java b/src/main/java/com/gg/server/domain/noti/exception/SlackJsonParseException.java deleted file mode 100644 index 3bdf62972..000000000 --- a/src/main/java/com/gg/server/domain/noti/exception/SlackJsonParseException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.noti.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ParseException; - -public class SlackJsonParseException extends ParseException { - public SlackJsonParseException() { - super("json parse error in getDmChannelId()", ErrorCode.SLACK_JSON_PARSE_ERR); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/exception/SlackSendException.java b/src/main/java/com/gg/server/domain/noti/exception/SlackSendException.java deleted file mode 100644 index 703f82189..000000000 --- a/src/main/java/com/gg/server/domain/noti/exception/SlackSendException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.noti.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.SendException; - -public class SlackSendException extends SendException { - public SlackSendException() { - super("fail to send notification", ErrorCode.SLACK_SEND_FAIL); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/exception/SlackUserGetFailedException.java b/src/main/java/com/gg/server/domain/noti/exception/SlackUserGetFailedException.java deleted file mode 100644 index 454e751ee..000000000 --- a/src/main/java/com/gg/server/domain/noti/exception/SlackUserGetFailedException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.noti.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class SlackUserGetFailedException extends NotExistException { - public SlackUserGetFailedException() { - super("fail to get slack user info", ErrorCode.SLACK_USER_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/service/NotiService.java b/src/main/java/com/gg/server/domain/noti/service/NotiService.java deleted file mode 100644 index f1a019265..000000000 --- a/src/main/java/com/gg/server/domain/noti/service/NotiService.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.gg.server.domain.noti.service; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.dto.NotiDto; -import com.gg.server.domain.noti.dto.NotiResponseDto; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@AllArgsConstructor -public class NotiService { - private final NotiRepository notiRepository; - private final UserRepository userRepository; - private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); - - @Transactional(readOnly = true) - public List findNotiByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); - List notiList = notiRepository.findAllByUserOrderByIdDesc(user); - List notiResponseDtoList = notiList.stream().map(NotiResponseDto::from).collect(Collectors.toList()); - return notiResponseDtoList; - } - - @Transactional - public NotiDto findNotiByIdAndUser(UserDto userDto, Long notiId) { - User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); - Noti noti = notiRepository.findByIdAndUser(notiId, user).orElseThrow(() -> new NotExistException("์š”์ฒญํ•œ ์•Œ๋ฆผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.NOT_FOUND)); - return NotiDto.from(noti); - } - - @Transactional - public void modifyNotiCheckedByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); - List notis = notiRepository.findAllByUser(user); - notis.forEach(noti -> {noti.modifyIsChecked(true);}); - } - - @Transactional - public void removeNotiById(Long notiId) { - notiRepository.deleteById(notiId); - } - - @Transactional - public void removeAllNotisByUser(UserDto userDto) { - User user = userRepository.findById(userDto.getId()).orElseThrow(UserNotFoundException::new); - notiRepository.deleteAllByUser(user); - } - - @Transactional - public Noti createMatched(User user, LocalDateTime startTime) { - String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; - Noti noti = new Noti(user, NotiType.MATCHED, notiMessage, false); - notiRepository.save(noti); - return noti; - } - - @Transactional - public Noti createMatchCancel(User user, LocalDateTime startTime) { - String notiMessage = startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์ƒ๋Œ€์— ์˜ํ•ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; - Noti noti = new Noti(user, NotiType.CANCELEDBYMAN, notiMessage, false); - notiRepository.save(noti); - return noti; - } - - @Transactional - public Noti createGiftNoti(User ownerUser, User payUser, String itemName) { - String notiMessage = "เฌ˜(เฉญหŠแต•ห‹)เฉญ* เฉˆโœฉ " + payUser.getIntraId() + "๋‹˜์—๊ฒŒ " + itemName + " ์•„์ดํ…œ์„ ์„ ๋ฌผ๋ฐ›์•˜์–ด์š”!"; - Noti noti = new Noti(ownerUser, NotiType.GIFT, notiMessage, false); - notiRepository.save(noti); - return noti; - } - - public Noti createImminentNoti(User user, String enemyIntra, NotiType notiType, Integer gameOpenMinute) { - String msg = "๋‹˜๊ณผ ๊ฒฝ๊ธฐ " + gameOpenMinute + "๋ถ„ ์ „ ์ž…๋‹ˆ๋‹ค. ์„œ๋‘๋ฅด์„ธ์š”!"; - return notiRepository.save(new Noti(user, notiType, msg, false)); - } - - public String getMessage(Noti noti) { - String message; - if (noti.getType() != NotiType.ANNOUNCE) { - message = notiMsg(noti.getType()); - } else { - message = "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + noti.getType().getMessage() + "\"\n\n๊ณต์ง€์‚ฌํ•ญ: " - + noti.getMessage() + "\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; - } - return message; - } - public String notiMsg(NotiType notiType) { - return "๐Ÿงš: \"์ƒˆ๋กœ์šด ์•Œ๋ฆผ์ด ๋„์ฐฉํ–ˆํ•‘.\"\n" + "๐Ÿงš: \"" + notiType.getMessage() + "\"\n\n ๐Ÿ“42GG์™€ ํ•จ๊ป˜ํ•˜๋Š” ํ–‰๋ณตํ•œ ํƒ๊ตฌ์ƒํ™œ๐Ÿ“" + - "\n$$์ง€๊ธˆ ์ฆ‰์‹œ ์ ‘์†$$ ----> https://42gg.kr"; - } -} diff --git a/src/main/java/com/gg/server/domain/noti/service/SnsNotiService.java b/src/main/java/com/gg/server/domain/noti/service/SnsNotiService.java deleted file mode 100644 index 726758068..000000000 --- a/src/main/java/com/gg/server/domain/noti/service/SnsNotiService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gg.server.domain.noti.service; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.dto.UserNotiDto; -import com.gg.server.domain.noti.service.sns.NotiMailSender; -import com.gg.server.domain.noti.service.sns.SlackbotService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.type.SnsType; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@Slf4j -public class SnsNotiService { - private final NotiMailSender notiMailSender; - private final SlackbotService slackbotService; - - public SnsNotiService(NotiMailSender notiMailSender, SlackbotService slackbotService) { - this.notiMailSender = notiMailSender; - this.slackbotService = slackbotService; - } - - @Transactional(readOnly = true) - public void sendSnsNotification(Noti noti, UserNotiDto user) { - log.info("Send Sns Noti"); - SnsType userSnsNotiOpt = user.getSnsNotiOpt(); - if (userSnsNotiOpt == SnsType.NONE) - return; - if(userSnsNotiOpt == SnsType.EMAIL) - notiMailSender.send(user, noti); - else if (userSnsNotiOpt == SnsType.SLACK) - slackbotService.send(user, noti); - else if (userSnsNotiOpt == SnsType.BOTH) { - notiMailSender.send(user, noti); - slackbotService.send(user, noti); - } - } - - @Transactional(readOnly = true) - public void sendSnsNotification(Noti noti, UserDto user) { - log.info("Send Sns Noti"); - SnsType userSnsNotiOpt = user.getSnsNotiOpt(); - if (userSnsNotiOpt == SnsType.NONE) - return; - if(userSnsNotiOpt == SnsType.EMAIL) - notiMailSender.send(user, noti); - else if (userSnsNotiOpt == SnsType.SLACK) - slackbotService.send(user, noti); - else if (userSnsNotiOpt == SnsType.BOTH) { - notiMailSender.send(user, noti); - slackbotService.send(user, noti); - } - } -} diff --git a/src/main/java/com/gg/server/domain/noti/service/sns/NotiMailSender.java b/src/main/java/com/gg/server/domain/noti/service/sns/NotiMailSender.java deleted file mode 100644 index 4e04b1c62..000000000 --- a/src/main/java/com/gg/server/domain/noti/service/sns/NotiMailSender.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gg.server.domain.noti.service.sns; - -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.dto.UserNotiDto; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.noti.service.SnsNotiService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.AsyncMailSender; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Component; - -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; - -@Component -@RequiredArgsConstructor -@Slf4j -public class NotiMailSender { - private final JavaMailSender javaMailSender; - private final AsyncMailSender asyncMailSender; - private final NotiService notiService; - - public void send(UserNotiDto user, Noti noti) { - MimeMessage message = javaMailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message); - try { - helper.setSubject("ํ•‘ํ์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ๋„์ฐฉํ•œ ํŽธ์ง€"); - log.info(user.getEmail()); - helper.setTo(user.getEmail()); - helper.setText(notiService.getMessage(noti)); - } catch (MessagingException e) { - log.error("MessagingException message = {}", e.getMessage()); - } - log.info("Email send {}", user.getUserId()); - asyncMailSender.send(message); - } - - public void send(UserDto user, Noti noti) { - MimeMessage message = javaMailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message); - try { - helper.setSubject("ํ•‘ํ์š”์ •๐Ÿงš์œผ๋กœ๋ถ€ํ„ฐ ๋„์ฐฉํ•œ ํŽธ์ง€"); - log.info(user.getEMail()); - helper.setTo(user.getEMail()); - helper.setText(notiService.getMessage(noti)); - } catch (MessagingException e) { - log.error("MessagingException message = {}", e.getMessage()); - } - log.info("Email send {}", user.getId()); - asyncMailSender.send(message); - } -} diff --git a/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotService.java b/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotService.java deleted file mode 100644 index 76d77ed76..000000000 --- a/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotService.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.gg.server.domain.noti.service.sns; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.dto.UserNotiDto; -import com.gg.server.domain.noti.exception.SlackJsonParseException; -import com.gg.server.domain.noti.exception.SlackSendException; -import com.gg.server.domain.noti.exception.SlackUserGetFailedException; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.user.dto.UserDto; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.*; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; -import java.util.Map; - -import static com.gg.server.domain.noti.service.sns.SlackbotUtils.*; - -@Component -@Slf4j -public class SlackbotService { - @Value("${slack.xoxbToken}") - private String authenticationToken; - - private final RestTemplate restTemplate; - private final ObjectMapper objectMapper; - private final NotiService notiService; - public SlackbotService(RestTemplateBuilder builder, ObjectMapper objectMapper, NotiService notiService) { - this.restTemplate = builder.build(); - this.objectMapper = objectMapper; - this.notiService = notiService; - } - - private String getSlackUserId(String intraId) throws SlackUserGetFailedException { - String userEmail = intraId + intraEmailSuffix; - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.add(HttpHeaders.AUTHORIZATION, authenticationPrefix + authenticationToken); - - MultiValueMap parameters = new LinkedMultiValueMap<>(); - parameters.add("email", userEmail); - - HttpEntity> request = new HttpEntity<>(parameters, headers); - - ResponseEntity responseEntity = restTemplate - .exchange(userIdGetUrl, HttpMethod.POST, request, SlackUserInfoResponse.class); - if (!responseEntity.getBody().ok) - throw new SlackUserGetFailedException(); - return responseEntity.getBody().user.id; - } - - private String getDmChannelId(String slackUserId) throws SlackJsonParseException { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.add(HttpHeaders.AUTHORIZATION, - authenticationPrefix + authenticationToken); - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - - Map map = new HashMap<>(); - map.put("users", slackUserId); - String contentBody = null; - try { - contentBody = objectMapper.writeValueAsString(map); - } catch (JsonProcessingException e) { - throw new SlackJsonParseException(); - } - - HttpEntity entity = new HttpEntity<>(contentBody, httpHeaders); - - ResponseEntity responseEntity = restTemplate - .exchange(conversationsUrl, HttpMethod.POST, entity, ConversationResponse.class); - if(!responseEntity.getBody().ok) { - log.error("fail to get user dm channel id"); - throw new SlackUserGetFailedException(); - } - return responseEntity.getBody().channel.id; - } - - @Async("asyncExecutor") - public void send(UserNotiDto user, Noti noti) { - log.info("slack alarm send"); - try { - startSendNoti(user.getIntraId(), noti); - } catch (SlackSendException e) { - log.error("SlackSendException message = {}", e.getMessage()); - } - } - - @Async("asyncExecutor") - public void send(UserDto user, Noti noti) { - log.info("slack alarm send"); - try { - startSendNoti(user.getIntraId(), noti); - } catch (SlackSendException e) { - log.error("SlackSendException message = {}", e.getMessage()); - } - } - - private void startSendNoti(String intraId, Noti noti) throws SlackSendException { - String slackUserId = getSlackUserId(intraId); - String slackChannelId = getDmChannelId(slackUserId); - String message = notiService.getMessage(noti); - - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.add(HttpHeaders.AUTHORIZATION, - authenticationPrefix + authenticationToken); - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - - Map map = new HashMap<>(); - map.put("channel",slackChannelId); - map.put("text", message); - String contentBody = null; - try { - contentBody = objectMapper.writeValueAsString(map); - } catch (JsonProcessingException e) { - log.error("start send Slack Noti", e); - throw new SlackJsonParseException(); - } - - HttpEntity entity = new HttpEntity<>(contentBody, httpHeaders); - - ResponseEntity respEntity = restTemplate - .exchange(sendMessageUrl, HttpMethod.POST, entity, String.class); - if(respEntity.getStatusCode() != HttpStatus.OK) - throw new SlackSendException(); - } - - @Getter - static class ConversationResponse { - private Boolean ok; - private Channel channel; - - @Getter - static class Channel { - private String id; - } - - } - - @Getter - static class SlackUserInfoResponse { - private Boolean ok; - private SlackUser user; - - @Getter - static class SlackUser{ - private String id; - } - } -} diff --git a/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotUtils.java b/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotUtils.java deleted file mode 100644 index 747824b1f..000000000 --- a/src/main/java/com/gg/server/domain/noti/service/sns/SlackbotUtils.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.domain.noti.service.sns; - -public class SlackbotUtils { - public static String conversationsUrl = "https://slack.com/api/conversations.open"; - public static String sendMessageUrl = "https://slack.com/api/chat.postMessage"; - public static String userIdGetUrl = "https://slack.com/api/users.lookupByEmail"; - public static String authenticationPrefix = "Bearer "; - public static String intraEmailSuffix = "@student.42seoul.kr"; -} diff --git a/src/main/java/com/gg/server/domain/noti/type/NotiType.java b/src/main/java/com/gg/server/domain/noti/type/NotiType.java deleted file mode 100644 index 5cca542d7..000000000 --- a/src/main/java/com/gg/server/domain/noti/type/NotiType.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.domain.noti.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum NotiType { - MATCHED("matched", "๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆํ."), - CANCELEDBYMAN("canceledbyman", "๋งค์นญ์ด ์ทจ์†Œ๋˜์—ˆํ."), - CANCELEDBYTIME("canceledbytime", "๋งค์นญ์ด ์ƒ๋Œ€ ์—†์Œ์œผ๋กœ ์ทจ์†Œ๋˜์—ˆํ."), - IMMINENT("imminent", "๋งค์น˜๊ฐ€ ๊ณง ์‹œ์ž‘๋ ํ."), - ANNOUNCE("announce", "๊ณต์ง€์‚ฌํ•ญ์ด ๋„์ฐฉํ–ˆํ."), - GIFT("gift", "์ƒˆ๋กœ์šด ์„ ๋ฌผ์ด ๋„์ฐฉํ–ˆํ."), - TOURNAMENT_CANCELED("tournament canceled", "์ฐธ๊ฐ€ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์‹ ์ฒญ ์ธ์› ๋ฏธ๋‹ฌ๋กœ ์ทจ์†Œ๋˜์—ˆํ."), - TOURNAMENT_GAME_MATCHED("tournament game matched", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์„ฑ์‚ฌ๋˜์—ˆํ."), - TOURNAMENT_GAME_CANCELED("tournament game canceled", "ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ์ด ์ทจ์†Œ๋˜์—ˆํ."); - - private final String code; - private final String message; - - public static NotiType of(String code) { - return Arrays.stream(NotiType.values()) - .filter(notiType-> notiType.getCode().equals(code)) - .findAny() - .orElse(ANNOUNCE); - } - - @JsonCreator - public static NotiType getEnumFromValue(String value) { - for(NotiType e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } - -} diff --git a/src/main/java/com/gg/server/domain/pchange/data/PChange.java b/src/main/java/com/gg/server/domain/pchange/data/PChange.java deleted file mode 100644 index ce47f4107..000000000 --- a/src/main/java/com/gg/server/domain/pchange/data/PChange.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gg.server.domain.pchange.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Getter -public class PChange extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "game_id") - private Game game; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "ppp_result") - private Integer pppResult; - - @NotNull - @Column(name = "exp") - private Integer exp; - - @NotNull - @Column(name = "is_checked") - private Boolean isChecked; - - public PChange(Game game, User user, Integer pppResult, Boolean isChecked) { - this.game = game; - this.user = user; - this.pppResult = pppResult; - this.exp = user.getTotalExp(); - this.isChecked = isChecked; - } - - public void checkPChange() { - this.isChecked = true; - } - public void updatePPP(Integer ppp) { - this.pppResult = ppp; - } - - @Override - public String toString() { - return "PChange{" + - "id=" + id + - ", game=" + game + - ", user=" + user + - ", pppResult=" + pppResult + - ", exp=" + exp + - ", isChecked=" + isChecked + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepository.java b/src/main/java/com/gg/server/domain/pchange/data/PChangeRepository.java deleted file mode 100644 index d3b72b09f..000000000 --- a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.domain.pchange.data; - -import com.gg.server.domain.game.type.Mode; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.List; -import java.util.Optional; - -public interface PChangeRepository extends JpaRepository , PChangeRepositoryCustom{ - - @Query(value = "SELECT pc FROM PChange pc join fetch pc.user WHERE pc.user.intraId LIKE %:intraId% order by pc.user.intraId asc, pc.id desc") - List findPChangesByUser_IntraId(@Param("intraId") String intraId); - - @Query(value = "SELECT pc FROM PChange pc join fetch pc.user WHERE pc.user.id =:userId order by pc.id desc") - List findAllByUserId(@Param("userId") Long userId); - - @Query(value = "SELECT pc FROM PChange pc join fetch pc.user join fetch pc.game WHERE pc.user.id = :userId and pc.game.mode in :modes order by pc.id desc") - List findAllByUserIdGameModeIn(@Param("userId") Long userId, @Param("modes") List modes); - Optional findByUserIdAndGameId(Long userId, Long gameId); - - Optional findPChangeByUserIdAndGameId(Long userId, Long gameId); - - List findPChangesByGameId(Long gameId); -} diff --git a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryCustom.java b/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryCustom.java deleted file mode 100644 index 9f2e132d1..000000000 --- a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryCustom.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.domain.pchange.data; - -import java.util.List; - -public interface PChangeRepositoryCustom { - List findPChangesHistory(String intraId, Long seasonId); - List findExpHistory(Long userId, Long gameId); - List findPPPHistory(Long userId, Long gameId, Long seasonId); -} diff --git a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryImpl.java b/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryImpl.java deleted file mode 100644 index 7b4c79fd9..000000000 --- a/src/main/java/com/gg/server/domain/pchange/data/PChangeRepositoryImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gg.server.domain.pchange.data; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; - -import javax.persistence.EntityManager; -import java.util.List; - -@Repository -@RequiredArgsConstructor -@Slf4j -public class PChangeRepositoryImpl implements PChangeRepositoryCustom{ - private final EntityManager em; - @Override - public List findPChangesHistory(String intraId, Long seasonId) { - String sql = "select p from PChange p join p.game g join p.user u join g.season s where u.intraId = " + - ":intra_id and s.id = :season_id and g.mode = 'RANK' order by p.createdAt desc"; - return em.createQuery(sql, PChange.class) - .setParameter("intra_id", intraId) - .setParameter("season_id", seasonId) - .setFirstResult(0) - .setMaxResults(10) - .getResultList(); - } - - @Override - public List findExpHistory(Long userId, Long gameId) { - String sql = "select p from PChange p join p.game g where p.user.id = " + - ":userId and p.id <= (select p2.id from PChange p2 where p2.game.id = :gameId and p2.user.id = :userId) order by p.createdAt desc"; - return em.createQuery(sql, PChange.class) - .setParameter("userId", userId) - .setParameter("gameId", gameId) - .setFirstResult(0) - .setMaxResults(2) - .getResultList(); - } - - @Override - public List findPPPHistory(Long userId, Long gameId, Long seasonId) { - String sql = "select p from PChange p join p.game g join g.season s where p.user.id = " + - ":userId and p.id <= (select p2.id from PChange p2 where p2.game.id = :gameId and p2.user.id =:userId) " + - "and p.game.mode = 'RANK' and s.id = :season_id " + - "order by p.createdAt desc"; - return em.createQuery(sql, PChange.class) - .setParameter("userId", userId) - .setParameter("gameId", gameId) - .setParameter("season_id", seasonId) - .setFirstResult(0) - .setMaxResults(2) - .getResultList(); - } -} diff --git a/src/main/java/com/gg/server/domain/pchange/exception/PChangeNotExistException.java b/src/main/java/com/gg/server/domain/pchange/exception/PChangeNotExistException.java deleted file mode 100644 index 1f3d00e77..000000000 --- a/src/main/java/com/gg/server/domain/pchange/exception/PChangeNotExistException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.pchange.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class PChangeNotExistException extends NotExistException { - public PChangeNotExistException() { - super("์ด์ „ exp ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.PCHANGE_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java b/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java deleted file mode 100644 index 968f2755a..000000000 --- a/src/main/java/com/gg/server/domain/pchange/service/PChangeService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.domain.pchange.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.user.data.User; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class PChangeService { - private final PChangeRepository pChangeRepository; - - @Transactional - public void addPChange(Game game, User user, Integer pppResult, Boolean isChecked) { - pChangeRepository.save(new PChange(game, user, pppResult, isChecked)); - } - - public List findExpChangeHistory(Long gameId, Long userId) { - List pChanges = pChangeRepository.findExpHistory(userId, gameId); - if (pChanges.isEmpty()) { - throw new PChangeNotExistException(); - } - return pChanges; - } - - public List findPPPChangeHistory(Long gameId, Long userId, Long seasonId) { - List pChanges = pChangeRepository.findPPPHistory(userId, gameId, seasonId); - if (pChanges.isEmpty()) { - throw new PChangeNotExistException(); - } - return pChanges; - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/data/Penalty.java b/src/main/java/com/gg/server/domain/penalty/data/Penalty.java deleted file mode 100644 index f187edfb4..000000000 --- a/src/main/java/com/gg/server/domain/penalty/data/Penalty.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.gg.server.domain.penalty.data; - -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Penalty extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "penalty_type", length = 20) - @Enumerated(EnumType.STRING) - private PenaltyType type; - - @Column(name = "message", length = 100) - private String message; - - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @NotNull - @Column(name = "penalty_time") - private Integer penaltyTime; - - public Penalty(User user, PenaltyType type, String message, LocalDateTime startTime, Integer penaltyTime) { - this.user = user; - this.type = type; - this.message = message; - this.startTime = startTime; - this.penaltyTime = penaltyTime; - } - - public void updateStartTime(LocalDateTime startTime) { - this.startTime = startTime; - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/data/PenaltyRepository.java b/src/main/java/com/gg/server/domain/penalty/data/PenaltyRepository.java deleted file mode 100644 index f68ba781f..000000000 --- a/src/main/java/com/gg/server/domain/penalty/data/PenaltyRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.penalty.data; - - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PenaltyRepository extends JpaRepository { - -} diff --git a/src/main/java/com/gg/server/domain/penalty/exception/PenaltyExpiredException.java b/src/main/java/com/gg/server/domain/penalty/exception/PenaltyExpiredException.java deleted file mode 100644 index 3670e1d4c..000000000 --- a/src/main/java/com/gg/server/domain/penalty/exception/PenaltyExpiredException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.penalty.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ExpiredException; - -public class PenaltyExpiredException extends ExpiredException { - public PenaltyExpiredException() { - super("์ด๋ฏธ ๋งŒ๋ฃŒ๋œ ํŒจ๋„ํ‹ฐ์ž…๋‹ˆ๋‹ค.", ErrorCode.PENALTY_EXPIRED); - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/exception/PenaltyNotFoundException.java b/src/main/java/com/gg/server/domain/penalty/exception/PenaltyNotFoundException.java deleted file mode 100644 index b0440907f..000000000 --- a/src/main/java/com/gg/server/domain/penalty/exception/PenaltyNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.penalty.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class PenaltyNotFoundException extends NotExistException { - public PenaltyNotFoundException() { - super("ํ•ด๋‹น ํŒจ๋„ํ‹ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.PENALTY_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/exception/RedisPenaltyUserNotFoundException.java b/src/main/java/com/gg/server/domain/penalty/exception/RedisPenaltyUserNotFoundException.java deleted file mode 100644 index 7ed319666..000000000 --- a/src/main/java/com/gg/server/domain/penalty/exception/RedisPenaltyUserNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.penalty.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class RedisPenaltyUserNotFoundException extends NotExistException { - public RedisPenaltyUserNotFoundException() { - super("Redis์— Penalty User ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.REDIS_PENALTY_USER_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/redis/PenaltyUserRedisRepository.java b/src/main/java/com/gg/server/domain/penalty/redis/PenaltyUserRedisRepository.java deleted file mode 100644 index efaf3cffc..000000000 --- a/src/main/java/com/gg/server/domain/penalty/redis/PenaltyUserRedisRepository.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.domain.penalty.redis; - -import com.gg.server.admin.penalty.type.PenaltyKey; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class PenaltyUserRedisRepository { - private final RedisTemplate redisTemplate; - - public void addPenaltyUser(RedisPenaltyUser penaltyUser, LocalDateTime releaseTime) { - LocalDateTime now = LocalDateTime.now(); - Duration duration = Duration.between(now, releaseTime); - redisTemplate.opsForValue().set(PenaltyKey.USER_ADMIN + penaltyUser.getIntraId(), penaltyUser, - duration.getSeconds(), TimeUnit.SECONDS); - } - public Optional findByIntraId(String intraId) { - RedisPenaltyUser penaltyUser = redisTemplate.opsForValue().get(PenaltyKey.USER_ADMIN + intraId); - return Optional.ofNullable(penaltyUser); - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/redis/RedisPenaltyUser.java b/src/main/java/com/gg/server/domain/penalty/redis/RedisPenaltyUser.java deleted file mode 100644 index eb12c011c..000000000 --- a/src/main/java/com/gg/server/domain/penalty/redis/RedisPenaltyUser.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.domain.penalty.redis; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import java.time.LocalDateTime; -import javax.persistence.Id; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; - -@Getter -@NoArgsConstructor -public class RedisPenaltyUser { - @Id - private String id; - private String intraId; - private Integer penaltyTime; - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime releaseTime; - - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - private LocalDateTime startTime; - private String reason; - - public RedisPenaltyUser(String intraId, Integer penaltyTime, LocalDateTime releaseTime, LocalDateTime startTime, - String reason) { - this.intraId = intraId; - this.penaltyTime = penaltyTime; - this.releaseTime = releaseTime; - this.startTime = startTime; - this.reason = reason; - } - - public void updateReleaseTime(LocalDateTime releaseTime, Integer penaltyTime) { - this.releaseTime = releaseTime; - this.penaltyTime = penaltyTime; - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java b/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java deleted file mode 100644 index ed680721d..000000000 --- a/src/main/java/com/gg/server/domain/penalty/service/PenaltyService.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gg.server.domain.penalty.service; - -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.data.PenaltyRepository; -import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.service.UserFindService; - -import java.time.LocalDateTime; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class PenaltyService { - private final PenaltyRepository penaltyRepository; - private final PenaltyUserRedisRepository penaltyUserRedisRepository; - private final UserFindService userFindService; - - /** - * penalty 1๋ถ„ ๋ถ€์—ฌ - * **/ - public void givePenalty(UserDto userDto, Integer penaltyMinutes) { - - User user = userFindService.findUserById(userDto.getId()); - Optional redisPenaltyUser = penaltyUserRedisRepository - .findByIntraId(userDto.getIntraId()); - LocalDateTime releaseTime; - RedisPenaltyUser penaltyUser; - Penalty penalty; - LocalDateTime now = LocalDateTime.now(); - if (redisPenaltyUser.isPresent()) { - releaseTime = redisPenaltyUser.get().getReleaseTime().plusMinutes(penaltyMinutes); - penaltyUser = new RedisPenaltyUser(userDto.getIntraId(), redisPenaltyUser.get().getPenaltyTime() + penaltyMinutes, - releaseTime, redisPenaltyUser.get().getStartTime(), "[AUTO] ๋งค์นญ ์ทจ์†Œ"); - penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] ๋งค์นญ ์ทจ์†Œ", redisPenaltyUser.get().getReleaseTime(), penaltyMinutes); - } else { - releaseTime = now.plusMinutes(penaltyMinutes); - penaltyUser = new RedisPenaltyUser(user.getIntraId(), penaltyMinutes, releaseTime, now, "[AUTO] ๋งค์นญ ์ทจ์†Œ"); - penalty = new Penalty(user, PenaltyType.CANCEL, "[AUTO] ๋งค์นญ ์ทจ์†Œ", now, penaltyMinutes); - } - penaltyRepository.save(penalty); - penaltyUserRedisRepository.addPenaltyUser(penaltyUser, releaseTime); - } - - public Boolean isPenaltyUser(String intraId) { - return penaltyUserRedisRepository.findByIntraId(intraId).isPresent(); - } -} diff --git a/src/main/java/com/gg/server/domain/penalty/type/PenaltyType.java b/src/main/java/com/gg/server/domain/penalty/type/PenaltyType.java deleted file mode 100644 index 98f584803..000000000 --- a/src/main/java/com/gg/server/domain/penalty/type/PenaltyType.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gg.server.domain.penalty.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum PenaltyType { - NONE("none"), - NOSHOW("noshow"), - CANCEL("cancel"); - - private final String code; - - public static PenaltyType of(String code) { - return Arrays.stream(PenaltyType.values()) - .filter(penaltyType-> penaltyType.getCode().equals(code)) - .findAny() - .orElse(NONE); - } - - @JsonCreator - public static PenaltyType getEnumFromValue(String value) { - for(PenaltyType e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/rank/controller/RankController.java b/src/main/java/com/gg/server/domain/rank/controller/RankController.java deleted file mode 100644 index 6fc5d3806..000000000 --- a/src/main/java/com/gg/server/domain/rank/controller/RankController.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gg.server.domain.rank.controller; - -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.service.RankService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong") -public class RankController { - - private final RankService rankService; - @GetMapping("/exp") - public ExpRankPageResponseDto getExpRankPage(@Valid PageRequestDto pageRequestDto, @Parameter(hidden = true) @Login UserDto user) { - PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), - Sort.by("totalExp").descending().and(Sort.by("intraId"))); - return rankService.getExpRankPageByRedis(pageRequest, user); - } - - /** - * - * @param pageRequestDto - * @param user - * @param season - * @param gameType - * - * gameType๋Š” single๋กœ ๊ณ ์ •๋˜์–ด ์˜ค๊ณ ์žˆ๋Š”๋ฐ ํ˜„์žฌ rank๊ฒŒ์ž„์€ single๋งŒ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด์„œ ์‚ฌ์šฉ ์•ˆํ•˜๊ธฐ๋กœ - */ - @GetMapping("/ranks/{gameType}") - public RankPageResponseDto getRankPage(@Valid PageRequestDto pageRequestDto, @Parameter(hidden = true) @Login UserDto user, - Long season, String gameType){ - PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize()); - return rankService.getRankPage(pageRequest, user, season); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/controller/RankV2Controller.java b/src/main/java/com/gg/server/domain/rank/controller/RankV2Controller.java deleted file mode 100644 index 1e4081e52..000000000 --- a/src/main/java/com/gg/server/domain/rank/controller/RankV2Controller.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.domain.rank.controller; - -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.service.RankService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import javax.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/v2") -public class RankV2Controller { - private final RankService rankService; - @GetMapping("/exp") - public ExpRankPageResponseDto getExpRankPage(@Valid PageRequestDto pageRequestDto, @Parameter(hidden = true) @Login UserDto user) { - PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize(), - Sort.by("totalExp").descending().and(Sort.by("intraId"))); - return rankService.getExpRankPage(pageRequest, user); - } - /** - * - * @param pageRequestDto - * @param user - * @param season - * @param gameType - * - * gameType๋Š” single๋กœ ๊ณ ์ •๋˜์–ด ์˜ค๊ณ ์žˆ๋Š”๋ฐ ํ˜„์žฌ rank๊ฒŒ์ž„์€ single๋งŒ ๊ตฌํ˜„๋˜์–ด์žˆ์–ด์„œ ์‚ฌ์šฉ ์•ˆํ•˜๊ธฐ๋กœ - */ - @GetMapping("/ranks/{gameType}") - public RankPageResponseDto getRankPage(@Valid PageRequestDto pageRequestDto, @Parameter(hidden = true) @Login UserDto user, - @RequestParam Long season, @PathVariable String gameType){ - PageRequest pageRequest = PageRequest.of(pageRequestDto.getPage() - 1, pageRequestDto.getSize()); - return rankService.getRankPageV2(pageRequest, user, season); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/data/Rank.java b/src/main/java/com/gg/server/domain/rank/data/Rank.java deleted file mode 100644 index 275f21646..000000000 --- a/src/main/java/com/gg/server/domain/rank/data/Rank.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.gg.server.domain.rank.data; - -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -@Entity -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Table(name="ranks") -public class Rank extends BaseTimeEntity implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "season_id") - private Season season; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "tier_id") - private Tier tier; - - @NotNull - @Column(name = "ppp") - private Integer ppp; - - @NotNull - @Column(name = "wins") - private Integer wins; - - @NotNull - @Column(name = "losses") - private Integer losses; - - @Column(name = "status_message", length = 30) - private String statusMessage; - - - public static Rank from (User user, Season season, Integer ppp, Tier tier) { - return Rank.builder() - .user(user) - .ppp(ppp) - .season(season) - .wins(0) - .losses(0) - .statusMessage("") - .tier(tier) - .build(); - } - - @Builder - public Rank(User user, Season season, Integer ppp, Integer wins, - Integer losses, String statusMessage, Tier tier) { - this.user = user; - this.season = season; - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - this.statusMessage = statusMessage; - this.tier = tier; - } - - public void setStatusMessage(String statusMessage) { - this.statusMessage = statusMessage; - } - - public void modifyUserRank(UserUpdateAdminRequestDto userUpdateAdminRequestDto) { - this.ppp = userUpdateAdminRequestDto.getPpp(); - this.wins = userUpdateAdminRequestDto.getWins(); - this.losses = userUpdateAdminRequestDto.getLosses(); - } - - public void modifyUserRank(Integer ppp, int wins, int losses) { - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - } - - public void updateTier(Tier tier) { - this.tier = tier; - } -} diff --git a/src/main/java/com/gg/server/domain/rank/data/RankRepository.java b/src/main/java/com/gg/server/domain/rank/data/RankRepository.java deleted file mode 100644 index a453cd817..000000000 --- a/src/main/java/com/gg/server/domain/rank/data/RankRepository.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.gg.server.domain.rank.data; - -import com.gg.server.domain.rank.dto.RankV2Dto; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -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 java.util.List; -import java.util.Optional; - -@Repository -public interface RankRepository extends JpaRepository { - Optional findByUserIdAndSeasonId(Long userId, Long seasonId); - - @Modifying(clearAutomatically = true) - @Query("delete from Rank r where r.season.id=:seasonId") - void deleteAllBySeasonId(@Param("seasonId") Long seasonId); - - Optional findFirstByOrderByCreatedAtDesc(); - - @EntityGraph(attributePaths = {"user", "tier"}) - List findAllBySeasonId(Long seasonId); - - List findAllBySeasonIdOrderByPppDesc(Long seasonId); - - @Query(value = "select count(r) from Rank r where r.season.id=:seasonId and not (r.wins = 0 and r.losses = 0)") - Long countRealRankPlayers(@Param("seasonId") Long seasonId); - - @Query(value = "SELECT u.intra_id intraId, r.status_message statusMessage, r.ppp, " - + "t.image_uri tierImageUri, u.text_color textColor, " - + "RANK() OVER(ORDER BY r.ppp DESC, pg.created_at ASC, u.total_exp DESC) AS ranking " - + "FROM Ranks r " - + "INNER JOIN Tier t " - + "ON r.tier_id = t.id " - + "INNER JOIN User u " - + "ON r.user_id = u.id " - + "INNER JOIN (SELECT MAX(p.created_at) created_at, p.user_id user_id " - + " FROM PChange p" - + " INNER JOIN Game g" - + " ON p.game_id = g.id" - + " WHERE g.season_id = :seasonId" - + " GROUP BY p.user_id) pg " - + "ON pg.user_id = u.id " - + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) " - + "LIMIT :limit OFFSET :offset ", nativeQuery = true) - List findPppRankBySeasonId(@Param("offset")int offset, @Param("limit")int limit, @Param("seasonId") Long seasonId); - - @Query(value = "SELECT count(*) " - + "FROM Ranks r " - + "INNER JOIN User u " - + "ON r.user_id = u.id " - + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) ", nativeQuery = true) - int countRankUserBySeasonId(@Param("seasonId")Long seasonId); - - @Query(value = "SELECT ranked.ranking " - + "FROM (" - + "SELECT u.id userId, RANK() OVER(ORDER BY r.ppp DESC, pg.created_at ASC, u.total_exp DESC) AS ranking " - + "FROM Ranks r " - + "INNER JOIN User u " - + "ON r.user_id = u.id " - + "INNER JOIN (SELECT MAX(p.created_at) created_at, p.user_id user_id " - + " FROM PChange p" - + " INNER JOIN Game g" - + " ON p.game_id = g.id" - + " WHERE g.season_id = :seasonId" - + " GROUP BY p.user_id) pg " - + "ON pg.user_id = u.id " - + "WHERE r.season_id = :seasonId AND (r.losses > 0 OR r.wins > 0) " - + ") ranked " - + "WHERE ranked.userId = :userId", nativeQuery = true) - Optional findRankByUserIdAndSeasonId(@Param("userId")Long userId, @Param("seasonId")Long seasonId); -} diff --git a/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java b/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java deleted file mode 100644 index fd2896def..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/ExpRankDto.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.gg.server.domain.rank.dto; - -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class ExpRankDto { - private String intraId; - private Integer rank; - private String statusMessage; - private Integer level; - private Integer exp; - private String userImageUri; - private String textColor; - - public static ExpRankDto from (User user, Integer rank, String statusMessage){ - ExpRankDto dto = ExpRankDto.builder() - .intraId(user.getIntraId()) - .rank(user.getTotalExp() == 0 ? -1 : rank) - .statusMessage(statusMessage) - .level(ExpLevelCalculator.getLevel(user.getTotalExp())) - .exp(user.getTotalExp()) - .userImageUri(user.getImageUri()) - .textColor(user.getTextColor()) - .build(); - return dto; - } - public static ExpRankDto from(ExpRankV2Dto dto) { - return ExpRankDto.builder() - .intraId(dto.getIntraId()) - .rank(dto.getRanking()) - .statusMessage(dto.getStatusMessage()) - .level(ExpLevelCalculator.getLevel(dto.getTotalExp())) - .exp(dto.getTotalExp()) - .userImageUri(dto.getImageUri()) - .textColor(dto.getTextColor()) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/rank/dto/ExpRankPageResponseDto.java b/src/main/java/com/gg/server/domain/rank/dto/ExpRankPageResponseDto.java deleted file mode 100644 index e645f9dee..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/ExpRankPageResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.rank.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import java.util.List; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class ExpRankPageResponseDto { - private int myRank; - private int currentPage; - private int totalPage; - private List rankList; -} diff --git a/src/main/java/com/gg/server/domain/rank/dto/ExpRankV2Dto.java b/src/main/java/com/gg/server/domain/rank/dto/ExpRankV2Dto.java deleted file mode 100644 index ec2958f13..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/ExpRankV2Dto.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.rank.dto; - -public interface ExpRankV2Dto { - String getIntraId(); - String getStatusMessage(); - Integer getTotalExp(); - String getImageUri(); - String getTextColor(); - Integer getRanking(); - -} diff --git a/src/main/java/com/gg/server/domain/rank/dto/RankDto.java b/src/main/java/com/gg/server/domain/rank/dto/RankDto.java deleted file mode 100644 index d31e9190c..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/RankDto.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.domain.rank.dto; - -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.user.data.User; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class RankDto { - private String intraId; - private int rank; - private int ppp; - private String statusMessage; - private String tierImageUri; - private String textColor; - - - public static RankDto from(User user, RankRedis rankRedis, Integer rank) { - RankDto dto = RankDto.builder() - .intraId(user.getIntraId()) - .rank(rank) - .ppp(rankRedis.getPpp()) - .statusMessage(rankRedis.getStatusMessage()) - .tierImageUri(rankRedis.getTierImageUri()) - .textColor(user.getTextColor()) - .build(); - return dto; - } - public static RankDto from(RankV2Dto dto) { - return RankDto.builder() - .intraId(dto.getIntraId()) - .rank(dto.getRanking()) - .ppp(dto.getPpp()) - .statusMessage(dto.getStatusMessage()) - .tierImageUri(dto.getTierImageUri()) - .textColor(dto.getTextColor()) - .build(); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java b/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java deleted file mode 100644 index 3bd4a4dee..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/RankPageResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.rank.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class RankPageResponseDto { - private int myRank; - private int currentPage; - private int totalPage; - private List rankList; -} diff --git a/src/main/java/com/gg/server/domain/rank/dto/RankV2Dto.java b/src/main/java/com/gg/server/domain/rank/dto/RankV2Dto.java deleted file mode 100644 index 9f84562ad..000000000 --- a/src/main/java/com/gg/server/domain/rank/dto/RankV2Dto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.domain.rank.dto; - -public interface RankV2Dto { - - String getIntraId(); - String getStatusMessage(); - Integer getPpp(); - String getTierImageUri(); - String getTextColor(); - Integer getRanking(); - -} diff --git a/src/main/java/com/gg/server/domain/rank/exception/RankNotFoundException.java b/src/main/java/com/gg/server/domain/rank/exception/RankNotFoundException.java deleted file mode 100644 index 92b552fe2..000000000 --- a/src/main/java/com/gg/server/domain/rank/exception/RankNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.rank.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class RankNotFoundException extends NotExistException { - public RankNotFoundException() { - super("๋žญํฌ ํ…Œ์ด๋ธ”์— ์—†๋Š” ์œ ์ €์ž…๋‹ˆ๋‹ค.", ErrorCode.RANK_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/exception/RankUpdateException.java b/src/main/java/com/gg/server/domain/rank/exception/RankUpdateException.java deleted file mode 100644 index 524a68a2c..000000000 --- a/src/main/java/com/gg/server/domain/rank/exception/RankUpdateException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.rank.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; - -public class RankUpdateException extends InvalidParameterException { - public RankUpdateException() { - super("Ppp๋ฅผ ์ˆ˜์ • ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค", ErrorCode.RANK_UPDATE_FAIL); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/exception/RedisDataNotFoundException.java b/src/main/java/com/gg/server/domain/rank/exception/RedisDataNotFoundException.java deleted file mode 100644 index 32e7fbe98..000000000 --- a/src/main/java/com/gg/server/domain/rank/exception/RedisDataNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.rank.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class RedisDataNotFoundException extends NotExistException { - public RedisDataNotFoundException() { - super("Redis์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.REDIS_RANK_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java deleted file mode 100644 index eb0590c35..000000000 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedis.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.gg.server.domain.rank.redis; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.user.dto.UserDto; -import lombok.*; -import org.springframework.data.redis.core.RedisHash; - -import java.io.Serializable; - -@RedisHash("rank") -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class RankRedis implements Serializable { - private Long userId; - private String intraId; - private int ppp; - private int wins; - private int losses; - private String statusMessage; - private String tierImageUri; - private String textColor; - - public void updateRank(int changePpp, int wins, int losses) { - this.ppp += changePpp; - this.wins = wins; - this.losses = losses; - } - - public void updateTierImage(String tierImageUri) { - this.tierImageUri = tierImageUri; - } - - public void changedRank(int ppp, int wins, int losses) { - this.ppp = ppp; - this.wins = wins; - this.losses = losses; - } - - public void setStatusMessage(String msg) { - this.statusMessage = msg; - } - - public static RankRedis from(UserDto user, Integer ppp, String tierImageUri) { - RankRedis rankRedis = RankRedis.builder() - .userId(user.getId()) - .intraId(user.getIntraId()) - .ppp(ppp) - .wins(0) - .losses(0) - .statusMessage("") - .tierImageUri(tierImageUri) - .textColor(user.getTextColor()) - .build(); - return rankRedis; - } - - public static RankRedis from(Rank rank) { - RankRedis rankRedis = RankRedis.builder() - .userId(rank.getUser().getId()) - .intraId(rank.getUser().getIntraId()) - .ppp(rank.getPpp()) - .wins(rank.getWins()) - .losses(rank.getLosses()) - .statusMessage(rank.getStatusMessage()) - .tierImageUri(rank.getTier().getImageUri()) - .textColor(rank.getUser().getTextColor()) - .build(); - return rankRedis; - } - - @Override - public String toString() { - return "RankRedis{" + - "userId=" + userId + - ", intraId='" + intraId + '\'' + - ", ppp=" + ppp + - ", wins=" + wins + - ", losses=" + losses + - ", statusMessage='" + statusMessage + '\'' + - ", tierImageUri='" + tierImageUri + '\'' + - ", textColor='" + textColor + '\'' + - '}'; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java deleted file mode 100644 index a64fce40f..000000000 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedisRepository.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.gg.server.domain.rank.redis; - -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import org.springframework.data.redis.core.HashOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ZSetOperations; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Comparator; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@Repository -public class RankRedisRepository { - private final ZSetOperations zSetOps; - private final HashOperations hashOps; - private final RedisTemplate redisTemplate; - - public RankRedisRepository(RedisTemplate redisTemplate) { - this.zSetOps = redisTemplate.opsForZSet(); - this.hashOps = redisTemplate.opsForHash(); - this.redisTemplate = redisTemplate; - } - - /** - * - * @param key - * @param userId - * @param ppp - * - * ZSET์— user๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ - */ - public void addToZSet(String key, Long userId, int ppp) { - zSetOps.add(key, userId.toString(), ppp); - } - - /** - * - * @param key - * @param userId - * @param ppp - * - * ZSET์—์„œ user์˜ ppp ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ฉ”์„œ๋“œ - */ - public void incrementScoreInZSet(String key, Long userId, int ppp) { - zSetOps.incrementScore(key, userId.toString(), ppp); - - } - - - /** - * - * @param key - * @param userId - * @param ppp - * - * ZSET์—์„œ user์˜ ppp๋ฅผ ๊ฐ์†Œ์‹œํ‚ค๋Š” ๋ฉ”์„œ๋“œ - */ - public void decrementScoreInZSet(String key, Long userId, int ppp) { - zSetOps.incrementScore(key, userId.toString(), -ppp); - } - - /** - * - * @param key - * @param userId - * - * ZSET์—์„œ user๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์„œ๋“œ - */ - public void deleteFromZSet(String key, Long userId) { - zSetOps.remove(key, userId.toString()); - } - - /** - * - * @param key - * @param userId - * @return 0 -> 1๋“ฑ - * - * ZSET์—์„œ user์˜ ์ˆœ์œ„(rank)๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์„œ๋“œ ppp๊ฐ€ ๋†’์€์ˆœ - */ - public Long getRankInZSet(String key, Long userId) { - Long result = zSetOps.reverseRank(key, userId.toString()); - if(result == null) - throw new RedisDataNotFoundException(); - return result; - } - - - /** - * - * @param key - * @param userId - * - * ZSET์—์„œ user์˜ ppp๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์„œ๋“œ - */ - public Long getScoreInZSet(String key, Long userId) { - Double result = zSetOps.score(key, userId.toString()); - if(result == null) - throw new RedisDataNotFoundException(); - return result.longValue(); - } - - /** - * - * @param key - * @param startRank - * @param endRank - * - * Zset์—์„œ user์˜ ๋žญํ‚น ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ทธ ๋ฒ”์œ„ ๋‚ด์˜ userId๋“ค์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ - * startRank -> 0๋ถ€ํ„ฐ ์‹œ์ž‘ - */ - public List getUserIdsByRangeFromZSet(String key, long startRank, long endRank) { - Set result = zSetOps.reverseRange(key, startRank, endRank); - List stringList = result.stream().map(Object::toString).collect(Collectors.toList()); - if (result == null) - throw new RedisDataNotFoundException(); - return stringList.stream() - .map(Long::parseLong).collect(Collectors.toList()); - } - - - - /** - * - * @param key - * @param userId - * @param userRank - * redis hash์— user rank๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์†Œ๋“œ - */ - public void addRankData(String key, Long userId, RankRedis userRank){ - hashOps.put(key, userId.toString(), userRank); - } - - /** - * - * @param key - * @param userId - * - * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์†Œ๋“œ - */ - public RankRedis findRankByUserId(String key, Long userId) { - Object result = hashOps.get(key, userId.toString()); - if (result == null) - throw new RedisDataNotFoundException(); - return RankRedis.class.cast(result); - } - - /** - * - * @param key - * @param userId - * @param userRank - * - * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฉ”์†Œ๋“œ - */ - public void updateRankData(String key, Long userId, RankRedis userRank) { - hashOps.put(key, userId.toString(), userRank); - } - - /** - * - * @param key - * @param userId - * - * ํ•ด๋‹น ์œ ์ €์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์†Œ๋“œ - */ - public void deleteRankData(String key, Long userId) { - hashOps.delete(key, userId.toString()); - } - - - /** - * - * @param key - * @param userIds - * - * ํ•ด๋‹น ์œ ์ €๋“ค์˜ rank๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฉ”์†Œ๋“œ - */ - public List findRanksByUserIds(String key, List userIds) { - List userIdsStr = userIds.stream().map(String::valueOf).collect(Collectors.toList()); - List objects = hashOps.multiGet(key, userIdsStr); - if(objects == null) - throw new RedisDataNotFoundException(); - return objects.stream().map(RankRedis.class::cast).collect(Collectors.toList()); - } - - public List findAllRanksOrderByPppDesc(String key) { - List objects = hashOps.values(key); - if(objects == null) - throw new RedisDataNotFoundException(); - return objects.stream().map(RankRedis.class::cast).sorted(Comparator.comparing(RankRedis::getPpp).reversed()).collect(Collectors.toList()); - } - - public Long countTotalRank(String zSetKey) { - Long result = zSetOps.size(zSetKey); - if(result == null) - throw new RedisDataNotFoundException(); - return result; - } - - public void deleteAll(){ - redisTemplate.delete(redisTemplate.keys("*")); - } - public void deleteZSetKey(String key) { - redisTemplate.delete(key); - } - - public void deleteHashKey(String key) { - redisTemplate.delete(key); - } - - public Boolean isEmpty(String hashKey) { - return hashOps.size(hashKey) == 0; - } -} diff --git a/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java b/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java deleted file mode 100644 index ed4aeadf6..000000000 --- a/src/main/java/com/gg/server/domain/rank/redis/RankRedisService.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.gg.server.domain.rank.redis; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.pchange.service.PChangeService; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; -import com.gg.server.global.utils.EloRating; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Slf4j -public class RankRedisService { - private final RankRedisRepository rankRedisRepository; - private final TierRepository tierRepository; - private final PChangeService pChangeService; - private final RankRepository rankRepository; - private final SeasonFindService seasonFindService; - - public Integer getUserPpp(Long userId, Long seasonId) { - String hashKey = RedisKeyManager.getHashKey(seasonId); - return rankRedisRepository.findRankByUserId(hashKey, userId).getPpp(); - } - public void updateRankRedis(TeamUser myTeamUser, TeamUser enemyTeamUser, Game game) { - // ๋‹จ์‹ -> 2๋ช… ๊ธฐ์ค€ - String key = RedisKeyManager.getHashKey(game.getSeason().getId()); - String zsetKey = RedisKeyManager.getZSetKey(game.getSeason().getId()); - RankRedis myTeam = rankRedisRepository.findRankByUserId(key, myTeamUser.getUser().getId()); - RankRedis enemyTeam = rankRedisRepository.findRankByUserId(key, enemyTeamUser.getUser().getId()); - Integer myPPP = myTeam.getPpp(); - Integer enemyPPP = enemyTeam.getPpp(); - updatePPP(myTeamUser, myTeam, enemyTeamUser.getTeam().getScore(), myPPP, enemyPPP, game.getSeason().getId()); - updatePPP(enemyTeamUser, enemyTeam, myTeamUser.getTeam().getScore(), enemyPPP, myPPP, game.getSeason().getId()); - updateRankUser(key, zsetKey, myTeamUser.getUser().getId(), myTeam); - updateRankUser(key, zsetKey, enemyTeamUser.getUser().getId(), enemyTeam); - pChangeService.addPChange(game, myTeamUser.getUser(), myTeam.getPpp(), true); - pChangeService.addPChange(game, enemyTeamUser.getUser(), enemyTeam.getPpp(), false); - } - - private void updateRankUser(String hashKey, String zsetKey, Long userId, RankRedis userRank) { - rankRedisRepository.updateRankData(hashKey, userId, userRank); - rankRedisRepository.deleteFromZSet(zsetKey, userId); - rankRedisRepository.addToZSet(zsetKey, userId, userRank.getPpp()); - } - - @Transactional - public void updatePPP(TeamUser teamuser, RankRedis myTeam, int enemyScore, Integer myPPP, Integer enemyPPP, Long seasonId) { - int win = teamuser.getTeam().getWin() ? myTeam.getWins() + 1 : myTeam.getWins(); - int losses = !teamuser.getTeam().getWin() ? myTeam.getLosses() + 1: myTeam.getLosses(); - // rank table ์ˆ˜์ • - Rank rank = rankRepository.findByUserIdAndSeasonId(myTeam.getUserId(), seasonId) - .orElseThrow(() -> new NotExistException("rank ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.NOT_FOUND)); - Integer changedPpp = EloRating.pppChange(myPPP, enemyPPP, - teamuser.getTeam().getWin(), - Math.abs(teamuser.getTeam().getScore() - enemyScore) == 2); - log.info("update before: intraId: " + teamuser.getUser().getIntraId() + ", win: db(" + rank.getWins() - + "), redis(" + myTeam.getWins() + "), losses: db(" + rank.getLosses() - + "), redis(" + myTeam.getLosses() + ")"); - rank.modifyUserRank(rank.getPpp() + changedPpp, win, losses); - myTeam.updateRank(changedPpp, - win, losses); - log.info("update after: intraId: " + teamuser.getUser().getIntraId() + ", win: db(" + rank.getWins() - + "), redis(" + myTeam.getWins() + "), losses: db(" + rank.getLosses() - + "), redis(" + myTeam.getLosses() + ")"); - } - - @Transactional - public void updateAllTier(Long gameId) { - // ์ „์ฒด ๋ ˆ๋””์Šค ๋žญํฌ ํ‹ฐ์–ด ์ƒˆ๋กœ๊ณ ์นจํ•˜๋Š” ๋กœ์ง - Season targetSeason = seasonFindService.findSeasonByGameId(gameId); - String key = RedisKeyManager.getHashKey(targetSeason.getId()); - String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); - List rankRedisList = rankRedisRepository.findAllRanksOrderByPppDesc(key); - Long totalRankPlayers = rankRepository.countRealRankPlayers(targetSeason.getId()); - List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); - - int top30percentPpp = rankRedisList.get((int) (totalRankPlayers * 0.3)).getPpp(); - int top10percentPpp = rankRedisList.get((int) (totalRankPlayers * 0.1)).getPpp(); - - for (int i = 0; i < rankRedisList.size(); i++) { - RankRedis rankRedis = rankRedisList.get(i); - if (rankRedis.getWins() == 0 && rankRedis.getLosses() == 0) { - rankRedis.updateTierImage(tierList.get(0).getImageUri()); - } else { - if (i < 3) { - rankRedis.updateTierImage(tierList.get(6).getImageUri()); - updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); - continue; - } - if (rankRedis.getPpp() < 970) { - // 970 ๋ฏธ๋งŒ - rankRedis.updateTierImage(tierList.get(1).getImageUri()); - } else if (rankRedis.getPpp() < 1010) { - // 970 ~ 1009 - rankRedis.updateTierImage(tierList.get(2).getImageUri()); - } else if (rankRedis.getPpp() < 1050) { - // 1010 ~ 1049 - rankRedis.updateTierImage(tierList.get(3).getImageUri()); - } else { - if ((rankRedis.getPpp() >= top30percentPpp) && (rankRedis.getPpp() < top10percentPpp)) { - // 1050 ์ด์ƒ, 30% ์ด์ƒ, 10% ๋ฏธ๋งŒ - rankRedis.updateTierImage(tierList.get(4).getImageUri()); - } else if (rankRedis.getPpp() >= top10percentPpp) { - // 1050 ์ด์ƒ, 10% ์ด์ƒ - rankRedis.updateTierImage(tierList.get(5).getImageUri()); - } else { - // 1050 ์ด์ƒ, 30% ๋ฏธ๋งŒ - rankRedis.updateTierImage(tierList.get(3).getImageUri()); - } - } - updateRankUser(key, zSetKey, rankRedis.getUserId(), rankRedis); - } - } - } - - public void rollbackRank(TeamUser teamUser, int ppp, Long seasonId) { - String hashkey = RedisKeyManager.getHashKey(seasonId); - RankRedis myTeam = rankRedisRepository.findRankByUserId(hashkey, teamUser.getUser().getId()); - int win = teamUser.getTeam().getWin() ? myTeam.getWins() - 1 : myTeam.getWins(); - int losses = !teamUser.getTeam().getWin() ? myTeam.getLosses() - 1: myTeam.getLosses(); - Rank rank = rankRepository.findByUserIdAndSeasonId(myTeam.getUserId(), seasonId) - .orElseThrow(RankNotFoundException::new); - log.info("Before: userId: " + teamUser.getUser().getIntraId() + ", " + "ppp: rank(" - + rank.getPpp() + "), redis(" + myTeam.getPpp() + "), win: " + myTeam.getWins() - + ", losses: " + myTeam.getLosses()); - rank.modifyUserRank(ppp, win, losses); - myTeam.changedRank(ppp, win, losses); - rankRepository.flush(); - updateRankUser(hashkey, RedisKeyManager.getZSetKey(seasonId), teamUser.getUser().getId(), myTeam); - log.info("After: userId: " + teamUser.getUser().getIntraId() + ", " + "ppp: rank(" - + rank.getPpp() + "), redis(" + myTeam.getPpp() + "), win: " + myTeam.getWins() - + ", losses: " + myTeam.getLosses()); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/redis/RedisKeyManager.java b/src/main/java/com/gg/server/domain/rank/redis/RedisKeyManager.java deleted file mode 100644 index ebff0d996..000000000 --- a/src/main/java/com/gg/server/domain/rank/redis/RedisKeyManager.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.rank.redis; - -public class RedisKeyManager { - private static final String ZSetKeyPrefix = "rank:ZSet:"; - private static final String HashKeyPrefix = "rank:hash:"; - private static final String RefKeyPrefix = "refresh:token:"; - - public static String getZSetKey(Long seasonId) { - return ZSetKeyPrefix + seasonId; - } - - public static String getHashKey(Long seasonId) { - return HashKeyPrefix + seasonId; - } - - public static String getRefKey(Long id) { - return RefKeyPrefix + id.toString(); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/service/RankFindService.java b/src/main/java/com/gg/server/domain/rank/service/RankFindService.java deleted file mode 100644 index f6e7e1f87..000000000 --- a/src/main/java/com/gg/server/domain/rank/service/RankFindService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.rank.service; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -public class RankFindService { - private final RankRepository rankRepository; - - public Rank findByUserIdAndSeasonId(Long userId, Long seasonId){ - return rankRepository.findByUserIdAndSeasonId(userId, seasonId).orElseThrow(() -> new RankNotFoundException()); - } -} diff --git a/src/main/java/com/gg/server/domain/rank/service/RankService.java b/src/main/java/com/gg/server/domain/rank/service/RankService.java deleted file mode 100644 index 4042287a1..000000000 --- a/src/main/java/com/gg/server/domain/rank/service/RankService.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.gg.server.domain.rank.service; - -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.dto.ExpRankDto; -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.ExpRankV2Dto; -import com.gg.server.domain.rank.dto.RankDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.dto.RankV2Dto; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.PageNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class RankService { - private final UserRepository userRepository; - private final RankRedisRepository redisRepository; - private final SeasonFindService seasonFindService; - private final RankRepository rankRepository; - - @Transactional(readOnly = true) - public ExpRankPageResponseDto getExpRankPageByRedis(PageRequest pageRequest, UserDto curUser) { - - Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); - Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); - if(pageRequest.getPageNumber() + 1 > users.getTotalPages()) - throw new PageNotFoundException("ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.PAGE_NOT_FOUND); - - List userIds = users.getContent().stream().map(user -> user.getId()).collect(Collectors.toList()); - Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - - String hashKey = RedisKeyManager.getHashKey(curSeason.getId()); - List ranks = redisRepository.findRanksByUserIds(hashKey, userIds); - - Integer startRank = pageRequest.getPageSize() * pageRequest.getPageNumber() + 1; - List expRankDtos = new ArrayList<>(); - for(int i = 0; i < ranks.size(); i++) { - RankRedis rank = ranks.get(i); - User user = users.getContent().get(i); - expRankDtos.add(ExpRankDto.from(user, startRank + i, rank.getStatusMessage())); - } - - return new ExpRankPageResponseDto(myRank.intValue(), pageRequest.getPageNumber() + 1, users.getTotalPages(), expRankDtos); - } - - /** - * ExpRankPage v2 (redis ์กฐํšŒ ์ œ๊ฑฐ - db ์กฐํšŒ๋กœ๋งŒ ํ•˜๋Š” ๊ธฐ๋Šฅ) - * @param pageRequest - * @param curUser - * @return - */ - @Transactional(readOnly = true) - public ExpRankPageResponseDto getExpRankPage(PageRequest pageRequest, UserDto curUser) { - - Long myRank = curUser.getTotalExp() == 0 ? -1 : userRepository.findExpRankingByIntraId(curUser.getIntraId()); - Page users = userRepository.findAllByTotalExpGreaterThan(pageRequest, 0); - if(pageRequest.getPageNumber() + 1 > users.getTotalPages()) - throw new PageNotFoundException(); - List expRankDtos = getExpRankList(pageRequest); - - return new ExpRankPageResponseDto(myRank.intValue(), - pageRequest.getPageNumber() + 1, - users.getTotalPages(), - expRankDtos); - } - - @Cacheable(value = "expRanking", cacheManager = "gameCacheManager", - key = "#pageRequest.pageNumber + #pageRequest.pageSize.toString()") - public List getExpRankList(PageRequest pageRequest) { - Season curSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - int pageOffset = pageRequest.getPageNumber() * pageRequest.getPageSize(); - List expRankV2Dtos = userRepository.findExpRank(pageOffset, pageRequest.getPageSize(), curSeason.getId()); - return expRankV2Dtos.stream().map(ExpRankDto::from).collect(Collectors.toList()); - } - - /** - * rank ํŽ˜์ด์ง€ ์กฐํšŒ v2 - * @param pageRequest - * @param curUser - * @param seasonId - * @return - */ - @Transactional(readOnly = true) - @Cacheable(value = "ranking", cacheManager = "gameCacheManager", - key = "#pageRequest.pageSize.toString() + #pageRequest.pageNumber + #curUser.id + #seasonId") - public RankPageResponseDto getRankPageV2(PageRequest pageRequest, UserDto curUser, Long seasonId) { - Season season; - if (seasonId == null || seasonId == 0) { - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - } else { - season = seasonFindService.findSeasonById(seasonId); - } - int totalPage = calcTotalPageV2(season, pageRequest.getPageSize()); - if (totalPage == 0) - return returnEmptyRankPage(); - if (pageRequest.getPageNumber() + 1 > totalPage) - throw new PageNotFoundException(); - - int myRank = rankRepository.findRankByUserIdAndSeasonId(curUser.getId(), season.getId()) - .orElse(-1); - int pageOffset = pageRequest.getPageNumber() * pageRequest.getPageSize(); - List rankList = rankRepository.findPppRankBySeasonId(pageOffset, pageRequest.getPageSize(), season.getId()) - .stream().map(RankDto::from).collect(Collectors.toList()); - return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); - } - - @Transactional(readOnly = true) - public RankPageResponseDto getRankPage(PageRequest pageRequest, UserDto curUser, Long seasonId) { - Season season; - if (seasonId == null || seasonId == 0) { - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - } else { - season = seasonFindService.findSeasonById(seasonId); - } - int totalPage = calcTotalPage(season, pageRequest.getPageSize()); - if (totalPage == 0) - return returnEmptyRankPage(); - if (pageRequest.getPageNumber() + 1 > totalPage) - throw new PageNotFoundException("ํŽ˜์ด์ง€๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.PAGE_NOT_FOUND); - - int myRank = findMyRank(curUser, season); - int startRank = pageRequest.getPageNumber() * pageRequest.getPageSize(); - int endRank = startRank + pageRequest.getPageSize() - 1; - List rankList = createRankList(startRank, endRank, season); - return new RankPageResponseDto(myRank, pageRequest.getPageNumber() + 1, totalPage, rankList); - } - - private RankPageResponseDto returnEmptyRankPage() { - return new RankPageResponseDto(-1, 1, 1, new ArrayList<>()); - } - private int findMyRank(UserDto curUser, Season season) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - try { - Long myRank = redisRepository.getRankInZSet(zSetKey, curUser.getId()); - return myRank.intValue() + 1; - } catch (RedisDataNotFoundException e) { - return -1; - } - } - private int calcTotalPage(Season season, int pageSize) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - try{ - Long totalUserCount = redisRepository.countTotalRank(zSetKey); - return (int) Math.ceil((double) totalUserCount / pageSize); - } catch (RedisDataNotFoundException e) { - return 0; - } - } - private int calcTotalPageV2(Season season, int pageSize) { - try{ - Integer totalUserCount = rankRepository.countRankUserBySeasonId(season.getId()); - return (int) Math.ceil((double) totalUserCount / pageSize); - } catch (RedisDataNotFoundException e) { - return 0; - } - } - private List createRankList(int startRank, int endRank, Season season) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - - List userIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, startRank, endRank); - List userRanks = redisRepository.findRanksByUserIds(hashKey, userIds); - List rankList = new ArrayList<>(); - - for (int i = 0; i < userRanks.size(); i++) { - User user = userRepository.findById(userIds.get(i)).orElseThrow(UserNotFoundException::new); - rankList.add(RankDto.from(user, userRanks.get(i), ++startRank)); - } -// for (RankRedis userRank : userRanks) { -// rankList.add(RankDto.from()) -// rankList.add(RankDto.from(userRank, ++startRank)); -// } - return rankList; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/rank/service/RedisUploadService.java b/src/main/java/com/gg/server/domain/rank/service/RedisUploadService.java deleted file mode 100644 index 35c47c883..000000000 --- a/src/main/java/com/gg/server/domain/rank/service/RedisUploadService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.gg.server.domain.rank.service; - -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.PostConstruct; -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -public class RedisUploadService { - private final RankRedisRepository redisRepository; - private final SeasonRepository seasonRepository; - private final RankRepository rankRepository; - private final RedisTemplate redisTemplate; - - @PostConstruct - @Transactional - public void uploadRedis() { - seasonRepository.findCurrentSeason(LocalDateTime.now()).ifPresent( currentSeason -> { - String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); - if(redisRepository.isEmpty(hashKey)) upload(); - }); - } - - private void upload() { - - redisTemplate.executePipelined((RedisCallback) connection ->{ - seasonRepository.findAll().forEach(season -> { - String hashKey = RedisKeyManager.getHashKey(season.getId()); - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - rankRepository.findAllBySeasonId(season.getId()).forEach(rank -> { - RankRedis rankRedis = RankRedis.from(rank); - connection.hSet(keySerializer().serialize(hashKey), - hashKeySerializer().serialize(rank.getUser().getId().toString()), - hashValueSerializer().serialize(rankRedis)); - if (rank.getWins() + rankRedis.getLosses() != 0){ - connection.zAdd(keySerializer().serialize(zSetKey), rank.getPpp(), - valueSerializer().serialize(rank.getUser().getId().toString())); - } - }); - }); - return null; - }); - } - - private RedisSerializer valueSerializer() { - return redisTemplate.getValueSerializer(); - } - - private RedisSerializer hashValueSerializer() { - return redisTemplate.getHashValueSerializer(); - } - - private RedisSerializer hashKeySerializer() { - return redisTemplate.getHashKeySerializer(); - } - - private RedisSerializer keySerializer() { - return redisTemplate.getKeySerializer(); - } - -} diff --git a/src/main/java/com/gg/server/domain/receipt/data/Receipt.java b/src/main/java/com/gg/server/domain/receipt/data/Receipt.java deleted file mode 100644 index 33df458ca..000000000 --- a/src/main/java/com/gg/server/domain/receipt/data/Receipt.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.gg.server.domain.receipt.data; - -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.receipt.type.ItemStatus; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Entity -public class Receipt { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "item_id") - private Item item; - - @NotNull - @Column(name = "purchaser_intra_id") - private String purchaserIntraId; - - @NotNull - @Column(name = "owner_intra_id") - private String ownerIntraId; - - @NotNull - @Enumerated(EnumType.STRING) - private ItemStatus status; - - @NotNull - @Column(name = "created_at") - private LocalDateTime createdAt; - - public Receipt(Item item, String purchaserIntraId, String ownerIntraId, - ItemStatus status, LocalDateTime purchasedAt) { - this.item = item; - this.purchaserIntraId = purchaserIntraId; - this.ownerIntraId = ownerIntraId; - this.status = status; - this.createdAt = purchasedAt; - } - - @Override - public String toString() { - return "Receipt{" + - "id=" + id + - ", item=" + item + - ", purchaserIntraId='" + purchaserIntraId + '\'' + - ", ownerIntraId='" + ownerIntraId + '\'' + - ", status=" + status + - ", purchasedAt=" + createdAt + - '}'; - } - - public void updateStatus(ItemStatus status) { - this.status = status; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java b/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java deleted file mode 100644 index 22463618d..000000000 --- a/src/main/java/com/gg/server/domain/receipt/data/ReceiptRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.gg.server.domain.receipt.data; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ReceiptRepository extends JpaRepository { -} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java b/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java deleted file mode 100644 index 102c8f46f..000000000 --- a/src/main/java/com/gg/server/domain/receipt/exception/ItemStatusException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.receipt.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; - -public class ItemStatusException extends BusinessException { - public ItemStatusException() {super("์•„์ดํ…œ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_STATUS_NOT_MATCHED);} -} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java deleted file mode 100644 index 711812ea4..000000000 --- a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotFoundException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.receipt.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class ReceiptNotFoundException extends NotExistException { - public ReceiptNotFoundException() {super("ํ•ด๋‹น ๊ฑฐ๋ž˜๋‚ด์—ญ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_NOT_FOUND);} -} diff --git a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java b/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java deleted file mode 100644 index 6441cd4ef..000000000 --- a/src/main/java/com/gg/server/domain/receipt/exception/ReceiptNotOwnerException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.gg.server.domain.receipt.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ForbiddenException; - -public class ReceiptNotOwnerException extends ForbiddenException { - public ReceiptNotOwnerException() {super("์•„์ดํ…œ์˜ ์†Œ์œ ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.", ErrorCode.RECEIPT_NOT_OWNER);} -} diff --git a/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java b/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java deleted file mode 100644 index de03b6551..000000000 --- a/src/main/java/com/gg/server/domain/receipt/type/ItemStatus.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.receipt.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum ItemStatus { - BEFORE("์‚ฌ์šฉ ์ „"), - WAITING("์‚ฌ์šฉ ๋Œ€๊ธฐ"), - USING("์‚ฌ์šฉ ์ค‘"), - USED("์‚ฌ์šฉ ์™„๋ฃŒ"), - DELETED("์‚ญ์ œ"); - - private final String description; -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/season/SeasonController.java b/src/main/java/com/gg/server/domain/season/SeasonController.java deleted file mode 100644 index f300817fe..000000000 --- a/src/main/java/com/gg/server/domain/season/SeasonController.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.season; - -import com.gg.server.domain.season.dto.SeasonListResDto; -import com.gg.server.domain.season.service.SeasonService; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RequiredArgsConstructor -@RestController -@RequestMapping("/pingpong/") -public class SeasonController { - - private final SeasonService seasonService; - @GetMapping("seasons") - public SeasonListResDto seasonList() { - return new SeasonListResDto(seasonService.seasonList()); - } -} diff --git a/src/main/java/com/gg/server/domain/season/data/Season.java b/src/main/java/com/gg/server/domain/season/data/Season.java deleted file mode 100644 index 96b2c4c7d..000000000 --- a/src/main/java/com/gg/server/domain/season/data/Season.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.gg.server.domain.season.data; - -import com.gg.server.admin.season.dto.SeasonCreateRequestDto; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Getter -public class Season { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Setter - @NotNull - @Column(name = "season_name", length = 20) - private String seasonName; - - @Setter - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @Setter - @NotNull - @Column(name = "end_time") - private LocalDateTime endTime; - - @Setter - @NotNull - @Column(name = "start_ppp") - private Integer startPpp; - - @Setter - @NotNull - @Column(name = "ppp_gap") - private Integer pppGap; - - @Builder - public Season(String seasonName, LocalDateTime startTime, LocalDateTime endTime, Integer startPpp, Integer pppGap) { - this.seasonName = seasonName; - this.startTime = startTime; - this.endTime = endTime; - this.startPpp = startPpp; - this.pppGap = pppGap; - } - - @Builder - public Season(SeasonCreateRequestDto createDto) { - this.seasonName = createDto.getSeasonName(); - this.startTime = createDto.getStartTime(); - this.startPpp = createDto.getStartPpp(); - this.pppGap = createDto.getPppGap(); - } -} diff --git a/src/main/java/com/gg/server/domain/season/data/SeasonRepository.java b/src/main/java/com/gg/server/domain/season/data/SeasonRepository.java deleted file mode 100644 index 12b643b7f..000000000 --- a/src/main/java/com/gg/server/domain/season/data/SeasonRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.domain.season.data; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -public interface SeasonRepository extends JpaRepository { - @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now") - Optional findCurrentSeason(@Param("now") LocalDateTime now); - - - @Query("select s from Season s where s.startTime <= :now") - List findActiveSeasons(@Param("now") LocalDateTime now); - - @Query("select s from Season s where s.startTime <= :now order by s.startTime desc") - List findActiveSeasonsDesc(@Param("now") LocalDateTime now); - - @Query("select s from Season s where s.startTime <= :now and s.endTime >= :now or s.startTime > :now") - List findCurrentAndNewSeason(@Param("now") LocalDateTime now); -} diff --git a/src/main/java/com/gg/server/domain/season/dto/CurSeason.java b/src/main/java/com/gg/server/domain/season/dto/CurSeason.java deleted file mode 100644 index 6648a57ac..000000000 --- a/src/main/java/com/gg/server/domain/season/dto/CurSeason.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.domain.season.dto; - -import com.gg.server.domain.season.data.Season; -import lombok.Getter; - -import java.time.LocalDateTime; - -@Getter -public class CurSeason { - private Long id; - private String seasonName; - private LocalDateTime startTime; - private LocalDateTime endTime; - private Integer startPpp; - private Integer pppGap; - - public CurSeason(Season season) { - this.id = season.getId(); - this.seasonName = season.getSeasonName(); - this.startTime = season.getStartTime(); - this.endTime = season.getEndTime(); - this.startPpp = season.getStartPpp(); - this.pppGap = season.getPppGap(); - } -} diff --git a/src/main/java/com/gg/server/domain/season/dto/SeasonListResDto.java b/src/main/java/com/gg/server/domain/season/dto/SeasonListResDto.java deleted file mode 100644 index 07938c015..000000000 --- a/src/main/java/com/gg/server/domain/season/dto/SeasonListResDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.season.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class SeasonListResDto { - List seasonList; - - public SeasonListResDto(List seasonList) { - this.seasonList = seasonList; - } -} diff --git a/src/main/java/com/gg/server/domain/season/dto/SeasonResDto.java b/src/main/java/com/gg/server/domain/season/dto/SeasonResDto.java deleted file mode 100644 index 82e87a497..000000000 --- a/src/main/java/com/gg/server/domain/season/dto/SeasonResDto.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.season.dto; - -import com.gg.server.domain.season.data.Season; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class SeasonResDto { - private Long id; - private String name; - - public SeasonResDto(Season season) { - this.id = season.getId(); - this.name = season.getSeasonName(); - } - - @Override - public String toString() { - return "SeasonResDto{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/season/exception/SeasonForbiddenException.java b/src/main/java/com/gg/server/domain/season/exception/SeasonForbiddenException.java deleted file mode 100644 index 939003572..000000000 --- a/src/main/java/com/gg/server/domain/season/exception/SeasonForbiddenException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.season.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ForbiddenException; - -public class SeasonForbiddenException extends ForbiddenException { - public SeasonForbiddenException() { - super(ErrorCode.SEASON_FORBIDDEN.getMessage(), ErrorCode.SEASON_FORBIDDEN); - } -} diff --git a/src/main/java/com/gg/server/domain/season/exception/SeasonNotFoundException.java b/src/main/java/com/gg/server/domain/season/exception/SeasonNotFoundException.java deleted file mode 100644 index 53e0ddc00..000000000 --- a/src/main/java/com/gg/server/domain/season/exception/SeasonNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.season.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class SeasonNotFoundException extends NotExistException { - public SeasonNotFoundException() { - super("์‹œ์ฆŒ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.SEASON_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/season/exception/SeasonTimeBeforeException.java b/src/main/java/com/gg/server/domain/season/exception/SeasonTimeBeforeException.java deleted file mode 100644 index c367e6d31..000000000 --- a/src/main/java/com/gg/server/domain/season/exception/SeasonTimeBeforeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.season.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ForbiddenException; - -public class SeasonTimeBeforeException extends ForbiddenException { - public SeasonTimeBeforeException() { - super(ErrorCode.SEASON_TIME_BEFORE.getMessage(), ErrorCode.SEASON_TIME_BEFORE); - } -} diff --git a/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java b/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java deleted file mode 100644 index d20216078..000000000 --- a/src/main/java/com/gg/server/domain/season/service/SeasonFindService.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gg.server.domain.season.service; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor - -public class SeasonFindService { - private final SeasonRepository seasonRepository; - private final GameRepository gameRepository; - - @Transactional(readOnly = true) - public Season findCurrentSeason(LocalDateTime now){ - return seasonRepository.findCurrentSeason(now).orElseThrow(() -> new SeasonNotFoundException()); - } - - @Transactional(readOnly = true) - public Season findSeasonById(Long seasonId){ - return seasonRepository.findById(seasonId).orElseThrow(() -> new SeasonNotFoundException()); - } - - @Transactional(readOnly = true) - public Season findSeasonByGameId(Long gameId){ - Game game = gameRepository.findById(gameId).orElseThrow(() -> new GameNotExistException()); - return game.getSeason(); - } -} diff --git a/src/main/java/com/gg/server/domain/season/service/SeasonService.java b/src/main/java/com/gg/server/domain/season/service/SeasonService.java deleted file mode 100644 index 9c0d9571a..000000000 --- a/src/main/java/com/gg/server/domain/season/service/SeasonService.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.domain.season.service; - -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.season.dto.SeasonResDto; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class SeasonService { - private final SeasonRepository seasonRepository; - - public List seasonList() { - return seasonRepository.findActiveSeasonsDesc(LocalDateTime.now()) - .stream().map(SeasonResDto::new).collect(Collectors.toList()); - } - -// public CurSeason getCurSeason() { -// return new CurSeason(seasonRepository.findByStartTimeGreaterThanEqualAndEndTimeLessThanEqual(LocalDateTime.now()) -// .orElseThrow(() -> new NotExistException("ํ˜„์žฌ ์‹œ์ฆŒ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.NOT_FOUND))); -// } -} diff --git a/src/main/java/com/gg/server/domain/slotmanagement/SlotManagement.java b/src/main/java/com/gg/server/domain/slotmanagement/SlotManagement.java deleted file mode 100644 index 5f7ab0106..000000000 --- a/src/main/java/com/gg/server/domain/slotmanagement/SlotManagement.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.gg.server.domain.slotmanagement; - -import com.gg.server.admin.slotmanagement.dto.SlotCreateRequestDto; -import com.gg.server.domain.slotmanagement.exception.SlotManagementForbiddenException; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Getter -@Entity -@NoArgsConstructor -@AllArgsConstructor -public class SlotManagement extends BaseTimeEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @Column(name = "past_slot_time") - private Integer pastSlotTime; - - @NotNull - @Column(name = "future_slot_time") - private Integer futureSlotTime; - - @NotNull - @Column(name = "open_minute") - private Integer openMinute; - - @NotNull - @Column(name = "game_interval") - private Integer gameInterval; - - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @Column(name = "end_time") - private LocalDateTime endTime; - - @Builder - public SlotManagement(Integer pastSlotTime, Integer futureSlotTime, Integer openMinute, Integer gameInterval, - LocalDateTime startTime, LocalDateTime endTime) { - this.pastSlotTime = pastSlotTime; - this.futureSlotTime = futureSlotTime; - this.openMinute = openMinute; - this.gameInterval = gameInterval; - this.startTime = startTime; - this.endTime = endTime; - } - - @Builder - public SlotManagement(SlotCreateRequestDto requestDto) { - this.pastSlotTime = requestDto.getPastSlotTime(); - this.futureSlotTime = requestDto.getFutureSlotTime(); - this.openMinute = requestDto.getOpenMinute(); - this.gameInterval = requestDto.getInterval(); - this.startTime = requestDto.getStartTime(); - this.endTime = null; - } - - public void updateEndTime(LocalDateTime endTime) { - if (this.endTime != null) - throw new SlotManagementForbiddenException(); - this.endTime = endTime; - } - - public void setNullEndTime() { - if (this.endTime == null) - throw new SlotManagementForbiddenException(); - this.endTime = null; - } -} diff --git a/src/main/java/com/gg/server/domain/slotmanagement/data/SlotManagementRepository.java b/src/main/java/com/gg/server/domain/slotmanagement/data/SlotManagementRepository.java deleted file mode 100644 index 158537c35..000000000 --- a/src/main/java/com/gg/server/domain/slotmanagement/data/SlotManagementRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gg.server.domain.slotmanagement.data; - -import com.gg.server.domain.slotmanagement.SlotManagement; -import java.time.LocalDateTime; -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 SlotManagementRepository - extends JpaRepository { - @Query("select sm from SlotManagement sm where sm.endTime > :now or sm.endTime is null") - List findAfter(@Param("now") LocalDateTime now); - - @Query("select sm from SlotManagement sm where (sm.endTime is null" - + " or sm.endTime > :now) and sm.startTime <=:now") - Optional findCurrent(@Param("now") LocalDateTime now); - - SlotManagement findFirstByOrderByCreatedAtDesc(); - - -} diff --git a/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementForbiddenException.java b/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementForbiddenException.java deleted file mode 100644 index accb87ccb..000000000 --- a/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementForbiddenException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.slotmanagement.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ForbiddenException; - -public class SlotManagementForbiddenException extends ForbiddenException { - public SlotManagementForbiddenException() { - super(ErrorCode.SLOTMANAGEMENT_FORBIDDEN.getMessage(), ErrorCode.SLOTMANAGEMENT_FORBIDDEN); - } -} diff --git a/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementNotFoundException.java b/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementNotFoundException.java deleted file mode 100644 index 7e1060154..000000000 --- a/src/main/java/com/gg/server/domain/slotmanagement/exception/SlotManagementNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.slotmanagement.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class SlotManagementNotFoundException extends NotExistException { - public SlotManagementNotFoundException() { - super(ErrorCode.SLOTMANAGEMENT_NOT_FOUND.getMessage(), ErrorCode.SLOTMANAGEMENT_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/team/data/Team.java b/src/main/java/com/gg/server/domain/team/data/Team.java deleted file mode 100644 index a3f4e0b5d..000000000 --- a/src/main/java/com/gg/server/domain/team/data/Team.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.gg.server.domain.team.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.utils.BusinessChecker; -import java.util.ArrayList; -import java.util.List; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.validation.constraints.NotNull; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Getter -public class Team { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "game_id") - private Game game; - - @Column(name = "score") - private Integer score; - - @Column(name = "win") - private Boolean win; - - @OneToMany(mappedBy = "team", cascade = CascadeType.ALL) - private List teamUsers = new ArrayList<>(); - - public Team(Game game, Integer score, Boolean win) { - this.game = game; - this.score = score; - this.win = win; - game.addTeam(this); - } - - public void updateScore(int score, Boolean win) { - this.score = score; - this.win = win; - } - - public void addTeamUser(TeamUser teamUser) { - BusinessChecker.mustNotNull(teamUser, ErrorCode.NULL_POINT); - BusinessChecker.mustNotExceed(1, teamUsers, ErrorCode.TEAM_USER_EXCEED); - BusinessChecker.mustNotContains(teamUser, teamUsers, ErrorCode.TEAM_USER_ALREADY_EXIST); - this.teamUsers.add(teamUser); - } -} diff --git a/src/main/java/com/gg/server/domain/team/data/TeamRepository.java b/src/main/java/com/gg/server/domain/team/data/TeamRepository.java deleted file mode 100644 index bdba99df3..000000000 --- a/src/main/java/com/gg/server/domain/team/data/TeamRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.team.data; - -import java.time.LocalDateTime; -import java.util.List; - -import com.gg.server.domain.team.dto.GameUser; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface TeamRepository extends JpaRepository { - @Query("select t from Team t where t.game.id=:gameId") - List findAllBy(@Param("gameId") Long gameId); -} diff --git a/src/main/java/com/gg/server/domain/team/data/TeamUser.java b/src/main/java/com/gg/server/domain/team/data/TeamUser.java deleted file mode 100644 index 81fe3ab42..000000000 --- a/src/main/java/com/gg/server/domain/team/data/TeamUser.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.gg.server.domain.team.data; - -import com.gg.server.domain.user.data.User; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.utils.BusinessChecker; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Entity -@Getter -@ToString -public class TeamUser { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "team_id") - private Team team; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - public TeamUser(Team team, User user) { - this.team = team; - this.user = user; - team.addTeamUser(this); - } - - public void updateUser(User user) { - BusinessChecker.mustNotNull(user, ErrorCode.NULL_POINT); - this.user = user; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java b/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java deleted file mode 100644 index 50edb7052..000000000 --- a/src/main/java/com/gg/server/domain/team/data/TeamUserRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.team.data; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.time.LocalDateTime; -import java.util.List; - -public interface TeamUserRepository extends JpaRepository { - @Query(value = "select team_user.id, team_user.team_id, team_user.user_id from team, team_user " + - "where team.game_id =:gid and team.id = team_user.team_id", nativeQuery = true) - List findAllByGameId(@Param("gid")Long gid); - - @Query(value = "select count(*) from game, team, team_user " + - "where game.start_time >= :today and team_user.team_id = team.id and team_user.user_id = :userId " + - "and team.game_id = game.id and game.status = 'END'", nativeQuery = true) - Integer findByDateAndUser(@Param("today")LocalDateTime today, @Param("userId") Long userId); - -} diff --git a/src/main/java/com/gg/server/domain/team/dto/GameUser.java b/src/main/java/com/gg/server/domain/team/dto/GameUser.java deleted file mode 100644 index d92e8cef8..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/GameUser.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.team.dto; - -import com.gg.server.domain.user.type.SnsType; - -public interface GameUser { - Long getGameId(); - Long getUserId(); - String getIntraId(); - String getEmail(); - SnsType getSnsNotiOpt(); -} diff --git a/src/main/java/com/gg/server/domain/team/dto/MatchTeamsInfoDto.java b/src/main/java/com/gg/server/domain/team/dto/MatchTeamsInfoDto.java deleted file mode 100644 index 7d20996be..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/MatchTeamsInfoDto.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.domain.team.dto; - -import com.gg.server.domain.game.dto.GameTeamUserInfo; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -import java.util.List; - -@Getter -@NoArgsConstructor -@ToString -public class MatchTeamsInfoDto { - private TeamInfo myTeam; - private TeamInfo enemyTeam; - - public MatchTeamsInfoDto(List infos, Long teamId) { - if (teamId == null) return; - myTeam = new TeamInfo(); - enemyTeam = new TeamInfo(); - for (GameTeamUserInfo info : - infos) { - if (teamId.equals(info.getTeamId())) { - myTeam.setTeam(info.getTeamId(), info.getScore()); - myTeam.addPlayer(info); - } else { - enemyTeam.setTeam(info.getTeamId(), info.getScore()); - enemyTeam.addPlayer(info); - } - } - } - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof MatchTeamsInfoDto)) { - return false; - } else { - MatchTeamsInfoDto other = (MatchTeamsInfoDto) obj; - return this.myTeam.equals(other.getMyTeam()) - && this.enemyTeam.equals(other.getEnemyTeam()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/team/dto/TeamInfo.java b/src/main/java/com/gg/server/domain/team/dto/TeamInfo.java deleted file mode 100644 index 36e4e6eb9..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/TeamInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gg.server.domain.team.dto; - -import com.gg.server.domain.game.dto.GameTeamUserInfo; -import lombok.Getter; -import lombok.ToString; - -import java.util.ArrayList; -import java.util.List; - -@Getter -@ToString -public class TeamInfo { - private Integer teamScore; - private Long teamId; - private List players; - - public TeamInfo() { - this.players = new ArrayList<>(); - } - - public void setTeam(Long teamId, Integer teamScore) { - this.teamId = teamId; - this.teamScore = teamScore; - } - - public void addPlayer(GameTeamUserInfo info) { - this.players.add(new TeamUserInfoDto(info.getIntraId(), info.getImage(), info.getExp(), null, null)); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof TeamInfo)) { - return false; - } else { - TeamInfo other = (TeamInfo) obj; - return this.teamScore.equals(other.getTeamScore()) - && this.teamId.equals(other.getTeamId()) - && this.players.equals(other.getPlayers()); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/team/dto/TeamReqDto.java b/src/main/java/com/gg/server/domain/team/dto/TeamReqDto.java deleted file mode 100644 index b8a6b610a..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/TeamReqDto.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.domain.team.dto; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TeamReqDto { - - @NotNull - private Long teamId; - - @NotNull - @Max(value = 2, message = "์ ์ˆ˜๋Š” ์ตœ๋Œ€ 2์  ์ž…๋‹ˆ๋‹ค.") - @Min(value = 0, message = "์ ์ˆ˜๋Š” ์ตœ์†Œ 0์  ์ž…๋‹ˆ๋‹ค.") - private int score; - - public TeamReqDto(Long teamId, int score) { - this.teamId = teamId; - this.score = score; - } - - @Override - public String toString() { - return "TeamReqDto{" + - "teamId=" + teamId + - ", score=" + score + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/team/dto/TeamUserInfoDto.java b/src/main/java/com/gg/server/domain/team/dto/TeamUserInfoDto.java deleted file mode 100644 index 5df76377f..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/TeamUserInfoDto.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gg.server.domain.team.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class TeamUserInfoDto { - private String intraId; - private String userImageUri; - private Integer level; - @JsonInclude(JsonInclude.Include.NON_NULL) - private Integer wins; - @JsonInclude(JsonInclude.Include.NON_NULL) - private Integer losses; - - public TeamUserInfoDto(String intraId, String userImageUri, Integer exp, Integer wins, Integer losses) { - this.intraId = intraId; - this.userImageUri = userImageUri; - this.level = ExpLevelCalculator.getLevel(exp); - this.wins = wins; - this.losses = losses; - } - - @Override - public String toString() { - return "TeamUserInfoDto{" + - "intraId='" + intraId + '\'' + - ", userImageUri='" + userImageUri + '\'' + - ", level=" + level + - '}'; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof TeamUserInfoDto)) { - return false; - } else { - TeamUserInfoDto other = (TeamUserInfoDto) obj; - return this.intraId.equals(other.getIntraId()) - && this.level.equals(other.getLevel()) - && this.userImageUri.equals(other.getUserImageUri()) - && (this.wins == other.getWins() || this.wins.equals(other.getWins())) - && (this.losses == other.getLosses() || this.losses.equals(other.getLosses())); - } - } -} diff --git a/src/main/java/com/gg/server/domain/team/dto/TeamUserListDto.java b/src/main/java/com/gg/server/domain/team/dto/TeamUserListDto.java deleted file mode 100644 index 5eeb81aae..000000000 --- a/src/main/java/com/gg/server/domain/team/dto/TeamUserListDto.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gg.server.domain.team.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.gg.server.domain.game.dto.GameListResDto; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -public class TeamUserListDto { - Long teamId; - - List players; - - @JsonInclude(JsonInclude.Include.NON_NULL) - Boolean isWin; - @JsonInclude(JsonInclude.Include.NON_NULL) - Integer score; - - public TeamUserListDto(List players, Boolean isWin, Integer score) { - this.isWin = isWin; - this.score = score; - this.players = players; - } - - public TeamUserListDto(Long teamId, List players, Boolean isWin, Integer score) { - this.teamId = teamId; - this.players = players; - this.isWin = isWin; - this.score = score == -1? null : score; - } - - @Override - public String toString() { - return "TeamUserListDto{" + - "players=" + players + - '}'; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof TeamUserListDto)) { - return false; - } else { - TeamUserListDto other = (TeamUserListDto) obj; - return (isWin == other.getIsWin() || this.isWin.equals(other.getIsWin())) - && (score == other.getScore() || this.score.equals(other.getScore())) - && this.players.equals(other.getPlayers()); - } - } -} diff --git a/src/main/java/com/gg/server/domain/team/exception/TeamIdNotMatchException.java b/src/main/java/com/gg/server/domain/team/exception/TeamIdNotMatchException.java deleted file mode 100644 index 5737d7538..000000000 --- a/src/main/java/com/gg/server/domain/team/exception/TeamIdNotMatchException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.team.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class TeamIdNotMatchException extends NotExistException { - public TeamIdNotMatchException() { - super(ErrorCode.TEAM_ID_NOT_MATCH.getMessage(), ErrorCode.TEAM_ID_NOT_MATCH); - } -} diff --git a/src/main/java/com/gg/server/domain/team/exception/TeamNotFoundException.java b/src/main/java/com/gg/server/domain/team/exception/TeamNotFoundException.java deleted file mode 100644 index 48e05d1d4..000000000 --- a/src/main/java/com/gg/server/domain/team/exception/TeamNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.team.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class TeamNotFoundException extends NotExistException { - - public TeamNotFoundException() { - super(ErrorCode.TEAM_NOT_FOUND.getMessage(), ErrorCode.TEAM_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/tier/data/Tier.java b/src/main/java/com/gg/server/domain/tier/data/Tier.java deleted file mode 100644 index f367e7071..000000000 --- a/src/main/java/com/gg/server/domain/tier/data/Tier.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.domain.tier.data; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import java.io.Serializable; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class Tier implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "image_uri") - private String imageUri; - - @Column(name = "name") - private String name; - - public Tier(String imageUri) { - this.imageUri = imageUri; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/tier/data/TierRepository.java b/src/main/java/com/gg/server/domain/tier/data/TierRepository.java deleted file mode 100644 index 1dd5b0561..000000000 --- a/src/main/java/com/gg/server/domain/tier/data/TierRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.tier.data; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - -import java.util.Optional; - -public interface TierRepository extends JpaRepository { - - @Query("SELECT t FROM Tier t WHERE t.id = (SELECT MIN(t.id) FROM Tier t)") - Optional findStartTier(); - - Optional findByName(String name); -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java b/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java deleted file mode 100644 index fe13c392b..000000000 --- a/src/main/java/com/gg/server/domain/tier/exception/TierNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.tier.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class TierNotFoundException extends NotExistException { - public TierNotFoundException() { - super("ํ•ด๋‹น ํ‹ฐ์–ด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.", ErrorCode.TIER_NOT_FOUND); - } - -} diff --git a/src/main/java/com/gg/server/domain/tier/service/TierService.java b/src/main/java/com/gg/server/domain/tier/service/TierService.java deleted file mode 100644 index 8821003d7..000000000 --- a/src/main/java/com/gg/server/domain/tier/service/TierService.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.gg.server.domain.tier.service; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class TierService { - private final TierRepository tierRepository; - private final RankRepository rankRepository; - - @Transactional - public void updateAllTier(Season season) { - List rankList = rankRepository.findAllBySeasonIdOrderByPppDesc(season.getId()); - Long totalRankPlayers = rankRepository.countRealRankPlayers(season.getId()); - List tierList = tierRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); - - int top30percentPpp = rankList.get((int) (totalRankPlayers * 0.3)).getPpp(); - int top10percentPpp = rankList.get((int) (totalRankPlayers * 0.1)).getPpp(); - - for (int i = 0; i < rankList.size(); i++) { - Rank rank = rankList.get(i); - if (rank.getWins() == 0 && rank.getLosses() == 0) { - rank.updateTier(tierList.get(0)); - } else { - if (i < 3) { - rank.updateTier(tierList.get(6)); - continue; - } - if (rank.getPpp() < 970) { - // 970 ๋ฏธ๋งŒ - rank.updateTier(tierList.get(1)); - } else if (rank.getPpp() < 1010) { - // 970 - 1009 - rank.updateTier(tierList.get(2)); - } else if (rank.getPpp() < 1050) { - // 1010 - 1049 - rank.updateTier(tierList.get(3)); - } else if (rank.getPpp() >= 1050) { - if (rank.getPpp() >= top30percentPpp && rank.getPpp() < top10percentPpp) { - // 1050 ์ด์ƒ, 30% ์ด์ƒ, 10% ๋ฏธ๋งŒ - rank.updateTier(tierList.get(4)); - } else if (rank.getPpp() >= top10percentPpp) { - // 1050 ์ด์ƒ, 10% ์ด์ƒ - rank.updateTier(tierList.get(5)); - } else { - // 1050 ์ด์ƒ, 30% ๋ฏธ๋งŒ - rank.updateTier(tierList.get(3)); - } - } - } - } - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/controller/TournamentController.java b/src/main/java/com/gg/server/domain/tournament/controller/TournamentController.java deleted file mode 100644 index 42859da36..000000000 --- a/src/main/java/com/gg/server/domain/tournament/controller/TournamentController.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.gg.server.domain.tournament.controller; - -import com.gg.server.domain.tournament.dto.*; -import com.gg.server.domain.tournament.service.TournamentService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; -import javax.validation.constraints.Positive; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.data.domain.Sort; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/tournaments") -public class TournamentController { - - private final TournamentService tournamentService; - - /** - * ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ - * @param tournamentFilterRequestDto Enum ํ•„ํ„ฐ ์ •๋ณด (page, size, type, status) - * @return ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ - */ - @GetMapping - public ResponseEntity getAllTournamentList(@ModelAttribute @Valid TournamentFilterRequestDto tournamentFilterRequestDto){ - Pageable pageRequest = PageRequest.of(tournamentFilterRequestDto.getPage() - 1, tournamentFilterRequestDto.getSize(), Sort.by("startTime").ascending()); - return ResponseEntity.status(HttpStatus.OK). - body(tournamentService.getAllTournamentList(pageRequest, tournamentFilterRequestDto.getType(), tournamentFilterRequestDto.getStatus())); - } - - /** - *

์œ ์ € ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ์—ฌ ์—ฌ๋ถ€ ํ™•์ธ ๋งค์„œ๋“œ

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ - * @param user ํ™•์ธํ•˜๊ณ ์ž ํ•˜๋Š” ์œ ์ €(๋กœ๊ทธ์ธํ•œ ์œ ์ € ๋ณธ์ธ) - * @return - */ - @GetMapping("/{tournamentId}/users") - ResponseEntity getUserStatusInTournament(@PathVariable Long tournamentId, @Parameter(hidden = true) @Login UserDto user) { - - return ResponseEntity.status(HttpStatus.OK).body(tournamentService.getUserStatusInTournament(tournamentId, user)); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๋‹จ์ผ ์กฐํšŒ - * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id - * @return ํ† ๋„ˆ๋จผํŠธ - */ - @GetMapping("/{tournamentId}") - public ResponseEntity getTournnament(@PathVariable @Positive Long tournamentId) { - TournamentResponseDto tournamentResponseDto = tournamentService.getTournament(tournamentId); - return ResponseEntity.status(HttpStatus.OK).body(tournamentResponseDto); - } - - @DeleteMapping("/{tournamentId}/users") - ResponseEntity cancelTournamentUserRegistration(@PathVariable Long tournamentId, @Parameter(hidden = true) @Login UserDto user) { - - return ResponseEntity.status(HttpStatus.OK).body(tournamentService.cancelTournamentUserRegistration(tournamentId, user)); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ - * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id - * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ - */ - @GetMapping("/{tournamentId}/games") - public ResponseEntity getTournamentGames(@PathVariable @Positive Long tournamentId){ - return ResponseEntity.status(HttpStatus.OK).body(tournamentService.getTournamentGames(tournamentId)); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ

- *

ํ† ๋„ˆ๋จผํŠธ ์ตœ๋Œ€ ์ธ์›๋ณด๋‹ค ์ด๋ฏธ ๋งŽ์ด ์‹ ์ฒญํ–ˆ๋‹ค๋ฉด ๋Œ€๊ธฐ์ž๋กœ ๋“ค์–ด๊ฐ„๋‹ค

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ id - * @param user ์‹ ์ฒญ ์œ ์ €(๋ณธ์ธ) - * @return - */ - @PostMapping("/{tournamentId}/users") - ResponseEntity registerTournamentUser(@PathVariable Long tournamentId, @Parameter(hidden = true) @Login UserDto user) { - - return ResponseEntity.status(HttpStatus.CREATED) - .body(tournamentService.registerTournamentUser(tournamentId, user)); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/Tournament.java b/src/main/java/com/gg/server/domain/tournament/data/Tournament.java deleted file mode 100644 index a81736da4..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/Tournament.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import static com.gg.server.global.exception.ErrorCode.*; -import static com.gg.server.global.exception.ErrorCode.TOURNAMENT_GAME_EXCEED; -import static com.gg.server.global.utils.BusinessChecker.mustContains; -import static com.gg.server.global.utils.BusinessChecker.mustNotContains; -import static com.gg.server.global.utils.BusinessChecker.mustNotExceed; -import static com.gg.server.global.utils.BusinessChecker.mustNotNull; - -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.BaseTimeEntity; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; -import javax.persistence.*; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Entity -public class Tournament extends BaseTimeEntity { - // ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž ์ˆ˜ => ํ˜„์žฌ๋Š” 8๊ฐ• ๊ณ ์ • - public static final int ALLOWED_JOINED_NUMBER = 8; - // ํ† ๋„ˆ๋จผํŠธ ์ตœ์†Œ ์‹œ์ž‘ ๋‚ ์งœ (n์ผ ํ›„) - public static final int ALLOWED_MINIMAL_START_DAYS = 2; - // ํ† ๋„ˆ๋จผํŠธ ์ตœ์†Œ ์ง„ํ–‰ ์‹œ๊ฐ„ (n์‹œ๊ฐ„) - public static final int MINIMUM_TOURNAMENT_DURATION = 2; - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @Column(name = "title", length = 30) - private String title; - - @NotNull - @Column(name = "contents", length = 3000) - private String contents; - - @NotNull - @Column(name = "start_time") - private LocalDateTime startTime; - - @NotNull - @Column(name = "end_time") - private LocalDateTime endTime; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "type") - private TournamentType type; - - @NotNull - @Column(name = "status") - @Enumerated(EnumType.STRING) - private TournamentStatus status; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "winner_id") - private User winner; - - @OneToMany(mappedBy = "tournament", cascade = CascadeType.ALL) - private List tournamentGames = new ArrayList<>(); - - @OneToMany(mappedBy = "tournament", cascade = CascadeType.ALL) - private List tournamentUsers = new ArrayList<>(); - - /** - * winner๋Š” ์ƒ์„ฑ์‹œ์ ์— ์กด์žฌํ•˜์ง€ ์•Š์Œ. - */ - @Builder - public Tournament(String title, String contents, LocalDateTime startTime, LocalDateTime endTime, - TournamentType type, TournamentStatus status) { - this.title = title; - this.contents = contents; - this.startTime = startTime; - this.endTime = endTime; - this.type = type; - this.status = status; - this.winner = null; - } - - public void update(String title, String contents, LocalDateTime startTime, - LocalDateTime endTime, TournamentType type, TournamentStatus status) { - this.title = title; - this.contents = contents; - this.startTime = startTime; - this.endTime = endTime; - this.type = type; - this.status = status; - } - - /** - * TournamentGame ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. - */ - protected void addTournamentGame(TournamentGame tournamentGame) { - mustNotNull(tournamentGame, NULL_POINT); - mustNotExceed(ALLOWED_JOINED_NUMBER - 2, tournamentGames, TOURNAMENT_GAME_EXCEED); - mustNotContains(tournamentGame, tournamentGames, TOURNAMENT_GAME_DUPLICATION); - this.tournamentGames.add(tournamentGame); - } - - /** - * TournamentUser ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. - */ - protected void addTournamentUser(@NotNull TournamentUser tournamentUser) { - mustNotNull(tournamentUser, NULL_POINT); - mustNotContains(tournamentUser, tournamentUsers, TOURNAMENT_USER_DUPLICATION); - this.tournamentUsers.add(tournamentUser); - } - - /** - * TournamentGame ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ๊ธฐํƒ€ ํ˜ธ์ถœ ๊ธˆ์ง€. - */ - protected void deleteTournamentUser(TournamentUser tournamentUser) { - mustNotNull(tournamentUser, NULL_POINT); - mustContains(tournamentUser, tournamentUsers, TOURNAMENT_USER_NOT_FOUND); - this.tournamentUsers.remove(tournamentUser); - } - - public void updateWinner(User winner) { - mustNotNull(winner, NULL_POINT); - this.winner = winner; - } - - public void updateStatus(TournamentStatus status) { - mustNotNull(status, NULL_POINT); - this.status = status; - } - - public void updateEndTime(LocalDateTime endTime) { - mustNotNull(endTime, NULL_POINT); - this.endTime = endTime; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/TournamentGame.java b/src/main/java/com/gg/server/domain/tournament/data/TournamentGame.java deleted file mode 100644 index d4e25d948..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/TournamentGame.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.global.utils.BaseTimeEntity; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; - -import lombok.*; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Entity -public class TournamentGame extends BaseTimeEntity { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "game_id") - private Game game; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "tournament_id") - private Tournament tournament; - - @NotNull - @Column(name = "round", length = 30) - @Enumerated(EnumType.STRING) - private TournamentRound tournamentRound; - - - /** - * id ๊ฐ’ ์ œ์™ธํ•œ ์ƒ์„ฑ์ž. - *

- * ์ƒ์„ฑ์— ๋”ฐ๋ฅธ Tournament ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •์„ ๋‹ด๋‹น - *

- * @param game - * @param tournament - * @param tournamentRound - */ - @Builder - public TournamentGame(Game game, Tournament tournament, TournamentRound tournamentRound) { - tournament.addTournamentGame(this); - this.game = game; - this.tournament = tournament; - this.tournamentRound = tournamentRound; - } - - /** - * TournamentGame์˜ ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. - * @param game - */ - public void updateGame(Game game) { - this.game = game; - } - -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/TournamentGameRepository.java b/src/main/java/com/gg/server/domain/tournament/data/TournamentGameRepository.java deleted file mode 100644 index c072ca4a4..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/TournamentGameRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.tournament.type.TournamentRound; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; -import java.util.Optional; - -public interface TournamentGameRepository extends JpaRepository { - List findAllByTournamentId(Long tournamentId); - - Optional findByTournamentIdAndTournamentRound(Long id, TournamentRound tournamentRound); - - Optional findByGameId(Long gameId); -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/TournamentRepository.java b/src/main/java/com/gg/server/domain/tournament/data/TournamentRepository.java deleted file mode 100644 index 0b54b4555..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/TournamentRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.tournament.type.TournamentStatus; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import com.gg.server.domain.tournament.type.TournamentType; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -import javax.validation.constraints.NotNull; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface TournamentRepository extends JpaRepository { - List findAllByStatusIsNot(TournamentStatus status); - Optional findByTitle(String title); - - Page findAllByTypeAndStatus(@NotNull TournamentType type, @NotNull TournamentStatus status, Pageable pageable); - - Page findAllByStatus(@NotNull TournamentStatus status, Pageable pageable); - List findAllByStatus(@NotNull TournamentStatus status); - - Page findAllByType(@NotNull TournamentType type, Pageable pageable); - - @Query(value = "select t from Tournament t where (t.startTime between :startTime and :endTime) " - + "or (t.endTime between :startTime and :endTime) " - + "or (:startTime between t.startTime and t.endTime) " - + "or (:endTime between t.startTime and t.endTime)") - List findAllBetween(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); - -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/TournamentUser.java b/src/main/java/com/gg/server/domain/tournament/data/TournamentUser.java deleted file mode 100644 index dc0cb614a..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/TournamentUser.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.user.data.User; -import com.gg.server.global.utils.BaseTimeEntity; -import java.time.LocalDateTime; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Entity -public class TournamentUser extends BaseTimeEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "tournament_id") - private Tournament tournament; - - @NotNull - @Column(name = "is_joined") - private Boolean isJoined; - - @NotNull - @Column(name = "register_time") - private LocalDateTime registerTime; - - /** - * ์ƒ์„ฑ์ž์ด๋ฉฐ, ๋นŒ๋”์ด์ž, ์ƒ์„ฑ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋‹ด๋‹นํ•œ๋‹ค. - */ - @Builder - public TournamentUser(User user, Tournament tournament, boolean isJoined, LocalDateTime registerTime) { - tournament.addTournamentUser(this); - this.user = user; - this.tournament = tournament; - this.isJoined = isJoined; - this.registerTime = registerTime; - } - - /** - * ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ, ์‚ญ์ œ ์ฑ…์ž„์„ ๊ฐ€์ง„๋‹ค. - */ - public void deleteTournament() { - tournament.deleteTournamentUser(this); - this.tournament = null; - } - - public void updateIsJoined(boolean isJoined) { - this.isJoined = isJoined; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/data/TournamentUserRepository.java b/src/main/java/com/gg/server/domain/tournament/data/TournamentUserRepository.java deleted file mode 100644 index d7b421a9a..000000000 --- a/src/main/java/com/gg/server/domain/tournament/data/TournamentUserRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.user.data.User; -import java.util.List; -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface TournamentUserRepository extends JpaRepository { - - int countByTournamentAndIsJoined(Tournament tournament, boolean isJoined); - - List findAllByTournament(Tournament tournament); - - List findAllByTournamentAndIsJoined(Tournament tournament, boolean isJoined); - - List findAllByTournamentId(Long tournamentId); - - Optional findByTournamentIdAndUserId(Long tournamentId, Long userId); - - List findAllByUser(User user); -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentFilterRequestDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentFilterRequestDto.java deleted file mode 100644 index 370a0d5ff..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentFilterRequestDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.tournament.dto; - -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.global.dto.PageRequestDto; -import lombok.Getter; - -@Getter -public class TournamentFilterRequestDto extends PageRequestDto { - - private TournamentType type; - - private TournamentStatus status; - - public TournamentFilterRequestDto(Integer page, Integer size, TournamentType type, TournamentStatus status) { - super(page, size); - this.type = type; - this.status = status; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameListResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameListResponseDto.java deleted file mode 100644 index faa450578..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameListResponseDto.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.tournament.dto; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TournamentGameListResponseDto { - private Long tournamentId; - private List games; - - public TournamentGameListResponseDto(Long tournamentId, List games) { - this.tournamentId = tournamentId; - this.games = games; - } - - @Override - public String toString() { - return "TournamentGameListResponseDto{" + - "tournamentId=" + tournamentId + - ", games=" + games.toString() + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameResDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameResDto.java deleted file mode 100644 index 961dee647..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentGameResDto.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gg.server.domain.tournament.dto; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.dto.GameResultResDto; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.type.TournamentRound; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class TournamentGameResDto { - - private Long tournamentGameId; - private Long nextTournamentGameId; - private TournamentRound tournamentRound; - private GameResultResDto game; - - public TournamentGameResDto(TournamentGame tournamentGame, GameTeamUser game, TournamentRound tournamentRound, TournamentGame nextTournamentGame){ - this.tournamentGameId = tournamentGame.getId(); - this.game = game == null? null : new GameResultResDto(game); - this.tournamentRound = tournamentRound; - this.nextTournamentGameId = nextTournamentGame == null? null : nextTournamentGame.getId(); - } - - @Override - public String toString() { - return "TournamentGameResDto{" + - "tournamentGameId=" + tournamentGameId + - ", NextTournamentGameId=" + nextTournamentGameId + - ", tournamentRound='" + tournamentRound + '\'' + - ", gameId=" + game.getGameId() + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentListResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentListResponseDto.java deleted file mode 100644 index c6ce1ca25..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentListResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.tournament.dto; - - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -@Getter -public class TournamentListResponseDto { - - private List tournaments; - private int totalPage; -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentResponseDto.java deleted file mode 100644 index 791d1e1d8..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentResponseDto.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.domain.tournament.dto; - - -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.dto.UserImageDto; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@AllArgsConstructor -@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -@Getter -public class TournamentResponseDto { - - private Long tournamentId; - private String title; - private String contents; - private LocalDateTime startTime; - private LocalDateTime endTime; - private TournamentType type; - private TournamentStatus status; - private String winnerIntraId; - private String winnerImageUrl; - private int playerCnt; - - public TournamentResponseDto (Tournament tournament, UserImageDto winner, int playerCnt) { - this.tournamentId = tournament.getId(); - this.title = tournament.getTitle(); - this.contents = tournament.getContents(); - this.startTime = tournament.getStartTime(); - this.endTime = tournament.getEndTime(); - this.type = tournament.getType(); - this.status = tournament.getStatus(); - this.winnerIntraId = winner.getIntraId(); - this.winnerImageUrl = winner.getImageUri(); - this.playerCnt = playerCnt; - } - - public void update_player_cnt(int playerCnt) { - this.playerCnt = playerCnt; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserListResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserListResponseDto.java deleted file mode 100644 index b08fee116..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserListResponseDto.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.domain.tournament.dto; - -import com.gg.server.domain.tournament.data.TournamentUser; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; - -@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -@Getter -public class TournamentUserListResponseDto { - private List users; - - public TournamentUserListResponseDto(List tournamentUsers){ - users = new ArrayList<>(); - for (TournamentUser tournamentUser : tournamentUsers) { - users.add(new TournamentUserResponseDto(tournamentUser)); - } - users.sort(Comparator.comparing(TournamentUserResponseDto::getIsJoined).reversed(). - thenComparing(TournamentUserResponseDto::getRegisteredDate)); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserRegistrationResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserRegistrationResponseDto.java deleted file mode 100644 index 21fee5f4a..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserRegistrationResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.tournament.dto; - - -import com.gg.server.domain.tournament.type.TournamentUserStatus; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -@Getter -public class TournamentUserRegistrationResponseDto { - private TournamentUserStatus status; -} diff --git a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserResponseDto.java b/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserResponseDto.java deleted file mode 100644 index 198a26f74..000000000 --- a/src/main/java/com/gg/server/domain/tournament/dto/TournamentUserResponseDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.domain.tournament.dto; - -import com.gg.server.domain.tournament.data.TournamentUser; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@AllArgsConstructor -@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) -@Getter -public class TournamentUserResponseDto { - private Long userId; - private String intraId; - private Boolean isJoined; - private LocalDateTime registeredDate; - - public TournamentUserResponseDto(TournamentUser tournamentUser) { - this.userId = tournamentUser.getUser().getId(); - this.intraId = tournamentUser.getUser().getIntraId(); - this.isJoined = tournamentUser.getIsJoined(); - this.registeredDate = tournamentUser.getRegisterTime(); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/exception/TournamentConflictException.java b/src/main/java/com/gg/server/domain/tournament/exception/TournamentConflictException.java deleted file mode 100644 index a300c0a14..000000000 --- a/src/main/java/com/gg/server/domain/tournament/exception/TournamentConflictException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gg.server.domain.tournament.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class TournamentConflictException extends DuplicationException { - public TournamentConflictException() { - super(ErrorCode.TOURNAMENT_CONFLICT.getMessage(), ErrorCode.TOURNAMENT_CONFLICT); - } - public TournamentConflictException(ErrorCode errorCode) { - super(errorCode.getMessage(), errorCode); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/exception/TournamentGameNotFoundException.java b/src/main/java/com/gg/server/domain/tournament/exception/TournamentGameNotFoundException.java deleted file mode 100644 index 9ea98a589..000000000 --- a/src/main/java/com/gg/server/domain/tournament/exception/TournamentGameNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.tournament.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class TournamentGameNotFoundException extends NotExistException { - public TournamentGameNotFoundException() { - super(ErrorCode.TOURNAMENT_GAME_NOT_FOUND.getMessage(), ErrorCode.TOURNAMENT_GAME_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/exception/TournamentNotFoundException.java b/src/main/java/com/gg/server/domain/tournament/exception/TournamentNotFoundException.java deleted file mode 100644 index a63fcb1f6..000000000 --- a/src/main/java/com/gg/server/domain/tournament/exception/TournamentNotFoundException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gg.server.domain.tournament.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class TournamentNotFoundException extends NotExistException { - public TournamentNotFoundException() { - super(ErrorCode.TOURNAMENT_NOT_FOUND.getMessage(), ErrorCode.TOURNAMENT_NOT_FOUND); - } - public TournamentNotFoundException(ErrorCode errorCode) { - super(errorCode.getMessage(), errorCode); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/exception/TournamentUpdateException.java b/src/main/java/com/gg/server/domain/tournament/exception/TournamentUpdateException.java deleted file mode 100644 index d1f9c6e80..000000000 --- a/src/main/java/com/gg/server/domain/tournament/exception/TournamentUpdateException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gg.server.domain.tournament.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.ForbiddenException; - -public class TournamentUpdateException extends ForbiddenException { - public TournamentUpdateException() { - super(ErrorCode.TOURNAMENT_CAN_NOT_UPDATE.getMessage(), ErrorCode.TOURNAMENT_CAN_NOT_UPDATE); - } - public TournamentUpdateException(ErrorCode errorCode) { - super(errorCode.getMessage(), errorCode); - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/service/TournamentService.java b/src/main/java/com/gg/server/domain/tournament/service/TournamentService.java deleted file mode 100644 index 5d4368b8f..000000000 --- a/src/main/java/com/gg/server/domain/tournament/service/TournamentService.java +++ /dev/null @@ -1,303 +0,0 @@ -package com.gg.server.domain.tournament.service; - -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.match.service.MatchTournamentService; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.tournament.data.*; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.data.TournamentUserRepository; -import com.gg.server.domain.tournament.dto.TournamentUserRegistrationResponseDto; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.tournament.dto.TournamentGameListResponseDto; -import com.gg.server.domain.tournament.dto.TournamentGameResDto; -import com.gg.server.domain.tournament.dto.TournamentListResponseDto; -import com.gg.server.domain.tournament.dto.TournamentResponseDto; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.exception.TournamentNotFoundException; -import com.gg.server.domain.tournament.exception.TournamentUpdateException; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.tournament.type.TournamentUserStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.dto.UserImageDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDate; -import java.util.ArrayList; - -import static com.gg.server.domain.tournament.type.TournamentRound.*; - -@Service -@RequiredArgsConstructor -public class TournamentService { - private final TournamentRepository tournamentRepository; - private final TournamentUserRepository tournamentUserRepository; - private final UserRepository userRepository; - private final TournamentGameRepository tournamentGameRepository; - private final GameRepository gameRepository; - private final MatchTournamentService matchTournamentService; - private final NotiAdminService notiAdminService; - - /** - * ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ - * @param pageRequest ํŽ˜์ด์ง€ ์ •๋ณด - * @param type ํ† ๋„ˆ๋จผํŠธ ํƒ€์ž… - * @param status ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ - * @return ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ - */ - public TournamentListResponseDto getAllTournamentList(Pageable pageRequest, TournamentType type, TournamentStatus status) { - - Page tournaments; - if (type == null && status == null) { - tournaments = tournamentRepository.findAll(pageRequest). - map(o-> new TournamentResponseDto(o, findTournamentWinner(o), findJoinedPlayerCnt(o))); - } else if (type == null){ - tournaments = tournamentRepository.findAllByStatus(status, pageRequest). - map(o-> new TournamentResponseDto(o, findTournamentWinner(o), findJoinedPlayerCnt(o))); - } else if (status == null) { - tournaments = tournamentRepository.findAllByType(type, pageRequest). - map(o-> new TournamentResponseDto(o, findTournamentWinner(o), findJoinedPlayerCnt(o))); - } else { - tournaments = tournamentRepository.findAllByTypeAndStatus(type, status, pageRequest). - map(o-> new TournamentResponseDto(o, findTournamentWinner(o), findJoinedPlayerCnt(o))); - } - return new TournamentListResponseDto(tournaments.getContent(), tournaments.getTotalPages()); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๋‹จ์ผ ์กฐํšŒ - * @param tournamentId - * @return ํ† ๋„ˆ๋จผํŠธ - */ - public TournamentResponseDto getTournament(long tournamentId) { - Tournament tournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - return (new TournamentResponseDto(tournament, findTournamentWinner(tournament), findJoinedPlayerCnt(tournament))); - } - - /** - *

์œ ์ € ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ ์ฐธ์—ฌ ์—ฌ๋ถ€ ํ™•์ธ ๋งค์„œ๋“œ

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ - * @param user ํ•ด๋‹น ์œ ์ € - * @return TournamentUserRegistrationResponseDto [ BEFORE || WAIT || PLAYER ] - * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ - */ - public TournamentUserRegistrationResponseDto getUserStatusInTournament(Long tournamentId, UserDto user) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - - TournamentUserStatus tournamentUserStatus = TournamentUserStatus.BEFORE; - Optional tournamentUser = tournamentUserRepository.findByTournamentIdAndUserId(tournamentId, user.getId()); - if (tournamentUser.isPresent()) { - tournamentUserStatus = tournamentUser.get().getIsJoined() ? TournamentUserStatus.PLAYER : TournamentUserStatus.WAIT; - } - return new TournamentUserRegistrationResponseDto(tournamentUserStatus); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ๋งค์„œ๋“œ

- *

์ด๋ฏธ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ ์ค‘ BEFORE || LIVE์ธ ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด ์‹ ์ฒญ ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค.

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ Id - * @param user ์‹ ์ฒญ ์œ ์ €(๋กœ๊ทธ์ธํ•œ ๋ณธ์ธ) - * @return TournamentUserRegistrationResponseDto [ WAIT || PLAYER ] - * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ - * @throws UserNotFoundException ์œ ์ € ์—†์Œ - * @throws TournamentConflictException ์ด๋ฏธ ์‹ ์ฒญํ•œ ํ† ๋„ˆ๋จผํŠธ ์กด์žฌ(BEFORE || LIVE์ธ ํ† ๋„ˆ๋จผํŠธ) - */ - @Transactional - public TournamentUserRegistrationResponseDto registerTournamentUser(Long tournamentId, UserDto user) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - - List tournamentUserList = targetTournament.getTournamentUsers(); - tournamentUserRepository.findAllByUser(loginUser).stream() - .filter(tu->tu.getTournament().getStatus().equals(TournamentStatus.BEFORE) || tu.getTournament().getStatus().equals(TournamentStatus.LIVE)) - .findAny() - .ifPresent(a->{throw new TournamentConflictException(ErrorCode.TOURNAMENT_ALREADY_PARTICIPANT);}); - TournamentUser tournamentUser = new TournamentUser(loginUser, targetTournament, - tournamentUserList.size() < Tournament.ALLOWED_JOINED_NUMBER, LocalDateTime.now()); - TournamentUserStatus tournamentUserStatus = tournamentUser.getIsJoined() ? TournamentUserStatus.PLAYER : TournamentUserStatus.WAIT; - return new TournamentUserRegistrationResponseDto(tournamentUserStatus); - } - - /** - *

์œ ์ € ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ์ทจ์†Œ ๋งค์„œ๋“œ

- *

์ฐธ๊ฐ€์ž๊ฐ€ WAIT ์ด๊ฑฐ๋‚˜ PLAYER ๋กœ ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ์— ์‹ ์ฒญ์„ ํ•œ ์ƒํƒœ์ผ๋•Œ๋งŒ ์ทจ์†Œํ•ด ์ค€๋‹ค.

- * @param tournamentId ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ - * @param user ํƒ€๊ฒŸ ์œ ์ €(์‚ฌ์šฉ์ž ๋ณธ์ธ) - * @throws TournamentNotFoundException ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์—†์Œ || ํƒ€๊ฒŸ ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹˜ - * @return - */ - @Transactional - public TournamentUserRegistrationResponseDto cancelTournamentUserRegistration(Long tournamentId, UserDto user) { - Tournament targetTournament = tournamentRepository.findById(tournamentId).orElseThrow(TournamentNotFoundException::new); - if (!targetTournament.getStatus().equals(TournamentStatus.BEFORE)) { - throw new TournamentUpdateException(); - } - - List tournamentUserList = targetTournament.getTournamentUsers(); - TournamentUser targetTournamentUser = tournamentUserList.stream() - .filter(tu -> (tu.getUser().getId().equals(user.getId()))) - .findAny() - .orElseThrow(()-> new TournamentNotFoundException(ErrorCode.TOURNAMENT_NOT_PARTICIPANT)); - tournamentUserList.remove(targetTournamentUser); - if (targetTournamentUser.getIsJoined() && tournamentUserList.size() >= Tournament.ALLOWED_JOINED_NUMBER) { - tournamentUserList.get(Tournament.ALLOWED_JOINED_NUMBER - 1).updateIsJoined(true); - } - tournamentUserRepository.delete(targetTournamentUser); - return new TournamentUserRegistrationResponseDto(TournamentUserStatus.BEFORE); - } - - /** - * ์ง„ํ–‰์ค‘์ธ ํ† ๋„ˆ๋จผํŠธ ์œ ๋ฌด ํ™•์ธ - * @param time ํ˜„์žฌ ์‹œ๊ฐ„ - * @return ์ข…๋ฃŒ๋˜์ง€ ์•Š์€ ํ† ๋„ˆ๋จผํŠธ ์žˆ์œผ๋ฉด true, ์—†์œผ๋ฉด false - */ - public boolean isNotEndedTournament(LocalDateTime time) { - List tournamentList = tournamentRepository.findAllByStatusIsNot(TournamentStatus.END); - for (Tournament tournament : tournamentList) { - if (time.isAfter(tournament.getStartTime()) && - time.isBefore(tournament.getEndTime())) { - return false; - } - } - return true; - } - - /** - * ์˜ค๋Š˜ ์‹œ์ž‘ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ status๋ฅผ LIVE๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ - * ์ฐธ๊ฐ€์ž๊ฐ€ ALLOWED_JOINED_NUMBER๋ณด๋‹ค ์ ์œผ๋ฉด ํ† ๋„ˆ๋จผํŠธ ์ทจ์†Œ - */ - @Transactional - public void startTournament() { - LocalDate date = LocalDate.now(); - List imminentTournaments = findImminentTournament(date); - for (Tournament imminentTournament : imminentTournaments) { - List tournamentUsers = imminentTournament.getTournamentUsers(); - if (tournamentUsers.size() < Tournament.ALLOWED_JOINED_NUMBER) { - for (TournamentUser tournamentUser : tournamentUsers) { - if (tournamentUser.getIsJoined().equals(true)) { - notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(tournamentUser.getUser().getIntraId(), NotiType.TOURNAMENT_CANCELED.getMessage())); - } - } - tournamentRepository.delete(imminentTournament); - return; - } - imminentTournament.updateStatus(TournamentStatus.LIVE); - matchTournamentService.matchGames(imminentTournament, QUARTER_FINAL_1); - } - } - - /** - * ์‹œ์ž‘ ์ž„๋ฐ•ํ•œ(์˜ค๋Š˜ ์‹œ์ž‘ํ•˜๋Š”) ํ† ๋„ˆ๋จผํŠธ ์กฐํšŒ - * @param date ์กฐํšŒํ•˜๋ ค๋Š” ํ† ๋„ˆ๋จผํŠธ์˜ ์‹œ์ž‘ ๋‚ ์งœ - * @return date ๋‚ ์งœ์— ์‹œ์ž‘ํ•˜๋Š” ํ† ๋„ˆ๋จผํŠธ - */ - private List findImminentTournament(LocalDate date) { - List tournaments = tournamentRepository.findAllByStatus(TournamentStatus.BEFORE); - List imminentTournaments = new ArrayList<>(); - - for (Tournament tournament : tournaments) { - LocalDate startDate = tournament.getStartTime().toLocalDate(); - if (startDate.isEqual(date)) { - imminentTournaments.add(tournament); - } - } - return imminentTournaments; - } - - - /** - * ํ† ๋„ˆ๋จผํŠธ ์šฐ์Šน์ž ์กฐํšŒ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @return ํ† ๋„ˆ๋จผํŠธ ์šฐ์Šน์ž ์ •๋ณด - */ - private UserImageDto findTournamentWinner(Tournament tournament) { - User winner = tournament.getWinner(); - return new UserImageDto(winner); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž ์ˆ˜ ์กฐํšŒ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @return ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž ์ˆ˜ - */ - private int findJoinedPlayerCnt(Tournament tournament) { - return tournamentUserRepository.countByTournamentAndIsJoined(tournament, true); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ - * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id - * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ชฉ๋ก - */ - public TournamentGameListResponseDto getTournamentGames(Long tournamentId) { - List tournamentGameResDtoList = getTournamentGameResDtoList(tournamentId); - return new TournamentGameListResponseDto(tournamentId, tournamentGameResDtoList); - } - - /** - * TournamentGameResDto list ๋ฐ˜ํ™˜ - * @param tournamentId ํ† ๋„ˆ๋จผํŠธ id - * @return List - * - tournamentGameId: ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ id - * - NextTournamentGameId: ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ id - * - tournamentRound: ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ - * - game: ๊ฒŒ์ž„ ์ •๋ณด - */ - private List getTournamentGameResDtoList(Long tournamentId){ - List tournamentGames = tournamentGameRepository.findAllByTournamentId(tournamentId); - List tournamentGameResDtoList = new ArrayList<>(); - for (TournamentGame tournamentGame : tournamentGames) { - TournamentGame nextTournamentGame = findNextTournamentGame(tournamentGames, tournamentGame); - GameTeamUser gameTeamUser = null; - if (tournamentGame.getGame() != null) { - gameTeamUser = gameRepository.findTeamsByGameId(tournamentGame.getGame().getId()) - .orElseThrow(() -> new BusinessException(ErrorCode.TEAM_USER_NOT_FOUND)); - } - tournamentGameResDtoList.add(new TournamentGameResDto(tournamentGame, gameTeamUser, tournamentGame.getTournamentRound(), nextTournamentGame)); - } - tournamentGameResDtoList.sort((o1, o2) -> { - if (o1.getTournamentRound().getRoundNumber() < o2.getTournamentRound().getRoundNumber()) { - return 1; - } - if (o1.getTournamentRound().getRoundOrder() > o2.getTournamentRound().getRoundOrder()) { - return 1; - } - return -1; - }); - return tournamentGameResDtoList; - } - - /** - * ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์กฐํšŒ - * @param tournamentGames tournamentGames ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ - * @param tournamentGame ํ˜„์žฌ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - * @return ๋‹ค์Œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - */ - private TournamentGame findNextTournamentGame(List tournamentGames, TournamentGame tournamentGame) { - TournamentRound tournamentRound = tournamentGame.getTournamentRound(); - return tournamentGames.stream() - .filter(tournamentGame1 -> tournamentGame1.getTournamentRound().equals(tournamentRound.getNextRound())) - .findFirst() - .orElse(null); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/tournament/type/TournamentRound.java b/src/main/java/com/gg/server/domain/tournament/type/TournamentRound.java deleted file mode 100644 index 89645d5c9..000000000 --- a/src/main/java/com/gg/server/domain/tournament/type/TournamentRound.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.domain.tournament.type; - -import java.util.ArrayList; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.List; - -@RequiredArgsConstructor -@Getter -public enum TournamentRound { - // the final -> ๊ฒฐ์Šน - // semi final -> 4๊ฐ• - // quarter final -> 8๊ฐ• - // ordinal()๋กœ sorting ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ˆœ์„œ ์ค‘์š” -> ์ดํ›„์— ๋ฆฌํŒฉํ† ๋ง์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. - THE_FINAL(null, 2, 1), - SEMI_FINAL_1(THE_FINAL, 4, 1), - SEMI_FINAL_2(THE_FINAL, 4, 2), - QUARTER_FINAL_1(SEMI_FINAL_1, 8, 1), - QUARTER_FINAL_2( SEMI_FINAL_1, 8, 2), - QUARTER_FINAL_3(SEMI_FINAL_2, 8, 3), - QUARTER_FINAL_4(SEMI_FINAL_2, 8, 4); - - private final TournamentRound nextRound; - private final int roundNumber; - private final int roundOrder; - - public static List getSameRounds(TournamentRound round) { - List sameRounds = new ArrayList<>(); - for (TournamentRound e : values()) { - if (e.roundNumber == round.roundNumber) { - sameRounds.add(e); - } - } - return sameRounds; - } - - /** - * ์ด์ „ TournamentRound์˜ roundNum๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. - * @param round - ํ˜„์žฌ ๋ผ์šด๋“œ - * @return ์ด์ „ ๋ผ์šด๋“œ์˜ roundNum, ์—†์„ ๊ฒฝ์šฐ -1 ๋ฐ˜ํ™˜ - */ - public static int getPreviousRoundNumber(TournamentRound round) { - for (TournamentRound e : values()) { - if (e.nextRound == round) { - return e.roundNumber; - } - } - return -1; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/type/TournamentStatus.java b/src/main/java/com/gg/server/domain/tournament/type/TournamentStatus.java deleted file mode 100644 index 644054125..000000000 --- a/src/main/java/com/gg/server/domain/tournament/type/TournamentStatus.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.tournament.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum TournamentStatus { - BEFORE("before", "ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์ „"), - LIVE("live", "ํ† ๋„ˆ๋จผํŠธ ์ง„ํ–‰ ์ค‘"), - END("end", "ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ"); - - private final String code; - private final String desc; - - - @JsonCreator - public static TournamentStatus getEnumFromValue(String value) { - if (value == null) return null; - for(TournamentStatus e : values()) { - if (e.name().equals(value)) { - return e; - } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/type/TournamentType.java b/src/main/java/com/gg/server/domain/tournament/type/TournamentType.java deleted file mode 100644 index ffe08f5e1..000000000 --- a/src/main/java/com/gg/server/domain/tournament/type/TournamentType.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.tournament.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum TournamentType { - ROOKIE("rookie", "์ดˆ๋ณด"), - MASTER("master", "๊ณ ์ˆ˜"), - CUSTOM("custom", "์ปค์Šคํ…€"); - - private final String code; - private final String desc; - - - @JsonCreator - public static TournamentType getEnumFromValue(String value) { - if (value == null) return null; - for(TournamentType e : values()) { - if (e.name().equals(value)) { - return e; - } else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/domain/tournament/type/TournamentUserStatus.java b/src/main/java/com/gg/server/domain/tournament/type/TournamentUserStatus.java deleted file mode 100644 index fda394de9..000000000 --- a/src/main/java/com/gg/server/domain/tournament/type/TournamentUserStatus.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.tournament.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum TournamentUserStatus { - PLAYER("player", "ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€์ž"), - WAIT("wait", "ํ† ๋„ˆ๋จผํŠธ ๋Œ€๊ธฐ์ž"), - BEFORE("before", "ํ† ๋„ˆ๋จผํŠธ ์‹ ์ฒญ ์ „"); - - private final String code; - private final String desc; -} diff --git a/src/main/java/com/gg/server/domain/user/controller/UserController.java b/src/main/java/com/gg/server/domain/user/controller/UserController.java deleted file mode 100644 index 10b54143b..000000000 --- a/src/main/java/com/gg/server/domain/user/controller/UserController.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.gg.server.domain.user.controller; - -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.user.dto.*; -import com.gg.server.domain.user.exception.KakaoOauth2AlreadyExistException; -import com.gg.server.domain.user.exception.TokenNotValidException; -import com.gg.server.domain.user.service.*; -import com.gg.server.domain.user.type.OauthType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.dto.PageRequestDto; -import com.gg.server.global.security.cookie.CookieUtil; -import com.gg.server.global.security.jwt.utils.TokenHeaders; -import com.gg.server.global.utils.argumentresolver.Login; -import io.swagger.v3.oas.annotations.Parameter; -import lombok.RequiredArgsConstructor; - -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.List; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/pingpong/users") -public class UserController { - private final UserService userService; - private final UserAuthenticationService userAuthenticationService; - private final CookieUtil cookieUtil; - private final UserCoinService userCoinService; - - @PostMapping("/accesstoken") - public ResponseEntity generateAccessToken(@RequestParam String refreshToken) { - String accessToken = userAuthenticationService.regenerate(refreshToken); - return new ResponseEntity<>(new UserAccessTokenDto(accessToken), HttpStatus.CREATED); - } - - @GetMapping - UserNormalDetailResponseDto getUserNormalDetail(@Parameter(hidden = true) @Login UserDto user){ - return userService.getUserNormalDetail(user); - } - - @GetMapping("/live") - UserLiveResponseDto getUserLiveDetail(@Parameter(hidden = true) @Login UserDto user) { - return userService.getUserLiveDetail(user); - } - - @GetMapping("/searches") - UserSearchResponseDto searchUsers(@RequestParam String intraId){ - List intraIds = userService.findByPartOfIntraId(intraId); - return new UserSearchResponseDto(intraIds); - } - - @GetMapping("/{intraId}") - public UserDetailResponseDto getUserDetail(@PathVariable String intraId){ - return userService.getUserDetail(intraId); - } - - @GetMapping("/{intraId}/rank") - public UserRankResponseDto getUserRank(@PathVariable String intraId, @RequestParam Long season){ - return userService.getUserRankDetail(intraId, season); - } - - @GetMapping("/{intraId}/historics") - public UserHistoryResponseDto getUserHistory(@PathVariable String intraId, @RequestParam Long season) { - return userService.getUserHistory(intraId, season); - } - - @PutMapping("{intraId}") - public ResponseEntity doModifyUser (@Valid @RequestBody UserModifyRequestDto userModifyRequestDto, - @PathVariable String intraId, @Parameter(hidden = true) @Login UserDto loginUser) { - if (!loginUser.getIntraId().equals(intraId)) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); - } - userService.updateUser(userModifyRequestDto.getRacketType(), userModifyRequestDto.getStatusMessage(), - userModifyRequestDto.getSnsNotiOpt(), intraId); - return ResponseEntity.noContent().build(); - } - - @PostMapping("/logout") - public void logout(HttpServletResponse response) { - cookieUtil.deleteCookie(response, TokenHeaders.REFRESH_TOKEN); - } - - /** - * 42user ์นด์นด์˜ค ๋กœ๊ทธ์ธ ์—ฐ๋™ ํ•ด์ œ - */ - @DeleteMapping("/oauth/kakao") - public void deleteOauthKakao(@Parameter(hidden = true) @Login UserDto user) { - if (user.getRoleType().equals(RoleType.GUEST) || user.getKakaoId() == null) { - throw new KakaoOauth2AlreadyExistException(); - } - userService.deleteKakaoId(user.getId()); - } - - @GetMapping("/oauth") - public UserOauthDto getUserOauth2Information(@Parameter(hidden = true) @Login UserDto user) { - return new UserOauthDto(OauthType.of(user.getRoleType(), user.getKakaoId()).getCode()); - } - - @GetMapping("/top3") - public UserImageResponseDto getUserImage(@RequestParam(required = false) Long seasonId, Mode mode) { - if (mode == Mode.RANK) - return userService.getRankedUserImagesByPPP(seasonId); - else{ - PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "totalExp")); - return userService.getRankedUserImagesByExp(pageRequest); - } - } - - @PatchMapping("/text-color") - public ResponseEntity updateTextColor(@RequestBody @Valid UserTextColorDto textColorDto, @Parameter(hidden = true) @Login UserDto user) { - userService.updateTextColor(user.getId() ,textColorDto); - return ResponseEntity.noContent().build(); - } - - @PostMapping("/attendance") - public UserAttendanceResponseDto attendUser(@Parameter(hidden = true) @Login UserDto user) { - return userService.attendUser(user.getId()); - } - - @PatchMapping("/edge") - public String updateEdge(@RequestBody @Valid UserEdgeDto userEdgeDto, @Parameter(hidden = true) @Login UserDto user) { - String edge = userService.updateEdge(user, userEdgeDto); - return "{\"edge\": " + "\"" + edge + "\"" +"}"; - } - - @GetMapping("/coin") - public UserCoinResponseDto getUserCoin(@Parameter(hidden = true) @Login UserDto user) { - return userCoinService.getUserCoin(user.getIntraId()); - } - - @PatchMapping("/background") - public String updateBackground(@RequestBody @Valid UserBackgroundDto userBackgroundDto, @Parameter(hidden = true) @Login UserDto user) { - String background = userService.updateBackground(user, userBackgroundDto); - return "{\"background\": " + "\"" + background + "\"" +"}"; - } - - @GetMapping("/coinhistory") - public UserCoinHistoryListResponseDto getUserCoinHistory(@ModelAttribute @Valid PageRequestDto coReq, @Parameter(hidden = true) @Login UserDto user) { - Pageable pageable = PageRequest.of(coReq.getPage() - 1, coReq.getSize(), Sort.by("createdAt").descending()); - - return userCoinService.getUserCoinHistory(pageable ,user.getIntraId()); - } - - @PostMapping(path = "/profile-image", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE}) - public ResponseEntity updateUserProfileImage(@RequestPart(required = false) MultipartFile profileImage, - @RequestPart @Valid UserProfileImageRequestDto userProfileImageRequestDto, - @Parameter(hidden = true) @Login UserDto user) throws IOException { - userService.updateUserProfileImage(user, userProfileImageRequestDto, profileImage); - return ResponseEntity.noContent().build(); - } -} diff --git a/src/main/java/com/gg/server/domain/user/data/User.java b/src/main/java/com/gg/server/domain/user/data/User.java deleted file mode 100644 index 1a9b58b21..000000000 --- a/src/main/java/com/gg/server/domain/user/data/User.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.gg.server.domain.user.data; - -import com.gg.server.admin.user.dto.UserUpdateAdminRequestDto; -import com.gg.server.domain.item.exception.InsufficientGgcoinException; -import com.gg.server.domain.user.type.*; -import com.gg.server.global.utils.BaseTimeEntity; -import lombok.*; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class User extends BaseTimeEntity implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @Column(name = "intra_id", length = 30) - private String intraId; - - @Column(name = "e_mail", length = 60) - private String eMail; - - @Column(name = "image_uri") - private String imageUri; - - @Enumerated(EnumType.STRING) - @Column(name = "racket_type", length = 10) - private RacketType racketType; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = "role_type", length = 10) - private RoleType roleType; - - @Column(name = "total_exp") - private Integer totalExp; - - @Column(name = "sns_noti_opt", length = 10) - @Enumerated(EnumType.STRING) - private SnsType snsNotiOpt; - - @Column(name = "kakao_id") - private Long kakaoId; - - @Column(name = "gg_coin") - private Integer ggCoin; - - @Column(name = "background") - @Enumerated(EnumType.STRING) - private BackgroundType background; - - @Column(name = "text_color", length = 10) - private String textColor; - - @Column(name = "edge") - @Enumerated(EnumType.STRING) - private EdgeType edge; - - @Builder - public User(String intraId, String eMail, String imageUri, RacketType racketType, - RoleType roleType, Integer totalExp, SnsType snsNotiOpt, Long kakaoId) { - this.intraId = intraId; - this.eMail = eMail; - this.imageUri = imageUri; - this.racketType = racketType; - this.roleType = roleType; - this.totalExp = totalExp; - this.snsNotiOpt = snsNotiOpt; - this.kakaoId = kakaoId; - this.background = BackgroundType.BASIC; - this.textColor = "#000000"; - this.edge = EdgeType.BASIC; - this.ggCoin = 0; - } - - public void modifyUserDetail(UserUpdateAdminRequestDto updateReq) { - this.eMail = updateReq.getEmail(); - this.racketType = updateReq.getRacketType(); - this.roleType = RoleType.of(updateReq.getRoleType()); - this.ggCoin = updateReq.getCoin(); - } - - public void updateImageUri(String imageUri) { - this.imageUri = imageUri; - } - - public void updateTypes(RacketType racketType, SnsType snsType) { - this.racketType = racketType; - this.snsNotiOpt = snsType; - } - - public void addExp(int plus) { - this.totalExp += plus; - } - - public void updateExp(int beforeExp) { - this.totalExp = beforeExp; - } - - public void updateKakaoId(Long kakaoId) { - this.kakaoId = kakaoId; - } - - public void updateTextColor(String textColor) { - this.textColor = textColor; - } - - public void updateEdge(EdgeType edge) { - this.edge = edge; - } - - public int addGgCoin(int plus) { - this.ggCoin += plus; - return this.ggCoin; - } - - public void payGgCoin(int amount) { - if (this.ggCoin < amount) { - throw new InsufficientGgcoinException(); // ์‚ฌ์šฉ์ž์˜ ggCoin์ด ํ•„์š”ํ•œ ๊ธˆ์•ก๋ณด๋‹ค ์ ์„ ๊ฒฝ์šฐ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ - } - this.ggCoin = this.ggCoin - amount; - } - - public void updateBackground(BackgroundType background) { - this.background = background; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/data/UserImage.java b/src/main/java/com/gg/server/domain/user/data/UserImage.java deleted file mode 100644 index 8cd0bf920..000000000 --- a/src/main/java/com/gg/server/domain/user/data/UserImage.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gg.server.domain.user.data; - -import com.sun.istack.NotNull; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import java.time.LocalDateTime; - -@NoArgsConstructor -@AllArgsConstructor -@Entity -@Getter -public class UserImage { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @NotNull - @Column(name = "image_uri") - private String imageUri; - - @NotNull - @Column(name = "created_at") - private LocalDateTime createdAt; - - @Column(name = "deleted_at") - private LocalDateTime deletedAt; - - @NotNull - @Column(name = "is_current") - private Boolean isCurrent; - - public UserImage(User user, String imageUri, LocalDateTime createdAt, LocalDateTime deletedAt, Boolean isCurrent) { - this.user = user; - this.imageUri = imageUri; - this.createdAt = createdAt; - this.deletedAt = deletedAt; - this.isCurrent = isCurrent; - } - - public void updateIsCurrent() { - this.isCurrent = !this.isCurrent; - } - - public void updateDeletedAt(LocalDateTime deletedAt) { - this.deletedAt = deletedAt; - updateIsCurrent(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java b/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java deleted file mode 100644 index 660805a63..000000000 --- a/src/main/java/com/gg/server/domain/user/data/UserImageRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.domain.user.data; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserImageRepository extends JpaRepository { - Optional findTopByUserAndIsCurrentIsTrueOrderByIdDesc(User user); -} diff --git a/src/main/java/com/gg/server/domain/user/data/UserRepository.java b/src/main/java/com/gg/server/domain/user/data/UserRepository.java deleted file mode 100644 index f6750bb6a..000000000 --- a/src/main/java/com/gg/server/domain/user/data/UserRepository.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.domain.user.data; - -import com.gg.server.domain.rank.dto.ExpRankV2Dto; -import java.util.List; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -import java.util.Optional; - -public interface UserRepository extends JpaRepository { - Optional findByIntraId(String intraId); - - Optional getUserByIntraId(String IntraId); - - Page findByIntraIdContains(Pageable pageable, String intraId); - - Page findAllByTotalExpGreaterThan(Pageable pageable, Integer exp); - - Optional findByKakaoId(Long kakaoId); - - @Query(nativeQuery = true, value = "select ranking from " + - "(select intra_id, row_number() over (order by total_exp desc, intra_id asc) as ranking from user) ranked where intra_id=:intraId") - Long findExpRankingByIntraId(@Param("intraId") String intraId); - Page findAll(Pageable pageable); - - @Query("select tu.user from User u, TeamUser tu, Team t, Game g" + - " where g.id=:gameId and t.game.id =g.id and tu.team.id = t.id " - + "and u.id = tu.user.id and u.id !=:userId") - List findEnemyByGameAndUser(@Param("gameId") Long gameId, @Param("userId") Long userId); - - List findUsersByIdIn(List userIds); - - @Modifying(clearAutomatically = true) - @Query("update User u set u.imageUri = :imageUri where u.id = :id") - void updateUserImage(Long id, String imageUri); - - @Query(value = "SELECT u.intra_id intraId, r.status_message statusMessage, u.total_exp totalExp, " - + "u.image_uri imageUri, u.text_color textColor, " - + "RANK() OVER(ORDER BY u.total_exp DESC, r.modified_at DESC, r.ppp DESC) ranking " - + "FROM User u LEFT JOIN Ranks r " - + "ON u.id = r.user_id " - + "WHERE r.season_id = :seasonId AND u.total_exp > 0 " - + "LIMIT :limit OFFSET :offset", nativeQuery = true) - List findExpRank(@Param("offset")int offset, @Param("limit")int limit, @Param("seasonId")Long seasonId); - -} diff --git a/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java deleted file mode 100644 index 74066fb9f..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/CoinHistoryResponseDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.coin.data.CoinHistory; -import com.gg.server.domain.coin.data.CoinHistoryRepository; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -public class CoinHistoryResponseDto { - private String history; - private int amount; - private LocalDateTime createdAt; - - public CoinHistoryResponseDto(CoinHistory coinHistory) { - this.history = coinHistory.getHistory(); - this.amount = coinHistory.getAmount(); - this.createdAt = coinHistory.getCreatedAt(); - } -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserAccessTokenDto.java b/src/main/java/com/gg/server/domain/user/dto/UserAccessTokenDto.java deleted file mode 100644 index ff4a79fb2..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserAccessTokenDto.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class UserAccessTokenDto { - private String accessToken; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java deleted file mode 100644 index c9f7b2ea6..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserAttendanceResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserAttendanceResponseDto { - private int beforeCoin; - private int afterCoin; - private int coinIncrement; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java b/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java deleted file mode 100644 index 38065e6d8..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserBackgroundDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserBackgroundDto { - @NotNull - private Long receiptId; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java deleted file mode 100644 index 0c80b4a71..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserCoinHistoryListResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.admin.coin.dto.CoinPolicyAdminResponseDto; -import com.gg.server.domain.coin.data.CoinHistory; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class UserCoinHistoryListResponseDto { - private List useCoinList; - private int totalPage; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java deleted file mode 100644 index fa5e130ad..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserCoinResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@Getter -public class UserCoinResponseDto { - private int coin; - - public UserCoinResponseDto(int userCoin) { - this.coin = userCoin; - } -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java deleted file mode 100644 index 1fb6b72ec..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserDetailResponseDto.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.BackgroundType; -import com.gg.server.domain.user.type.EdgeType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.*; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class UserDetailResponseDto { - private String intraId; - private String userImageUri; - private String racketType; - private String statusMessage; - private Integer level; - private Integer currentExp; - private Integer maxExp; - private Double expRate; - private SnsType snsNotiOpt; - private BackgroundType background; - private String textColor; - private EdgeType edge; - private String tierName; - private String tierImageUri; - - public UserDetailResponseDto(User user, String statusMessage, Tier tier) { - this.intraId = user.getIntraId(); - this.racketType = user.getRacketType().getCode(); - this.userImageUri = user.getImageUri(); - this.statusMessage = statusMessage; - this.snsNotiOpt = user.getSnsNotiOpt(); - this.background= user.getBackground(); - this.textColor = user.getTextColor(); - this.edge = user.getEdge(); - this.tierName = tier.getName(); - this.tierImageUri = tier.getImageUri(); - calculateExpAndLevel(user); - } - - private void calculateExpAndLevel(User user) { - this.currentExp = ExpLevelCalculator.getCurrentLevelMyExp(user.getTotalExp()); - this.maxExp = ExpLevelCalculator.getLevelMaxExp(ExpLevelCalculator.getLevel(user.getTotalExp())); - this.level = ExpLevelCalculator.getLevel(user.getTotalExp()); - this.expRate = (double)(currentExp * 10000 / maxExp) / 100; - } - -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserDto.java b/src/main/java/com/gg/server/domain/user/dto/UserDto.java deleted file mode 100644 index 393aeaa6a..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserDto.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class UserDto { - private Long id; - private String intraId; - private String eMail; - private RacketType racketType; - private RoleType roleType; - private Integer totalExp; - private SnsType snsNotiOpt; - private Long kakaoId; - private String textColor; - private Integer ggCoin; - - static public UserDto from (User user) { - UserDto userDto; - if (user == null) { - userDto = null; - } else { - userDto = UserDto.builder() - .id(user.getId()) - .intraId(user.getIntraId()) - .eMail(user.getEMail()) - .racketType(user.getRacketType()) - .roleType(user.getRoleType()) - .totalExp(user.getTotalExp()) - .snsNotiOpt(user.getSnsNotiOpt()) - .kakaoId(user.getKakaoId()) - .ggCoin(user.getGgCoin()) - .build(); - } - return userDto; - } - - @Override - public String toString() { - return "UserDto{" + - "id=" + id + - ", intraId='" + intraId + '\'' + - ", eMail='" + eMail + '\'' + - ", racketType=" + racketType + - ", roleType=" + roleType + - ", totalExp=" + totalExp + - ", snsNotiOpt=" + snsNotiOpt + - ", kakaoId=" + kakaoId + - '}'; - } -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java b/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java deleted file mode 100644 index e333aed27..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserEdgeDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserEdgeDto { - @NotNull - private Long receiptId; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserHistoryData.java b/src/main/java/com/gg/server/domain/user/dto/UserHistoryData.java deleted file mode 100644 index 26e3587fc..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserHistoryData.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.pchange.data.PChange; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -public class UserHistoryData { - private int ppp; - private LocalDateTime date; - - public UserHistoryData(PChange pChange){ - this.ppp = pChange.getPppResult(); - this.date = pChange.getCreatedAt(); - } -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserHistoryResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserHistoryResponseDto.java deleted file mode 100644 index 4df716096..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserHistoryResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class UserHistoryResponseDto { - private List historics; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java b/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java deleted file mode 100644 index 19762a1df..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserImageDto.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.EdgeType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -import java.time.LocalDateTime; - - -@Getter -@NoArgsConstructor -public class UserImageDto { - private String intraId; - private String imageUri; - private EdgeType edge; - private String tierImage; - - public UserImageDto(String intraId, String imageUri, EdgeType edge, String tierImage) { - this.intraId = intraId; - this.imageUri = imageUri; - this.edge = edge; - this.tierImage = tierImage; - } - - public UserImageDto(User user){ - this.intraId = (user == null)? null : user.getIntraId(); - this.imageUri = (user == null)? null : user.getImageUri(); - } -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserImageResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserImageResponseDto.java deleted file mode 100644 index dc5f46628..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserImageResponseDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserImageResponseDto { - - List userImages; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserLiveResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserLiveResponseDto.java deleted file mode 100644 index 906ffe54f..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserLiveResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.game.type.Mode; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class UserLiveResponseDto { - private int notiCount; - private String event; - private Mode currentMatchMode; - private Long gameId; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserModifyRequestDto.java b/src/main/java/com/gg/server/domain/user/dto/UserModifyRequestDto.java deleted file mode 100644 index 0cac21747..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserModifyRequestDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.SnsType; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class UserModifyRequestDto { - - private RacketType racketType; - private String statusMessage; - private SnsType snsNotiOpt; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java deleted file mode 100644 index 259c3db39..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserNormalDetailResponseDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.type.EdgeType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserNormalDetailResponseDto { - private String intraId; - private String userImageUri; - private Boolean isAdmin; - private Boolean isAttended; - private EdgeType edgeType; - private String tierName; - private String tierImageUri; - private Integer level; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserOauthDto.java b/src/main/java/com/gg/server/domain/user/dto/UserOauthDto.java deleted file mode 100644 index c48286706..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserOauthDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.gg.server.domain.user.type.OauthType; -import com.gg.server.domain.user.type.RoleType; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class UserOauthDto { - private String oauthType; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java b/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java deleted file mode 100644 index 7666b2afe..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserProfileImageRequestDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserProfileImageRequestDto { - @NotNull - private Long receiptId; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserRankResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserRankResponseDto.java deleted file mode 100644 index 3baa2b8fe..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserRankResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@ToString -public class UserRankResponseDto { - private int rank; - private int ppp; - private int wins; - private int losses; - private double winRate; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserSearchResponseDto.java b/src/main/java/com/gg/server/domain/user/dto/UserSearchResponseDto.java deleted file mode 100644 index f604fed73..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserSearchResponseDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class UserSearchResponseDto { - private List users; -} diff --git a/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java b/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java deleted file mode 100644 index 3629792c2..000000000 --- a/src/main/java/com/gg/server/domain/user/dto/UserTextColorDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.domain.user.dto; - -import com.sun.istack.NotNull; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class UserTextColorDto { - @NotNull - private Long receiptId; - @NotNull - private String textColor; -} diff --git a/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2AlreadyExistException.java b/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2AlreadyExistException.java deleted file mode 100644 index 1fe3bfb2c..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2AlreadyExistException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.InvalidParameterException; -import com.gg.server.global.exception.custom.NotExistException; - -public class KakaoOauth2AlreadyExistException extends InvalidParameterException { - public KakaoOauth2AlreadyExistException() { - super("kakao user already exists", ErrorCode.KAKAO_OAUTH2_DUPLICATE); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2NotFoundException.java b/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2NotFoundException.java deleted file mode 100644 index bd53b5ba5..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/KakaoOauth2NotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class KakaoOauth2NotFoundException extends NotExistException { - public KakaoOauth2NotFoundException() { - super("Kakao oauth2 is not found", ErrorCode.KAKAO_OAUTH2_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/TokenNotValidException.java b/src/main/java/com/gg/server/domain/user/exception/TokenNotValidException.java deleted file mode 100644 index 29f9cb4f3..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/TokenNotValidException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.AuthenticationException; - -public class TokenNotValidException extends AuthenticationException { - public TokenNotValidException() { - super("Authentication error", ErrorCode.UNAUTHORIZED); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java b/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java deleted file mode 100644 index 3e3ce132e..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserAlreadyAttendanceException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.DuplicationException; - -public class UserAlreadyAttendanceException extends DuplicationException { - public UserAlreadyAttendanceException() { - super("์ด๋ฏธ ์ถœ์„ํ•œ ์œ ์ €์ž…๋‹ˆ๋‹ค.", ErrorCode.USER_ALREADY_ATTENDANCE); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserImageLargeException.java b/src/main/java/com/gg/server/domain/user/exception/UserImageLargeException.java deleted file mode 100644 index fa68d2f27..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserImageLargeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class UserImageLargeException extends FileException { - public UserImageLargeException() { - super("์ด๋ฏธ์ง€ ํŒŒ์ผ 50KB ์ดˆ๊ณผ", ErrorCode.USER_IMAGE_TOO_LARGE); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java b/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java deleted file mode 100644 index b7e8b8598..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserImageNullException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class UserImageNullException extends FileException { - public UserImageNullException() { - super("์ด๋ฏธ์ง€ ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.USER_IMAGE_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserImageTypeException.java b/src/main/java/com/gg/server/domain/user/exception/UserImageTypeException.java deleted file mode 100644 index 328cf4d42..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserImageTypeException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.FileException; - -public class UserImageTypeException extends FileException { - public UserImageTypeException() { - super("์ด๋ฏธ์ง€ ํƒ€์ž…์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค", ErrorCode.USER_IMAGE_WRONG_TYPE); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserNotFoundException.java b/src/main/java/com/gg/server/domain/user/exception/UserNotFoundException.java deleted file mode 100644 index 5748340d7..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserNotFoundException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.NotExistException; - -public class UserNotFoundException extends NotExistException { - public UserNotFoundException() { - super("ํ•ด๋‹น ์œ ์ €๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.", ErrorCode.USER_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java b/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java deleted file mode 100644 index c1c40abea..000000000 --- a/src/main/java/com/gg/server/domain/user/exception/UserTextColorException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.domain.user.exception; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; - -public class UserTextColorException extends CustomRuntimeException { - public UserTextColorException() { - super("user text color code is not valid", ErrorCode.USER_TEXT_COLOR_WRONG_TYPE); - } -} diff --git a/src/main/java/com/gg/server/domain/user/service/UserAuthenticationService.java b/src/main/java/com/gg/server/domain/user/service/UserAuthenticationService.java deleted file mode 100644 index b30a7aa58..000000000 --- a/src/main/java/com/gg/server/domain/user/service/UserAuthenticationService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.domain.user.exception.TokenNotValidException; -import com.gg.server.global.security.jwt.repository.JwtRedisRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class UserAuthenticationService { - private final JwtRedisRepository jwtRedisRepository; - private final AuthTokenProvider tokenProvider; - - public String regenerate(String refreshToken) { - Long userId = jwtRedisRepository.getUserIdFromRefToken(refreshToken); - if (userId == null) - throw new TokenNotValidException(); - return tokenProvider.createToken(userId); - } -} diff --git a/src/main/java/com/gg/server/domain/user/service/UserCoinService.java b/src/main/java/com/gg/server/domain/user/service/UserCoinService.java deleted file mode 100644 index 58fcf7407..000000000 --- a/src/main/java/com/gg/server/domain/user/service/UserCoinService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.admin.feedback.dto.FeedbackAdminResponseDto; -import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; -import com.gg.server.domain.coin.data.CoinHistory; -import com.gg.server.domain.coin.data.CoinHistoryRepository; -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.CoinHistoryResponseDto; -import com.gg.server.domain.user.dto.UserCoinHistoryListResponseDto; -import com.gg.server.domain.user.dto.UserCoinResponseDto; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@Service -public class UserCoinService { - private final UserRepository userRepository; - private final CoinHistoryRepository coinHistoryRepository; - - @Transactional(readOnly = true) - public UserCoinResponseDto getUserCoin(String intraId) { - int userCoin = userRepository.findByIntraId(intraId).orElseThrow(() -> new UserNotFoundException()).getGgCoin(); - - return new UserCoinResponseDto(userCoin); - } - - @Transactional(readOnly = true) - public UserCoinHistoryListResponseDto getUserCoinHistory(Pageable pageable, String intraId) { - User user = userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - - Page coinHistories = coinHistoryRepository.findAllByUserOrderByIdDesc(user, pageable); - Page coinHistoryResponseDtos = coinHistories.map(CoinHistoryResponseDto::new); - UserCoinHistoryListResponseDto responseDto = new UserCoinHistoryListResponseDto(coinHistoryResponseDtos.getContent(), - coinHistoryResponseDtos.getTotalPages()); - - return responseDto; - } -} diff --git a/src/main/java/com/gg/server/domain/user/service/UserFindService.java b/src/main/java/com/gg/server/domain/user/service/UserFindService.java deleted file mode 100644 index 59515de0f..000000000 --- a/src/main/java/com/gg/server/domain/user/service/UserFindService.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -public class UserFindService { - private final UserRepository userRepository; - private final SeasonFindService seasonFindService; - private final RankRedisRepository rankRedisRepository; - - @Transactional(readOnly = true) - public User findUserById(Long userId) { - return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - } - - @Transactional(readOnly = true) - public User findByIntraId(String intraId){ - return userRepository.findByIntraId(intraId).orElseThrow(UserNotFoundException::new); - } - - @Transactional(readOnly = true) - public String getUserStatusMessage(User targetUser) { - Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); - try{ - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, targetUser.getId()); - return userRank.getStatusMessage(); - }catch (RedisDataNotFoundException e){ - return ""; - } - } -} diff --git a/src/main/java/com/gg/server/domain/user/service/UserService.java b/src/main/java/com/gg/server/domain/user/service/UserService.java deleted file mode 100644 index 619dec023..000000000 --- a/src/main/java/com/gg/server/domain/user/service/UserService.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.gg.server.domain.user.service; - -import com.gg.server.domain.coin.service.CoinHistoryService; -import com.gg.server.domain.coin.service.UserCoinChangeService; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.pchange.exception.PChangeNotExistException; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.rank.service.RankFindService; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.data.ReceiptRepository; -import com.gg.server.domain.receipt.exception.ReceiptNotFoundException; -import com.gg.server.domain.receipt.type.ItemStatus; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.data.UserImageRepository; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.*; -import com.gg.server.domain.user.exception.*; -import com.gg.server.domain.user.type.*; -import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; -import com.gg.server.global.utils.ExpLevelCalculator; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class UserService { - - private final UserFindService userFindService; - private final UserRepository userRepository; - private final NotiRepository notiRepository; - private final GameRepository gameRepository; - private final RankRedisRepository rankRedisRepository; - private final SeasonFindService seasonFindService; - private final PChangeRepository pChangeRepository; - private final RankFindService rankFindService; - private final RedisMatchUserRepository redisMatchUserRepository; - private final UserCoinChangeService userCoinChangeService; - private final CoinHistoryService coinHistoryService; - private final ReceiptRepository receiptRepository; - private final AsyncNewUserImageUploader asyncNewUserImageUploader; - private final UserImageRepository userImageRepository; - private final ItemService itemService; - private final TierRepository tierRepository; - - /** - * @param intraId - * @return intraId๊ฐ€ ํฌํ•จ๋œ ์œ ์ €๋“ค์˜ intraId๋ฅผ ํŽ˜์ด์ง• ๊ด€๊ณ„์—†์ด ์ตœ๋Œ€ 5๊ฐœ๊นŒ์ง€ ๊ฒ€์ƒ‰ํ•˜์—ฌ List๋กœ return - */ - @Transactional(readOnly = true) - public List findByPartOfIntraId(String intraId) { - Pageable pageable = PageRequest.of(0, 5, Sort.by("intraId").ascending()); - Page pageUsers = userRepository.findByIntraIdContains(pageable, intraId); - return pageUsers.getContent().stream().map(user -> user.getIntraId()) - .collect(Collectors.toList()); - } - - /** - * @param user - event: - * - null โ†’ ๋กœ๊ทธ์ธ ์œ ์ €๊ฐ€ ์žกํžŒ ๋งค์นญ์ด ํ•˜๋‚˜๋„ ์—†์„ ๋•Œ - * - match โ†’ ๋งค์นญ์€ ๋˜์—ˆ์œผ๋‚˜ ๊ฒŒ์ž„์‹œ์ž‘ ์ „์ผ ๋•Œ or ๋งค์นญ์ค‘์ธ ๊ฒฝ์šฐ - * - game โ†’ ์œ ์ €๊ฐ€ ๊ฒŒ์ž„์ด ์žกํ˜”๊ณ  ํ˜„์žฌ ๊ฒŒ์ž„์ค‘์ธ ๊ฒฝ์šฐ - *

- * - currentMatchMode - * - normal - * - rank - * - null -> ๋งค์นญ์ด ์•ˆ์žกํ˜”์„ ๋•Œ or ๊ฒŒ์ž„ ์ „ - */ - @Transactional() - public UserLiveResponseDto getUserLiveDetail(UserDto user) { - int notiCnt = notiRepository.countNotCheckedNotiByUser(user.getId()); - Optional optionalGame = gameRepository.getLatestGameByUser(user.getId()); - int userMatchCnt = redisMatchUserRepository.countMatchTime(user.getId()); - if (optionalGame.isPresent()) { - Game game = optionalGame.get(); - if (game.getStatus() == StatusType.LIVE || game.getStatus() == StatusType.WAIT) - return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); - else if (game.getStatus() == StatusType.END) { - PChange userPChange = pChangeRepository.findPChangeByUserIdAndGameId(user.getId(), game.getId()).orElseThrow(() -> new PChangeNotExistException()); - if (!userPChange.getIsChecked()) { - userPChange.checkPChange(); - return new UserLiveResponseDto(notiCnt, "game", game.getMode(), game.getId()); - } - } - - if (game.getStatus() == StatusType.BEFORE) - return new UserLiveResponseDto(notiCnt, "match", null, null); - } - if (userMatchCnt > 0) { - return new UserLiveResponseDto(notiCnt, "match", null, null); - } - return new UserLiveResponseDto(notiCnt, null, null, null); - } - - @Transactional(readOnly = true) - public UserDetailResponseDto getUserDetail(String targetUserIntraId) { - User targetUser = userFindService.findByIntraId(targetUserIntraId); - String statusMessage = userFindService.getUserStatusMessage(targetUser); - Tier tier; - try{ - tier = rankFindService.findByUserIdAndSeasonId(targetUser.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); - } catch (RankNotFoundException e) { - tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - } - return new UserDetailResponseDto(targetUser, statusMessage, tier); - } - - @Transactional - public void updateUser(RacketType racketType, String statusMessage, SnsType snsNotiOpt, String intraId) { - User user = userFindService.findByIntraId(intraId); - Season currentSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - updateRedisRankStatusMessage(statusMessage, user, currentSeason); - updateRankTableStatusMessage(user.getId(), statusMessage, currentSeason.getId()); - user.updateTypes(racketType, snsNotiOpt); - } - - private void updateRankTableStatusMessage(Long userId, String statusMessage, Long seasonId) { - Rank rank = rankFindService.findByUserIdAndSeasonId(userId, seasonId); - rank.setStatusMessage(statusMessage); - } - - private void updateRedisRankStatusMessage(String statusMessage, User user, Season currentSeason) { - String hashKey = RedisKeyManager.getHashKey(currentSeason.getId()); - - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); - userRank.setStatusMessage(statusMessage); - rankRedisRepository.updateRankData(hashKey, user.getId(), userRank); - } - - /** - * @param intraId - * @param seasonId seasonId == 0 -> current season, else -> ํ•ด๋‹น Id๋ฅผ ๊ฐ€์ง„ season์˜ ๋ฐ์ดํ„ฐ - *

- * ๊ธฐ์กด ์ฟผ๋ฆฌ - * @return ์œ ์ €์˜ ์ตœ๊ทผ 10๊ฐœ์˜ ๋žญํฌ ๊ฒฝ๊ธฐ ๊ธฐ๋ก - * @Query(nativeQuery = true, value = "SELECT * FROM pchange " + - * "where game_id in (SELECT id FROM game where season = :season and mode = :mode ) " + - * "AND user_id = :intraId ORDER BY id Desc limit :limit") - * -> Limit์—๋Š” 10์ด ๊ธฐ๋ณธ์œผ๋กœ ๋“ค์–ด๊ฐ - */ - @Transactional(readOnly = true) - public UserHistoryResponseDto getUserHistory(String intraId, Long seasonId) { - Season season; - if (seasonId == 0) { - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - } else { - season = seasonFindService.findSeasonById(seasonId); - } - List pChanges = pChangeRepository.findPChangesHistory(intraId, season.getId()); - List historyData = pChanges.stream().map(UserHistoryData::new).collect(Collectors.toList()); - Collections.reverse(historyData); - return new UserHistoryResponseDto(historyData); - } - - /** - * @param targetUserIntraId - * @param seasonId seasonId == 0 -> current season, else -> ํ•ด๋‹น Id๋ฅผ ๊ฐ€์ง„ season์˜ ๋ฐ์ดํ„ฐ - * @return - */ - @Transactional(readOnly = true) - public UserRankResponseDto getUserRankDetail(String targetUserIntraId, Long seasonId) { - Season season; - if (seasonId == 0) { - season = seasonFindService.findCurrentSeason(LocalDateTime.now()); - } else { - season = seasonFindService.findSeasonById(seasonId); - } - String ZSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - User user = userFindService.findByIntraId(targetUserIntraId); - try { - Long userRanking = rankRedisRepository.getRankInZSet(ZSetKey, user.getId()); - userRanking += 1; - RankRedis userRank = rankRedisRepository.findRankByUserId(hashKey, user.getId()); - double winRate = (double) (userRank.getWins() * 10000 / (userRank.getWins() + userRank.getLosses())) / 100; - return new UserRankResponseDto(userRanking.intValue(), userRank.getPpp(), userRank.getWins(), userRank.getLosses(), winRate); - } catch (RedisDataNotFoundException ex) { - return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); - } catch (ArithmeticException ex2) { - return new UserRankResponseDto(-1, season.getStartPpp(), 0, 0, 0); - } - } - - public User getUser(Long userId) { - return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - } - - @Transactional - public void deleteKakaoId(Long userId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - user.updateKakaoId(null); - } - - @Transactional(readOnly = true) - public UserImageResponseDto getRankedUserImagesByPPP(Long seasonId) { - Season targetSeason; - - if (seasonId == 0) - targetSeason = seasonFindService.findCurrentSeason(LocalDateTime.now()); - else - targetSeason = seasonFindService.findSeasonById(seasonId); - try { - String zSetKey = RedisKeyManager.getZSetKey(targetSeason.getId()); - List userIds = rankRedisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 2); - List users = userRepository.findUsersByIdIn(userIds); - List userImages = new ArrayList<>(); - userIds.forEach(userId -> { - User user = users.stream().filter(u -> u.getId().equals(userId)).findFirst().orElseThrow(UserNotFoundException::new); - Tier tier = rankFindService.findByUserIdAndSeasonId(user.getId(), targetSeason.getId()).getTier(); - userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), user.getEdge(), tier.getImageUri())); - }); - return new UserImageResponseDto(userImages); - } catch (RedisDataNotFoundException ex) { - return new UserImageResponseDto(new ArrayList<>()); - } - } - - public UserImageResponseDto getRankedUserImagesByExp(PageRequest pageRequest) { - List users = userRepository.findAll(pageRequest).getContent(); - List userImages = new ArrayList<>(); - for (User user : users) { - Tier tier = rankFindService.findByUserIdAndSeasonId(user.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); - userImages.add(new UserImageDto(user.getIntraId(), user.getImageUri(), user.getEdge(), tier.getImageUri())); - } - return new UserImageResponseDto(userImages); - } - - @Transactional - public UserAttendanceResponseDto attendUser(Long userId) { - User user = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - - int plus = userCoinChangeService.addAttendanceCoin(user); - - return new UserAttendanceResponseDto(user.getGgCoin() - plus, user.getGgCoin(), plus); - } - - @Transactional - public UserNormalDetailResponseDto getUserNormalDetail(UserDto user) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - Boolean isAdmin = user.getRoleType() == RoleType.ADMIN; - Boolean isAttended = coinHistoryService.hasAttendedToday(loginUser); - Integer level = ExpLevelCalculator.getLevel(user.getTotalExp()); - Tier tier; - try { - tier = rankFindService.findByUserIdAndSeasonId(user.getId(), seasonFindService.findCurrentSeason(LocalDateTime.now()).getId()).getTier(); - } catch (RankNotFoundException ex) { - // ์นด์นด์˜ค ์œ ์ €๋‚˜ Rank๊ฐ€ ์—†๋Š” ์œ ์ € - tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - } - return new UserNormalDetailResponseDto(user.getIntraId(), loginUser.getImageUri(), isAdmin, isAttended, loginUser.getEdge(), tier.getName(), tier.getImageUri(), level); - } - - @Transactional() - public void updateTextColor(Long userId, UserTextColorDto textColorDto) { - String textColor = textColorDto.getTextColor(); - Receipt receipt = receiptRepository.findById(textColorDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); - User loginUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new); - - if (!UserTextColorCheckService.check(textColor)) - throw new UserTextColorException(); - - itemService.checkItemType(receipt, ItemType.TEXT_COLOR); - itemService.checkItemOwner(loginUser, receipt); - itemService.checkItemStatus(receipt); - - loginUser.updateTextColor(textColor); - receipt.updateStatus(ItemStatus.USED); - } - - @Transactional - public String updateEdge(UserDto user, UserEdgeDto userEdgeDto) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - EdgeType edgeType = EdgeType.getRandomEdgeType(); - Receipt receipt = receiptRepository.findById(userEdgeDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); - - itemService.checkItemType(receipt, ItemType.EDGE); - itemService.checkItemOwner(loginUser, receipt); - itemService.checkItemStatus(receipt); - - loginUser.updateEdge(edgeType); - receipt.updateStatus(ItemStatus.USED); - - return edgeType.toString(); - } - - @Transactional - public String updateBackground(UserDto user, UserBackgroundDto userBackgroundDto) { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - BackgroundType backgroundType = BackgroundType.getRandomBackgroundType(); - Receipt receipt = receiptRepository.findById(userBackgroundDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); - - itemService.checkItemType(receipt, ItemType.BACKGROUND); - itemService.checkItemOwner(loginUser, receipt); - itemService.checkItemStatus(receipt); - - loginUser.updateBackground(backgroundType); - receipt.updateStatus(ItemStatus.USED); - - return backgroundType.toString(); - } - - @Transactional - public void updateUserProfileImage(UserDto user, UserProfileImageRequestDto userProfileImageRequestDto, MultipartFile userImageFile) throws IOException { - User loginUser = userRepository.findById(user.getId()).orElseThrow(UserNotFoundException::new); - Receipt receipt = receiptRepository.findById(userProfileImageRequestDto.getReceiptId()).orElseThrow(ReceiptNotFoundException::new); - - itemService.checkItemType(receipt, ItemType.PROFILE_IMAGE); - itemService.checkItemOwner(loginUser, receipt); - itemService.checkItemStatus(receipt); - - if (userImageFile == null) - throw new UserImageNullException(); - if (userImageFile.getSize() > 50000) { - throw new UserImageLargeException(); - } else if (userImageFile.getContentType() == null || !userImageFile.getContentType().equals("image/jpeg")) { - throw new UserImageTypeException(); - } - - UserImage userImage = userImageRepository.findTopByUserAndIsCurrentIsTrueOrderByIdDesc(loginUser).orElseThrow(UserImageNullException::new); - userImage.updateIsCurrent(); - asyncNewUserImageUploader.update(user.getIntraId(), userImageFile); - receipt.updateStatus(ItemStatus.USED); - } -} diff --git a/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java b/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java deleted file mode 100644 index 278cc6e5f..000000000 --- a/src/main/java/com/gg/server/domain/user/service/UserTextColorCheckService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.gg.server.domain.user.service; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class UserTextColorCheckService { - public static boolean check(String textColor) { - if (textColor == null) - return false; - if (textColor.length() != 7) - return false; - if (textColor.charAt(0) != '#') - return false; - for (int i = 1; i < 7; i++) { - char c = textColor.charAt(i); - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) - return false; - } - return true; - } -} diff --git a/src/main/java/com/gg/server/domain/user/type/BackgroundType.java b/src/main/java/com/gg/server/domain/user/type/BackgroundType.java deleted file mode 100644 index 01629e6fc..000000000 --- a/src/main/java/com/gg/server/domain/user/type/BackgroundType.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.domain.user.type; - -import lombok.RequiredArgsConstructor; - -import java.util.Random; - -@RequiredArgsConstructor -public enum BackgroundType { - BASIC(0), - COLOR1(1), - COLOR2(2), - COLOR3(3), - COLOR4(4), - COLOR5(5), - COLOR6(6), - COLOR7(7), - COLOR8(8), - COLOR9(9), - COLOR10(10), - COLOR11(11), - COLOR12(12), - COLOR13(13), - COLOR14(14), - COLOR15(15), - COLOR16(16); - - private final Integer code; - - public static BackgroundType getRandomBackgroundType() { - Random random = new Random(); - int tierInt = random.nextInt(100); - int colorInt; - - if (tierInt <= 50) - colorInt = random.nextInt(100) % 4 + 1; - else if (tierInt <= 70) - colorInt = (random.nextInt(99) % 3) + 5; - else if (tierInt <= 85) - colorInt = (random.nextInt(99) % 3) + 8; - else if (tierInt <= 95) - colorInt = (random.nextInt(99) % 3) + 11; - else - colorInt = (random.nextInt(99) % 3) + 14; - - return BackgroundType.values()[colorInt]; - } - - public static BackgroundType of(String code) { - return BackgroundType.valueOf(code); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/type/EdgeType.java b/src/main/java/com/gg/server/domain/user/type/EdgeType.java deleted file mode 100644 index e6446216f..000000000 --- a/src/main/java/com/gg/server/domain/user/type/EdgeType.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.domain.user.type; - -import lombok.RequiredArgsConstructor; - -import java.util.Random; - -@RequiredArgsConstructor -public enum EdgeType { - BASIC(0), - COLOR1(1), - COLOR2(2), - COLOR3(3), - COLOR4(4), - COLOR5(5), - COLOR6(6), - COLOR7(7), - COLOR8(8), - COLOR9(9), - COLOR10(10), - COLOR11(11), - COLOR12(12), - COLOR13(13), - COLOR14(14), - COLOR15(15), - COLOR16(16); - - private final Integer code; - - public static EdgeType getRandomEdgeType() { - Random random = new Random(); - int tierInt = random.nextInt(100); - int colorInt; - - if (tierInt <= 50) - colorInt = random.nextInt(100) % 4 + 1; - else if (tierInt <= 70) - colorInt = (random.nextInt(99) % 3) + 5; - else if (tierInt <= 85) - colorInt = (random.nextInt(99) % 3) + 8; - else if (tierInt <= 95) - colorInt = (random.nextInt(99) % 3) + 11; - else - colorInt = (random.nextInt(99) % 3) + 14; - - return EdgeType.values()[colorInt]; - } - - public static EdgeType of(String code) { - return EdgeType.valueOf(code); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/domain/user/type/OauthType.java b/src/main/java/com/gg/server/domain/user/type/OauthType.java deleted file mode 100644 index ad1fcdaa9..000000000 --- a/src/main/java/com/gg/server/domain/user/type/OauthType.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.gg.server.domain.user.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import java.util.Arrays; -import java.util.Locale; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum OauthType { - KAKAO("kakao"), - FORTYTWO("fortyTwo"), - BOTH("both"); - - private final String code; - - @JsonCreator - public static OauthType getEnumFromValue(String value) { - for(OauthType e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } - - public static OauthType of(RoleType roleType, Long kakaoId) { - if (kakaoId == null) { - return OauthType.FORTYTWO; - } - if (roleType.equals(RoleType.GUEST)) { - return OauthType.KAKAO; - } - return OauthType.BOTH; - } -} diff --git a/src/main/java/com/gg/server/domain/user/type/RacketType.java b/src/main/java/com/gg/server/domain/user/type/RacketType.java deleted file mode 100644 index c7d32a857..000000000 --- a/src/main/java/com/gg/server/domain/user/type/RacketType.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gg.server.domain.user.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Locale; - -@Getter -@RequiredArgsConstructor -public enum RacketType { - PENHOLDER("PENHOLDER"), - SHAKEHAND("SHAKEHAND"), - DUAL("DUAL"), - NONE("NONE"); - - private final String code; - - @JsonCreator - public static RacketType getEnumFromValue(String value) { - for(RacketType e : values()) { - if(e.code.equals(value)) { - return e; - } - else if (e.code.toUpperCase(Locale.ROOT).equals(value.toUpperCase(Locale.ROOT))) { - return e; - } - } - return null; - } - -} diff --git a/src/main/java/com/gg/server/domain/user/type/RoleType.java b/src/main/java/com/gg/server/domain/user/type/RoleType.java deleted file mode 100644 index 7a64a963f..000000000 --- a/src/main/java/com/gg/server/domain/user/type/RoleType.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.user.type; - -import com.fasterxml.jackson.annotation.JsonCreator; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -@Getter -@RequiredArgsConstructor -public enum RoleType { - - ADMIN("ROLE_ADMIN", "๊ด€๋ฆฌ์ž"), - USER("ROLE_USER", "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž"), - GUEST("ROLE_GUEST", "๊ฒŒ์ŠคํŠธ"); - - private final String key; - private final String displayName; - - public static RoleType of(String key) { - return Arrays.stream(RoleType.values()) - .filter(r -> r.getKey().equals(key)) - .findAny() - .orElse(USER); - } -} - diff --git a/src/main/java/com/gg/server/domain/user/type/SnsType.java b/src/main/java/com/gg/server/domain/user/type/SnsType.java deleted file mode 100644 index fe08f3652..000000000 --- a/src/main/java/com/gg/server/domain/user/type/SnsType.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.user.type; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -@Getter -@RequiredArgsConstructor -public enum SnsType { - - NONE(0, "NONE"), - SLACK(1, "SLACK"), - EMAIL(2, "EMAIL"), - BOTH(3, "BOTH"); - - private final Integer value; - private final String code; - - public static SnsType of(String code) { - return Arrays.stream(SnsType.values()) - .filter(snsType-> snsType.getCode().equals(code)) - .findAny() - .orElse(SLACK); - } - -} diff --git a/src/main/java/com/gg/server/global/config/AWSConfig.java b/src/main/java/com/gg/server/global/config/AWSConfig.java deleted file mode 100644 index d74fd5d1d..000000000 --- a/src/main/java/com/gg/server/global/config/AWSConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.global.config; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class AWSConfig { - - @Value("${cloud.aws.credentials.accessKey}") - private String accessKey; - - @Value("${cloud.aws.credentials.secretKey}") - private String secretKey; - - @Value("${cloud.aws.region.static}") - private String region; - - @Bean - public AmazonS3 amazonS3Client() { - AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); - - return AmazonS3ClientBuilder - .standard() - .withCredentials(new AWSStaticCredentialsProvider(credentials)) - .withRegion(region) - .build(); - } -} diff --git a/src/main/java/com/gg/server/global/config/AsyncConfiguration.java b/src/main/java/com/gg/server/global/config/AsyncConfiguration.java deleted file mode 100644 index 7d476e798..000000000 --- a/src/main/java/com/gg/server/global/config/AsyncConfiguration.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gg.server.global.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.util.concurrent.Executor; - -@Configuration -@EnableAsync -public class AsyncConfiguration implements AsyncConfigurer { - - private static Logger logger = LoggerFactory.getLogger(AsyncConfiguration.class); - - @Override - @Bean(name = "asyncExecutor") - public Executor getAsyncExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setCorePoolSize(5); - executor.setMaxPoolSize(20); - executor.setQueueCapacity(100); - executor.setThreadNamePrefix("MailExecutor-"); - executor.initialize(); - return executor; - } - - @Override - public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { - return (ex, method, params) -> - logger.error("Exception handler for async method '" + method.toGenericString() - + "' threw unexpected exception itself", ex); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/config/ConstantConfig.java b/src/main/java/com/gg/server/global/config/ConstantConfig.java deleted file mode 100644 index 858a18adb..000000000 --- a/src/main/java/com/gg/server/global/config/ConstantConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.global.config; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * ConstantConfig. - * - *

- * yml ํŒŒ์ผ์— ์ •์˜๋œ ๋ณ€์ˆ˜๋“ค์„ ๊ฐ€์ ธ์˜ค๋Š” ํด๋ž˜์Šค. - *

- * - */ -@Component -@Getter -public class ConstantConfig { - @Value("${constant.allowedMinimalStartDays}") - private int allowedMinimalStartDays; - - @Value("${constant.tournamentSchedule}") - private String tournamentSchedule; -} diff --git a/src/main/java/com/gg/server/global/config/RedisConfig.java b/src/main/java/com/gg/server/global/config/RedisConfig.java deleted file mode 100644 index 5efd0d4d2..000000000 --- a/src/main/java/com/gg/server/global/config/RedisConfig.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.gg.server.global.config; - -import java.time.Duration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.cache.RedisCacheConfiguration; -import org.springframework.data.redis.cache.RedisCacheManager; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; -import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.RedisSerializationContext; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import org.springframework.session.data.redis.config.ConfigureRedisAction; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -/** - * Redis ์„ค์ • - */ -@Configuration -@EnableCaching -@EnableRedisRepositories -@EnableTransactionManagement -public class RedisConfig { - - /** - * Redis Host - */ - @Value("${spring.redis.host}") - private String host; - - /** - * Redis Port - */ - @Value("${spring.redis.port}") - private int port; - - /** - * Redis Connection Factory - *

- * redisConnectionFactory() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด RedisConnectionFactory ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ํ†ตํ•ด RedisTemplate ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ํ•ด๋‹น - * ๊ธฐ๋Šฅ์€ Spring Boot ์—์„œ ์ž๋™์œผ๋กœ ์ œ๊ณตํ•ด์ฃผ์ง€๋งŒ, RedisConnectionFactory ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•˜๊ธฐ ์œ„ํ•ด ์ง์ ‘ ์ƒ์„ฑ - * - * @return - */ - @Bean - public RedisConnectionFactory redisConnectionFactory() { - return new LettuceConnectionFactory(host, port); - } - - /** - * ์บ์‹œ ๊ด€๋ฆฌ์ž - *

- * RedisCacheManager ๋ฅผ ํ†ตํ•ด Redis ์— ๋Œ€ํ•œ ์บ์‹œ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ์บ์‹œ์˜ ๊ธฐ๋ณธ ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด RedisCacheConfiguration ์„ ์‚ฌ์šฉํ•œ๋‹ค. - * - * @param connectionFactory - * @return - */ - @Bean - public CacheManager gameCacheManager(RedisConnectionFactory connectionFactory) { - RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory( - redisConnectionFactory()); - RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig() - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer( - new GenericJackson2JsonRedisSerializer())) // Value Serializer ๋ณ€๊ฒฝ - .entryTtl(Duration.ofMinutes(30)); // ์บ์‹œ ์ˆ˜๋ช… - builder.cacheDefaults(configuration); - return builder.build(); - } - - - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { - final RedisTemplate redisTemplate = new RedisTemplate<>(); - - redisTemplate.setConnectionFactory(redisConnectionFactory); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - - redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer()); - redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); - redisTemplate.setEnableTransactionSupport(true); // <= - - return redisTemplate; - } - - /** - * StringRedisTemplate - *

- * StringRedisTemplate ์„ ํ†ตํ•ด Redis ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. - * - * @param redisTemplate - * @return - */ - @Bean - public ListOperations redisListTemplate(RedisTemplate redisTemplate) { - return redisTemplate.opsForList(); - } - - /** - * ConfigureRedisAction - *

- * Elasticache๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, CONFIG ๋ช…๋ น์–ด ์‚ฌ์šฉ์ด ์ œํ•œ๋จ์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ - * - * @return ConfigureRedisAction - */ - @Bean - public ConfigureRedisAction configureRedisAction() { - return ConfigureRedisAction.NO_OP; - } - -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/config/SwaggerConfig.java b/src/main/java/com/gg/server/global/config/SwaggerConfig.java deleted file mode 100644 index faced4d9c..000000000 --- a/src/main/java/com/gg/server/global/config/SwaggerConfig.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.gg.server.global.config; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import io.swagger.v3.oas.models.servers.Server; -import org.springdoc.core.GroupedOpenApi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class SwaggerConfig { - @Bean - public GroupedOpenApi group1() { - return GroupedOpenApi.builder() - .group("pingpong") - .pathsToMatch("/pingpong/**") - .packagesToScan("com.gg.server.domain") - .build(); - } - - @Bean - public GroupedOpenApi admin_group() { - return GroupedOpenApi.builder() - .group("pingpong admin") - .pathsToMatch("/pingpong/admin/**") - .build(); - } - - @Bean - public OpenAPI springShopOpenAPI() { - String jwtSchemeName = "jwtAuth"; - SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName); - Components components = new Components() - .addSecuritySchemes(jwtSchemeName, new SecurityScheme() - .name(jwtSchemeName) - .type(SecurityScheme.Type.HTTP) - .scheme("Bearer") - .bearerFormat("JWT")); - Server server = new Server(); - server.setUrl("/"); - server.setDescription("test Server url"); - return new OpenAPI() - .info(new Info().title("42GG V2 API") - .description("42GG ๋ฐฑ์—”๋“œ ํ”„๋กœ์ ํŠธ API ๋ช…์„ธ์„œ์ž…๋‹ˆ๋‹ค.") - .version("v2.0.0")) - .addServersItem(server) - .addSecurityItem(securityRequirement) - .components(components); - } -} diff --git a/src/main/java/com/gg/server/global/config/TimeZoneConfiguration.java b/src/main/java/com/gg/server/global/config/TimeZoneConfiguration.java deleted file mode 100644 index 1ee70313d..000000000 --- a/src/main/java/com/gg/server/global/config/TimeZoneConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.global.config; - -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; -import java.util.TimeZone; - -@Configuration -public class TimeZoneConfiguration { - - @PostConstruct - public void init() { - TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); - } -} diff --git a/src/main/java/com/gg/server/global/config/WebConfig.java b/src/main/java/com/gg/server/global/config/WebConfig.java deleted file mode 100644 index f7573f428..000000000 --- a/src/main/java/com/gg/server/global/config/WebConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gg.server.global.config; - -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.argumentresolver.LoginMemberArgumentResolver; -import com.gg.server.global.utils.querytracker.LoggingInterceptor; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import java.util.List; - -@Configuration -@RequiredArgsConstructor -public class WebConfig implements WebMvcConfigurer { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - private final LoggingInterceptor loggingInterceptor; - - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(new LoginMemberArgumentResolver(userRepository, tokenProvider)); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(loggingInterceptor); - } -} diff --git a/src/main/java/com/gg/server/global/dto/PageRequestDto.java b/src/main/java/com/gg/server/global/dto/PageRequestDto.java deleted file mode 100644 index 1a4a5ff9a..000000000 --- a/src/main/java/com/gg/server/global/dto/PageRequestDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.global.dto; - -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.validation.constraints.Min; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -public class PageRequestDto { - - @Min(value = 1, message = "page must be greater than 0") - @NotNull(message = "page ๋Š” ํ•„์ˆ˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.") - private Integer page; - - @Min(value = 1, message = "size must be greater than 0") - @Max(value = 30, message = "size must be less than 30") - private Integer size = 20; - - public PageRequestDto(Integer page, Integer size) { - this.page = page; - if (size == null) - this.size = 20; - else - this.size = size; - } -} diff --git a/src/main/java/com/gg/server/global/exception/ErrorCode.java b/src/main/java/com/gg/server/global/exception/ErrorCode.java deleted file mode 100644 index 799555552..000000000 --- a/src/main/java/com/gg/server/global/exception/ErrorCode.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.gg.server.global.exception; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public enum ErrorCode { - //common - NULL_POINT(500, "G100", "NULL POINT EXCEPTION"), - - //user - USER_NOT_FOUND(404, "UR100", "USER NOT FOUND"), - USER_IMAGE_NOT_FOUND(404, "UR200", "USER IMAGE NOT FOUND"), - USER_IMAGE_TOO_LARGE(413, "UR401", "USER IMAGE IS TOO LARGE"), - USER_IMAGE_WRONG_TYPE(415, "UR402", "USER IMAGE TYPE IS WRONG"), - KAKAO_OAUTH2_NOT_FOUND(404, "UR101", "KAKAO OAUTH2 NOT FOUND"), - KAKAO_OAUTH2_DUPLICATE(409, "UR300", "KAKAO OAUTH2 ALREADY EXIST"), - USER_TEXT_COLOR_WRONG_TYPE(401, "UR403", "USER TEXT COLOR CODE IS WRONG"), - USER_ALREADY_ATTENDANCE(409, "UR301", "USER ALREADY ATTENDANCE"), - - //announcement - ANNOUNCE_NOT_FOUND(404, "AN100", "ANNOUNCEMENT NOT FOUND"), - ANNOUNCE_DUPLICATE(409, "AN300", "ANNOUNCEMENT DUPLICATION"), - - //coinPolicy - CoinPolicy_NOT_FOUND(404, "CP100", "COINPOLICY NOT FOUND"), - - //coinHistory - COIN_HISTORY_NOT_FOUND(404, "CH100", "COIN HISTORY NOT FOUND"), - - //season - SEASON_NOT_FOUND(404, "SE100", "SEASON NOT FOUND"), - SEASON_FORBIDDEN(400, "SE500", "SEASON FORBIDDEN ERROR"), - SEASON_TIME_BEFORE(400, "SE501", "SEASON TIME BEFORE"), - - //slotmanagement - SLOTMANAGEMENT_NOT_FOUND(404, "SM100", "SLOTMANAGEMENT NOT FOUND"), - SLOTMANAGEMENT_FORBIDDEN(400, "SM500", "SLOTMANAGEMENT FORBIDDEN"), - - //rank - RANK_NOT_FOUND(404, "RK100", "RANK NOT FOUND"), - REDIS_RANK_NOT_FOUND(404, "RK101", "REDIS RANK NOT FOUND"), - RANK_UPDATE_FAIL(400, "RK200", "RANK UPDATE FAIL"), - - //tier - TIER_NOT_FOUND(404, "TR100", "TIER NOT FOUND"), - - //item - ITEM_NOT_FOUND(404, "IT100", "ITEM NOT FOUND"), - ITEM_TYPE_NOT_MATCHED(400, "IT200", "ITEM TYPE NOT MATCHED"), - ITEM_NOT_PURCHASABLE(400, "IT201", "ITEM NOT PURCHASABLE"), - INSUFFICIENT_GGCOIN(400,"IT202","INSUFFICIENT GGCOIN"), - GUEST_ROLE_PURCHASE_FORBIDDEN(403, "IT203", "GUEST ROLE USERS CANNOT PURCHASE ITEMS."), - GUEST_ROLE_GIFT_FORBIDDEN(403, "IT204", "GUEST ROLE USERS CANNOT GIFT ITEMS."), - ITEM_NOT_AVAILABLE(400, "IT205", "ITEM NOT AVAILABLE"), - ITEM_IMAGE_TOO_LARGE(413, "IT401", "ITEM IMAGE IS TOO LARGE"), - ITEM_IMAGE_WRONG_TYPE(415, "IT402", "ITEM IMAGE TYPE IS WRONG"), - - //receipt - RECEIPT_NOT_FOUND(404, "RC100", "RECEIPT NOT FOUND"), - RECEIPT_NOT_OWNER(403, "RC500", "RECEIPT NOT OWNER"), - RECEIPT_STATUS_NOT_MATCHED(400, "RC200", "RECEIPT STATUS NOT MATCHED"), - - //megaphone - MEGAPHONE_NOT_FOUND(404, "ME100", "MEGAPHONE NOT FOUND"), - MEGAPHONE_TIME(400, "ME200", "MEGAPHONE TIME"), - MEGAPHONE_CONTENT(400, "ME201", "MEGAPHONE CONTENT IS EMPTY"), - - /** Penalty **/ - PENALTY_NOT_FOUND(404, "PE100", "PENALTY NOT FOUND"), - REDIS_PENALTY_USER_NOT_FOUND(404, "PE101", "REDIS PENALTY USER NOT FOUND"), - PENALTY_EXPIRED(400, "PE200", "PENALTY EXPIRED"), - - /** team **/ - TEAM_ID_NOT_MATCH(400, "TM201", "TEAM id ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - TEAM_DUPLICATION(409, "TM202", "์ค‘๋ณต๋œ Team ์ด ํ•œ Game ์— ์กด์žฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), - TEAM_SIZE_EXCEED(500, "TM203", "๊ฒŒ์ž„ ์ตœ๋Œ€ Team ์˜ ์ˆ˜(2)๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค."), - TEAM_NOT_FOUND(404, "TM204", "TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - WINNING_TEAM_NOT_FOUND(404, "TM205", "WINNING TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - LOSING_TEAM_NOT_FOUND(404, "TM206", "LOSING TEAM์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - - - /** - * team_user - */ - TEAM_USER_ALREADY_EXIST(409, "TU201", "์ค‘๋ณต๋œ TEAM_USER"), - TEAM_USER_EXCEED(500, "TU202", "TeamUser ์ตœ๋Œ€ ์ธ์›์˜ ์ˆ˜(2)๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค."), - TEAM_USER_NOT_FOUND(404, "TU203", "TeamUser๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."), - - /** game **/ - GAME_DB_NOT_VALID(500, "GM201", "GAME DB NOT CONSISTENCY"), - SCORE_NOT_MATCHED(400, "GM202", "score ์ž…๋ ฅ์ด ๊ธฐ์กด๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค."), - GAME_NOT_FOUND(404, "GM101", "GAME ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - GAME_NOT_RECENTLY(400, "GM203", "๊ฐ€์žฅ ์ตœ๊ทผ ๊ฒŒ์ž„์ด ์•„๋‹™๋‹ˆ๋‹ค."), - GAME_DUPLICATION_EXCEPTION(409, "GM204", "GAME ALREADY EXISTS"), - GAME_STATUS_NOT_MATCHED(400, "GM205", "๊ฒŒ์ž„ ์ƒํƒœ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค."), - SCORE_ALREADY_ENTERED(400, "GM206", "์ ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ž…๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."), - SCORE_NOT_INVALID(400, "GM205", "score ์ž…๋ ฅ์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - GAME_NOT_TOURNAMENT(400, "GM206", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ด ์•„๋‹™๋‹ˆ๋‹ค."), - - /** match **/ - SLOT_ENROLLED(400, "MA300", "SLOT ALREADY ENROLLED"), - SLOT_COUNT_EXCEEDED(400, "MA301", "SLOT COUNT MORE THAN THREE"), - SLOT_NOT_FOUND(404, "MA100", "SLOT NOT FOUND"), - PENALTY_USER_ENROLLED(400, "MA302", "PENALTY USER ENROLLED"), - SLOT_PAST(400, "MA303", "PAST SLOT ENROLLED"), - MODE_INVALID(400, "MA200", "MODE INVALID"), - - /** Common **/ - INTERNAL_SERVER_ERR(500, "CM001","INTERNAL SERVER ERROR"), - NOT_FOUND(404, "CM002", "NOT FOUND"), - BAD_REQUEST(400, "CM003", "BAD REQUEST"), - UNAUTHORIZED(401, "CM004", "UNAUTHORIZED"), - METHOD_NOT_ALLOWED(405, "CM005", "METHOD NOT ALLOWED"), - PAGE_NOT_FOUND(404, "CM006", "PAGE NOT FOUND"), - VALID_FAILED(400, "CM007" , "Valid Test Failed."), - BAD_ARGU(400, "ARGUMENT-ERR-400", "์ž˜๋ชป๋œ argument ์ž…๋‹ˆ๋‹ค."), - UNREADABLE_HTTP_MESSAGE(400, "CM008", "์œ ํšจํ•˜์ง€ ์•Š์€ HTTP ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค."), - - //Feedback - FEEDBACK_NOT_FOUND(404, "FB100", "FB NOT FOUND"), - - /** - * PChange - **/ - PCHANGE_NOT_FOUND(404, "PC100", "PChange ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."), - - AWS_S3_ERR(500, "CL001", "AWS S3 Error"), - AWS_SERVER_ERR(500, "CL002", "AWS Error"), - - // SENDER - SLACK_USER_NOT_FOUND(404, "SL001", "fail to get slack user info"), - SLACK_CH_NOT_FOUND(404, "SL002", "fail to get user dm channel id"), - SLACK_JSON_PARSE_ERR(400, "SL002", "json parse error"), - SLACK_SEND_FAIL(400, "SL003","fail to send notification" ), - - // Tournament - TOURNAMENT_INVALID_TIME(400, "TN001", "์œ ํšจํ•œ ํ† ๋„ˆ๋จผํŠธ ๊ธฐ๊ฐ„์ด ์•„๋‹™๋‹ˆ๋‹ค."), - TOURNAMENT_CAN_NOT_UPDATE(403, "TN002", "ํ† ๋„ˆ๋จผํŠธ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†๋Š” ๊ธฐ๊ฐ„์ž…๋‹ˆ๋‹ค."), - TOURNAMENT_INVALID_SCORE(403, "TN003", "์Šค์ฝ”์–ด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), - TOURNAMENT_NOT_BEFORE(403, "TN004", "tournament status is not before"), - TOURNAMENT_NOT_LIVE(403, "TN005", "tournament status is not live"), - TOURNAMENT_GAME_CAN_NOT_CANCELED(403, "TN006", "์ง„ํ–‰์ค‘์ธ ํ† ๋„ˆ๋จผํŠธ์˜ ๊ฒŒ์ž„์€ ์ทจ์†Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."), - TOURNAMENT_NOT_FOUND(404, "TN007", "target tournament not found"), - TOURNAMENT_GAME_NOT_FOUND(404, "TN008", "tournament game not found"), - TOURNAMENT_NOT_PARTICIPANT(404, "TN009", "ํ† ๋„ˆ๋จผํŠธ์˜ ์‹ ์ฒญ์ž๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค."), - TOURNAMENT_USER_NOT_FOUND(404, "TN010", "target tournament user not found"), - TOURNAMENT_CONFLICT(409, "TN011", "tournament conflicted"), - TOURNAMENT_ALREADY_PARTICIPANT(409, "TN012", "์ด๋ฏธ ํ† ๋„ˆ๋จผํŠธ์˜ ์‹ ์ฒญ์ž ์ž…๋‹ˆ๋‹ค."), - TOURNAMENT_CONFLICT_GAME(409, "TN013", "ํ† ๋„ˆ๋จผํŠธ ๊ธฐ๊ฐ„ ๋‚ด ๋Œ€๊ธฐ์ค‘์ธ ๊ฒŒ์ž„์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค."), - TOURNAMENT_GAME_DUPLICATION(409, "TN014", "์ค‘๋ณต๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์ž…๋‹ˆ๋‹ค!"), - TOURNAMENT_USER_DUPLICATION(409, "TN015", "์ค‘๋ณต๋œ ํ† ๋„ˆ๋จผํŠธ ์œ ์ €์ž…๋‹ˆ๋‹ค!"), - TOURNAMENT_GAME_EXCEED(500, "TN016", "ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ตœ๋Œ€ ์‚ฌ์ด์ฆˆ๋ฅผ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค!"), - TOURNAMENT_IS_BEFORE(403, "TN017", "before์ธ ํ† ๋„ˆ๋จผํŠธ์—์„œ ์ ์ˆ˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") - ; - private final int status; - private final String errCode; - private String message; - - public void setMessage(String msg) { - this.message = msg; - } -} diff --git a/src/main/java/com/gg/server/global/exception/ErrorResponse.java b/src/main/java/com/gg/server/global/exception/ErrorResponse.java deleted file mode 100644 index fdf3f3fe6..000000000 --- a/src/main/java/com/gg/server/global/exception/ErrorResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.global.exception; - -import lombok.Getter; - -@Getter -public class ErrorResponse { - private int status; - private String message; - private String code; - - public ErrorResponse(ErrorCode errorCode) { - this.status = errorCode.getStatus(); - this.message = errorCode.getMessage(); - this.code = errorCode.getErrCode(); - } -} diff --git a/src/main/java/com/gg/server/global/exception/GlobalExceptionHandler.java b/src/main/java/com/gg/server/global/exception/GlobalExceptionHandler.java deleted file mode 100644 index fb049e3f9..000000000 --- a/src/main/java/com/gg/server/global/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.gg.server.global.exception; - -import com.gg.server.global.exception.custom.*; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.SdkClientException; -import lombok.extern.slf4j.Slf4j; -import org.springframework.dao.DataAccessException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.validation.BindException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; - -import java.time.format.DateTimeParseException; - -@Slf4j -@ControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler({BindException.class}) - public ResponseEntity validException(BindException ex) { - log.error("bind error", ex.getBindingResult().getAllErrors().get(0)); - ErrorCode ec = ErrorCode.VALID_FAILED; - ec.setMessage(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage()); - ErrorResponse response = new ErrorResponse(ec); - return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler({MethodArgumentTypeMismatchException.class}) - public ResponseEntity typeErrorException(MethodArgumentTypeMismatchException ex) { - log.error("type error", ex.getMessage()); - ErrorCode ec = ErrorCode.VALID_FAILED; - ec.setMessage(ex.getMessage()); - ErrorResponse response = new ErrorResponse(ec); - return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler({DBConsistencyException.class}) - public ResponseEntity dbConsistencyException(DBConsistencyException ex) { - log.error("db ์ •ํ•ฉ์„ฑ ์˜ค๋ฅ˜", ex); - return new ResponseEntity<>(new ErrorResponse(ex.getErrorCode()), HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler({NotExistException.class, PageNotFoundException.class}) - public ResponseEntity notFoundException(CustomRuntimeException ex) { - log.error("Not Exist", ex); - ErrorResponse response = new ErrorResponse(ex.getErrorCode()); - return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler({DuplicationException.class}) - public ResponseEntity duplicatedException(DuplicationException ex) { - log.error("Duplicated", ex); - return new ResponseEntity<>(new ErrorResponse(ex.getErrorCode()), HttpStatus.CONFLICT); - } - - @ExceptionHandler({ForbiddenException.class}) - public ResponseEntity forbiddenException(ForbiddenException ex) { - log.error("forbidden", ex); - ErrorResponse response = new ErrorResponse(ex.getErrorCode()); - return new ResponseEntity<>(response, HttpStatus.FORBIDDEN); - } - - @ExceptionHandler({CustomRuntimeException.class}) - public ResponseEntity validException(CustomRuntimeException ex) { - log.error("์˜ˆ์™ธ์ฒ˜๋ฆฌ๋œ ์—๋Ÿฌ", ex.getMessage(), ex.getErrorCode()); - ErrorResponse response = new ErrorResponse(ex.getErrorCode()); - return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(AuthenticationException.class) - public ResponseEntity authenticationException(AuthenticationException ex) { - log.error("authentication exception"); - ErrorResponse response = new ErrorResponse(ex.getErrorCode()); - return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); - } - @ExceptionHandler(AmazonServiceException.class) - protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle(AmazonServiceException ex) { - log.error("AmazonServiceException", ex); - ErrorResponse response = new ErrorResponse(ErrorCode.AWS_S3_ERR); - return new ResponseEntity<>(response, HttpStatus.valueOf(ex.getStatusCode())); - } - - @ExceptionHandler(SdkClientException.class) - protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle(SdkClientException ex) { - log.error("AmazonServiceException", ex.getMessage()); - ErrorResponse response = new ErrorResponse(ErrorCode.AWS_SERVER_ERR); - return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler({RuntimeException.class}) - public ResponseEntity runtimeException(RuntimeException ex) { - log.error("์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค.", ex); - ErrorResponse response = new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERR); - return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); - } - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - protected ResponseEntity httpRequestMethodNotSupportedExceptionHandle(HttpRequestMethodNotSupportedException ex) { - log.error("์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.", ex.getMethod()); - ErrorResponse response = new ErrorResponse(ErrorCode.METHOD_NOT_ALLOWED); - return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED); - } - @ExceptionHandler(Exception.class) - public ResponseEntity handleException(Exception ex) { - log.error("!!!!!! SERVER ERROR !!!!!!", ex.getMessage()); - ErrorResponse response = new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERR); - return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - protected ResponseEntity handleException(HttpMessageNotReadableException e) { - return ResponseEntity.badRequest().body(ErrorCode.UNREADABLE_HTTP_MESSAGE.getMessage()); - } - - @ExceptionHandler(MissingServletRequestParameterException.class) - protected ResponseEntity handleException(MissingServletRequestParameterException e) { - return ResponseEntity.badRequest().body(ErrorCode.BAD_ARGU.getMessage()); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/AuthenticationException.java b/src/main/java/com/gg/server/global/exception/custom/AuthenticationException.java deleted file mode 100644 index 0603a8e77..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/AuthenticationException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class AuthenticationException extends CustomRuntimeException { - private ErrorCode errorCode; - - public AuthenticationException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/BusinessException.java b/src/main/java/com/gg/server/global/exception/custom/BusinessException.java deleted file mode 100644 index 61d8c7ddc..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/BusinessException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class BusinessException extends CustomRuntimeException{ - public BusinessException(String message, ErrorCode errorCode) { - super(message, errorCode); - } - - public BusinessException(ErrorCode errorCode) { - super(errorCode.getMessage(), errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/CustomRuntimeException.java b/src/main/java/com/gg/server/global/exception/custom/CustomRuntimeException.java deleted file mode 100644 index fea25749c..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/CustomRuntimeException.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; -import lombok.Getter; - -@Getter -public class CustomRuntimeException extends RuntimeException { - private ErrorCode errorCode; - - public CustomRuntimeException(String message, ErrorCode errorCode) { - super(message); - this.errorCode = errorCode; - errorCode.setMessage(message); - } - - public CustomRuntimeException(ErrorCode errorCode) { - super(errorCode.getMessage()); - this.errorCode = errorCode; - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/DBConsistencyException.java b/src/main/java/com/gg/server/global/exception/custom/DBConsistencyException.java deleted file mode 100644 index 5fdd937e5..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/DBConsistencyException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; -import lombok.Getter; - -@Getter -public class DBConsistencyException extends CustomRuntimeException { - public DBConsistencyException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/DuplicationException.java b/src/main/java/com/gg/server/global/exception/custom/DuplicationException.java deleted file mode 100644 index c86f160e4..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/DuplicationException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class DuplicationException extends CustomRuntimeException{ - public DuplicationException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/ExpiredException.java b/src/main/java/com/gg/server/global/exception/custom/ExpiredException.java deleted file mode 100644 index 9931be239..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/ExpiredException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class ExpiredException extends CustomRuntimeException{ - public ExpiredException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/FileException.java b/src/main/java/com/gg/server/global/exception/custom/FileException.java deleted file mode 100644 index 4acf8d7ae..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/FileException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class FileException extends CustomRuntimeException{ - - public FileException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/ForbiddenException.java b/src/main/java/com/gg/server/global/exception/custom/ForbiddenException.java deleted file mode 100644 index bd2e5b10f..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/ForbiddenException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class ForbiddenException extends CustomRuntimeException{ - public ForbiddenException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/InvalidParameterException.java b/src/main/java/com/gg/server/global/exception/custom/InvalidParameterException.java deleted file mode 100644 index 763096c42..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/InvalidParameterException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; -import lombok.Getter; - -public class InvalidParameterException extends CustomRuntimeException{ - public InvalidParameterException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/NotExistException.java b/src/main/java/com/gg/server/global/exception/custom/NotExistException.java deleted file mode 100644 index 718ec0753..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/NotExistException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class NotExistException extends CustomRuntimeException { - private ErrorCode errorCode; - - public NotExistException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/PageNotFoundException.java b/src/main/java/com/gg/server/global/exception/custom/PageNotFoundException.java deleted file mode 100644 index 08b43d99b..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/PageNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class PageNotFoundException extends CustomRuntimeException{ - public PageNotFoundException(String message, ErrorCode errorCode) { - super(message, errorCode); - } - public PageNotFoundException() { - super(ErrorCode.PAGE_NOT_FOUND.getMessage(), ErrorCode.PAGE_NOT_FOUND); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/ParseException.java b/src/main/java/com/gg/server/global/exception/custom/ParseException.java deleted file mode 100644 index d945be9b0..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/ParseException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class ParseException extends CustomRuntimeException { - public ParseException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/exception/custom/SendException.java b/src/main/java/com/gg/server/global/exception/custom/SendException.java deleted file mode 100644 index 6707269c9..000000000 --- a/src/main/java/com/gg/server/global/exception/custom/SendException.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.exception.custom; - -import com.gg.server.global.exception.ErrorCode; - -public class SendException extends CustomRuntimeException { - public SendException(String message, ErrorCode errorCode) { - super(message, errorCode); - } -} diff --git a/src/main/java/com/gg/server/global/log/aspect/TraceAspect.java b/src/main/java/com/gg/server/global/log/aspect/TraceAspect.java deleted file mode 100644 index f98b1fae5..000000000 --- a/src/main/java/com/gg/server/global/log/aspect/TraceAspect.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.gg.server.global.log.aspect; - -import com.gg.server.global.log.domain.TraceStatus; -import com.gg.server.global.log.service.LogTrace; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; - -import java.util.Arrays; - -@Slf4j -@Aspect -@AllArgsConstructor -@Component -public class TraceAspect { - private final LogTrace logTrace; - - @Pointcut("execution(* com.gg.server.admin..*(..))") - public void allAdmin(){} - - @Pointcut("execution(* com.gg.server.domain..*(..))") - public void allDomain(){} - - @Pointcut("execution(* com.gg.server.global.security..*(..))") - public void securityDomain(){} - - @Pointcut("execution(* com.gg.server.global.scheduler..*(..))") - public void scheduler(){} - - @Around("(allAdmin() || allDomain() || scheduler()) && !securityDomain()") - public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable { - TraceStatus status = null; - MethodSignature method = (MethodSignature)joinPoint.getSignature(); - Object[] methodArgs = joinPoint.getArgs(); - try{ - status = logTrace.begin(method.getDeclaringType().getSimpleName() + "." + method.getName() + "(): arguments = " + Arrays.toString(methodArgs)); - Object result = joinPoint.proceed(); - logTrace.end(status); - return result; - } catch (Exception e) { - logTrace.exception(status, e); - throw e; - } - } -} diff --git a/src/main/java/com/gg/server/global/log/domain/TraceId.java b/src/main/java/com/gg/server/global/log/domain/TraceId.java deleted file mode 100644 index e5ef4195d..000000000 --- a/src/main/java/com/gg/server/global/log/domain/TraceId.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.global.log.domain; - -import java.util.UUID; - -public class TraceId { - private String id; - private int level; - - public TraceId() { - this.id = createId(); - this.level = 0; - } - - private TraceId(String id, int level) { - this.id = id; - this.level = level; - } - - private String createId() { - return UUID.randomUUID().toString().substring(0, 8); - } - - public TraceId createNextId() { - return new TraceId(id, level + 1); - } - - public TraceId createPreviousId() { - return new TraceId(id, level - 1); - } - - public boolean isFirstLevel() { - return level == 0; - } - - public String getId() { - return id; - } - - public int getLevel() { - return level; - } -} diff --git a/src/main/java/com/gg/server/global/log/domain/TraceStatus.java b/src/main/java/com/gg/server/global/log/domain/TraceStatus.java deleted file mode 100644 index 4382d990b..000000000 --- a/src/main/java/com/gg/server/global/log/domain/TraceStatus.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.global.log.domain; - -import lombok.Getter; - -@Getter -public class TraceStatus { - private TraceId traceId; - private Long startTimeMs; - private String message; - - public TraceStatus(TraceId traceId, Long startTimeMs, String message) { - this.traceId = traceId; - this.startTimeMs = startTimeMs; - this.message = message; - } -} diff --git a/src/main/java/com/gg/server/global/log/pointcut/TracePointcut.java b/src/main/java/com/gg/server/global/log/pointcut/TracePointcut.java deleted file mode 100644 index 324274334..000000000 --- a/src/main/java/com/gg/server/global/log/pointcut/TracePointcut.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.global.log.pointcut; - -import org.aspectj.lang.annotation.Pointcut; - -public class TracePointcut { - @Pointcut("execution(* com.gg.server.domain..*(..))") - public void allDomain(){} - - //ํƒ€์ž… ํŒจํ„ด์ด *Service - @Pointcut("execution(* *..*Service.*(..))") - public void allService(){} - - //allOrder && allService - @Pointcut("allDomain() && allService()") - public void orderAndService(){} -} diff --git a/src/main/java/com/gg/server/global/log/service/LogTrace.java b/src/main/java/com/gg/server/global/log/service/LogTrace.java deleted file mode 100644 index f8d4f1600..000000000 --- a/src/main/java/com/gg/server/global/log/service/LogTrace.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.gg.server.global.log.service; - -import com.gg.server.global.log.domain.TraceStatus; - -public interface LogTrace { - TraceStatus begin(String message); - void end(TraceStatus status); - void exception(TraceStatus status, Exception e); -} diff --git a/src/main/java/com/gg/server/global/log/service/ThreadLocalLogTrace.java b/src/main/java/com/gg/server/global/log/service/ThreadLocalLogTrace.java deleted file mode 100644 index a7bab66cd..000000000 --- a/src/main/java/com/gg/server/global/log/service/ThreadLocalLogTrace.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.gg.server.global.log.service; - -import com.gg.server.global.log.domain.TraceId; -import com.gg.server.global.log.domain.TraceStatus; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class ThreadLocalLogTrace implements LogTrace { - - private static final String START_PREFIX = "-->"; - private static final String COMPLETE_PREFIX = "<--"; - private static final String EX_PREFIX = " traceIdHolder = new ThreadLocal<>(); - - public TraceStatus begin(String message) { - syncTraceId(); - TraceId logId = traceIdHolder.get(); - Long startTimeMs = System.currentTimeMillis(); - log.info("[{}] {}{}", logId.getId(), addSpace(START_PREFIX, logId.getLevel()), message); - - return new TraceStatus(logId, startTimeMs, message); - } - - public void end(TraceStatus status) { - complete(status, null); - } - - public void exception(TraceStatus status, Exception e) { - if (status != null) { - complete(status, e); - } - } - - private void complete(TraceStatus status, Exception e) { - Long stopTimeMs = System.currentTimeMillis(); - long resultTimeMs = stopTimeMs - status.getStartTimeMs(); - TraceId traceId = status.getTraceId(); - if (e == null) { - log.info("[{}] {}{} time={}ms", traceId.getId(), addSpace(COMPLETE_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs); - } else { - log.info("[{}] {}{} time={}ms ex={}", traceId.getId(), addSpace(EX_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs, e.toString()); - } - - releaseTraceId(); - } - - private void syncTraceId() { - TraceId traceId = traceIdHolder.get(); - if (traceId == null) { - traceIdHolder.set(new TraceId()); - } else { - traceIdHolder.set(traceId.createNextId()); - } - } - - private void releaseTraceId() { - TraceId traceId = traceIdHolder.get(); - if (traceId.isFirstLevel()) { - traceIdHolder.remove();//destroy - } else { - traceIdHolder.set(traceId.createPreviousId()); - } - } - - private static String addSpace(String prefix, int level) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < level; i++) { - sb.append( (i == level - 1) ? "|" + prefix : "| "); - } - return sb.toString(); - } -} diff --git a/src/main/java/com/gg/server/global/scheduler/AbstractScheduler.java b/src/main/java/com/gg/server/global/scheduler/AbstractScheduler.java deleted file mode 100644 index b731faf9c..000000000 --- a/src/main/java/com/gg/server/global/scheduler/AbstractScheduler.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.gg.server.global.scheduler; - -import lombok.Getter; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.support.CronTrigger; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -public abstract class AbstractScheduler { - private ThreadPoolTaskScheduler scheduler; - @Getter - protected String cron; - @Getter - protected Integer interval; - - public abstract Runnable runnable(); - - public void renewScheduler() { - scheduler.shutdown(); - startScheduler(); - } - - protected void setCron(String cron) { - this.cron = cron; - } - - protected void setInterval(Integer interval) { - this.interval = interval; - } - - @PostConstruct - public void init() { - startScheduler(); - } - - @PreDestroy - public void destroy() { - scheduler.shutdown(); - } - - private void startScheduler() { - scheduler = new ThreadPoolTaskScheduler(); - scheduler.setPoolSize(4); - scheduler.initialize(); - scheduler.schedule(this.runnable(), new CronTrigger(cron)); - } -} diff --git a/src/main/java/com/gg/server/global/scheduler/GameStatusScheduler.java b/src/main/java/com/gg/server/global/scheduler/GameStatusScheduler.java deleted file mode 100644 index 5b152ceff..000000000 --- a/src/main/java/com/gg/server/global/scheduler/GameStatusScheduler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.global.scheduler; - -import com.gg.server.domain.game.service.GameStatusService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class GameStatusScheduler extends AbstractScheduler{ - private final GameStatusService gameStatusService; - - public GameStatusScheduler(GameStatusService gameStatusService) { - this.gameStatusService = gameStatusService; - this.setCron("0 */5 * * * *"); - } - - @Override - public Runnable runnable() { - return () -> { - log.info("GameStatusScheduler start"); - // BEFORE -> LIVE - gameStatusService.updateBeforeToLiveStatus(); - // LIVE -> WAIT - gameStatusService.updateLiveToWaitStatus(); - // imminent Noti - gameStatusService.imminentGame(); - }; - } -} diff --git a/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java b/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java deleted file mode 100644 index e814d0981..000000000 --- a/src/main/java/com/gg/server/global/scheduler/MegaphoneScheduler.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.global.scheduler; - -import com.gg.server.domain.megaphone.service.MegaphoneService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.time.LocalDate; - -@Component -@Slf4j -public class MegaphoneScheduler extends AbstractScheduler { - private final MegaphoneService megaphoneService; - - public MegaphoneScheduler(MegaphoneService megaphoneService) { - this.megaphoneService = megaphoneService; - this.setCron("0 59 23 * * *"); - } - - @Override - public Runnable runnable() { - return () -> { - log.info("Set Megaphone List "); - megaphoneService.setMegaphoneList(LocalDate.now()); - }; - } -} diff --git a/src/main/java/com/gg/server/global/scheduler/TournamentScheduler.java b/src/main/java/com/gg/server/global/scheduler/TournamentScheduler.java deleted file mode 100644 index 3765a137e..000000000 --- a/src/main/java/com/gg/server/global/scheduler/TournamentScheduler.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.global.scheduler; - -import com.gg.server.domain.tournament.service.TournamentService; -import com.gg.server.global.config.ConstantConfig; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class TournamentScheduler extends AbstractScheduler { - private final TournamentService tournamentService; - - private final ConstantConfig constantConfig; - - public TournamentScheduler(TournamentService tournamentService, ConstantConfig constantConfig) { - this.tournamentService = tournamentService; - this.constantConfig = constantConfig; - this.cron = constantConfig.getTournamentSchedule(); // TODO QA ์ดํ›„ 0 0 0 * * * ๋กœ ๋ณ€๊ฒฝ - } - - @Override - public Runnable runnable() { - return () -> { - log.info("Tournament Scheduler Started"); - tournamentService.startTournament(); - }; - } -} diff --git a/src/main/java/com/gg/server/global/security/UserPrincipal.java b/src/main/java/com/gg/server/global/security/UserPrincipal.java deleted file mode 100644 index 30eb2236e..000000000 --- a/src/main/java/com/gg/server/global/security/UserPrincipal.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.gg.server.global.security; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RoleType; -import lombok.Getter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; - -import java.util.*; - -@Getter -public class UserPrincipal implements OAuth2User, UserDetails { - private final Long id; - private final String nickname; - private final Collection authorities; - private Map attributes; - - public UserPrincipal(Long id, String nickname, Collection authorities) { - this.id = id; - this.nickname = nickname; - this.authorities = authorities; - } - - public static UserPrincipal create(User user) { - List authorities = new ArrayList<>(); - if (user.getRoleType().getKey().equals("ROLE_USER")) { - authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); - } else if (user.getRoleType().getKey().equals("ROLE_ADMIN")) { - authorities.add(new SimpleGrantedAuthority(RoleType.USER.getKey())); - authorities.add(new SimpleGrantedAuthority(RoleType.ADMIN.getKey())); - } - return new UserPrincipal(user.getId(), user.getIntraId(), authorities); - } - - public static UserPrincipal create(User user, Map attributes) { - UserPrincipal userPrincipal = UserPrincipal.create(user); - userPrincipal.setAttributes(attributes); - return userPrincipal; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - @Override - public String getPassword() { - return null; - } - - @Override - public String getUsername() { - return nickname; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public String getName() { - return String.valueOf(id); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/security/config/RestAuthenticationEntryPoint.java b/src/main/java/com/gg/server/global/security/config/RestAuthenticationEntryPoint.java deleted file mode 100644 index f5bb19733..000000000 --- a/src/main/java/com/gg/server/global/security/config/RestAuthenticationEntryPoint.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.global.security.config; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -@Slf4j -public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence( - HttpServletRequest request, - HttpServletResponse response, - AuthenticationException authException - ) throws IOException { - authException.printStackTrace(); - log.info("Responding with unauthorized error. Message := {}", authException.getMessage()); - response.sendError( - HttpServletResponse.SC_UNAUTHORIZED, - authException.getLocalizedMessage() - ); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/security/config/SecurityConfig.java b/src/main/java/com/gg/server/global/security/config/SecurityConfig.java deleted file mode 100644 index 599af2108..000000000 --- a/src/main/java/com/gg/server/global/security/config/SecurityConfig.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.gg.server.global.security.config; - -import com.gg.server.global.security.config.properties.CorsProperties; -import com.gg.server.global.security.handler.OAuthAuthenticationSuccessHandler; -import com.gg.server.global.security.jwt.utils.TokenAuthenticationFilter; -import com.gg.server.global.security.repository.OAuthAuthorizationRequestBasedOnCookieRepository; -import com.gg.server.global.security.service.CustomUserDetailsService; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.Arrays; - -@RequiredArgsConstructor -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - private final CustomUserDetailsService userDetailsService; - private final OAuthAuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler; - private final CorsProperties corsProperties; - private final TokenAuthenticationFilter tokenAuthenticationFilter; - private final OAuthAuthorizationRequestBasedOnCookieRepository oAuth2AuthorizationRequestBasedOnCookieRepository; - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService); - } - - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .cors() - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - .antMatchers("/pingpong/admin/**").hasRole("ADMIN") - .antMatchers(HttpMethod.PUT, "/pingpong/users/{intraId}").hasAnyRole("USER", "ADMIN") - .antMatchers(HttpMethod.POST, "/pingpong/match").hasAnyRole("USER", "ADMIN") - .antMatchers(HttpMethod.POST, "/pingpong/tournaments/{tournamentId}/users").hasAnyRole("USER", "ADMIN") - .antMatchers("/login", "/oauth2/authorization/**", "/","/pingpong/users/oauth/**", - "/pingpong/users/accesstoken", "/actuator/**", - "/swagger-ui/**", "/swagger-ui**", "/v3/api-docs/**", "/v3/api-docs**", "/api-docs").permitAll() - .anyRequest().authenticated() - .and() - .csrf().disable() - .formLogin().disable() - .httpBasic().disable() - .exceptionHandling() - .authenticationEntryPoint(new RestAuthenticationEntryPoint()) - .and() - .oauth2Login() - .authorizationEndpoint() - .baseUri("/oauth2/authorization") - .authorizationRequestRepository(oAuth2AuthorizationRequestBasedOnCookieRepository) - .and() - .successHandler(oAuth2AuthenticationSuccessHandler); - - http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - } - - @Bean - public UrlBasedCorsConfigurationSource corsConfigurationSource() { - UrlBasedCorsConfigurationSource corsConfigSource = new UrlBasedCorsConfigurationSource(); - CorsConfiguration corsConfig = new CorsConfiguration(); - corsConfig.setAllowedHeaders(Arrays.asList(corsProperties.getAllowedHeaders().split(","))); - corsConfig.setAllowedMethods(Arrays.asList(corsProperties.getAllowedMethods().split(","))); - corsConfig.setAllowedOrigins(Arrays.asList(corsProperties.getAllowedOrigins().split(","))); - corsConfig.setAllowCredentials(true); - corsConfig.setMaxAge(corsConfig.getMaxAge()); - corsConfigSource.registerCorsConfiguration("/**", corsConfig); - return corsConfigSource; - } - -} diff --git a/src/main/java/com/gg/server/global/security/config/properties/AppProperties.java b/src/main/java/com/gg/server/global/security/config/properties/AppProperties.java deleted file mode 100644 index c713878f4..000000000 --- a/src/main/java/com/gg/server/global/security/config/properties/AppProperties.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.global.security.config.properties; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -import java.util.ArrayList; -import java.util.List; - -@Getter -@Configuration -@ConfigurationProperties(prefix = "app") -public class AppProperties { - private final Auth auth = new Auth(); - private final OAuth2 oauth2 = new OAuth2(); - - @Getter - @Setter - @NoArgsConstructor - @AllArgsConstructor - public static class Auth { - private String tokenSecret; - private String refreshTokenSecret; - private long tokenExpiry; - private long refreshTokenExpiry; - } - - public static final class OAuth2 { - private List authorizedRedirectUris = new ArrayList<>(); - - public List getAuthorizedRedirectUris() { - return authorizedRedirectUris; - } - - public OAuth2 authorizedRedirectUris(List authorizedRedirectUris) { - this.authorizedRedirectUris = authorizedRedirectUris; - return this; - } - } -} - diff --git a/src/main/java/com/gg/server/global/security/config/properties/CorsProperties.java b/src/main/java/com/gg/server/global/security/config/properties/CorsProperties.java deleted file mode 100644 index 097d77d5f..000000000 --- a/src/main/java/com/gg/server/global/security/config/properties/CorsProperties.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.global.security.config.properties; - -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Getter -@Setter -@Configuration -@ConfigurationProperties(prefix = "cors") -public class CorsProperties { - private String allowedOrigins; - private String allowedMethods; - private String allowedHeaders; - private Long maxAge; -} diff --git a/src/main/java/com/gg/server/global/security/cookie/CookieUtil.java b/src/main/java/com/gg/server/global/security/cookie/CookieUtil.java deleted file mode 100644 index ea837e543..000000000 --- a/src/main/java/com/gg/server/global/security/cookie/CookieUtil.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.gg.server.global.security.cookie; - - -import com.gg.server.global.security.config.properties.AppProperties; -import com.gg.server.global.utils.ApplicationYmlRead; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.web.server.Cookie.SameSite; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseCookie; -import org.springframework.stereotype.Component; -import org.springframework.util.SerializationUtils; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Base64; -import java.util.Optional; - -@Component -@RequiredArgsConstructor -public class CookieUtil { - - private final ApplicationYmlRead applicationYmlRead; - - public Optional getCookie(HttpServletRequest request, String name) { - Cookie[] cookies = request.getCookies(); - - if (cookies != null && cookies.length > 0) { - for (Cookie cookie : cookies) { - if (name.equals(cookie.getName())) { - return Optional.of(cookie); - } - } - } - return Optional.empty(); - } - - public void addCookie(HttpServletResponse response, String name, String value, int maxAge) { - String domain = applicationYmlRead.getDomain(); - ResponseCookie cookie = ResponseCookie.from(name, value) - .maxAge(maxAge) - .domain(domain) - .httpOnly(false) - .path("/") - .secure(true) - .build(); - response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); - } - public void deleteCookie(HttpServletResponse response, String name) { - String domain = applicationYmlRead.getDomain(); - ResponseCookie cookie = ResponseCookie.from(name, null) - .maxAge(0) - .domain(domain) - .httpOnly(false) - .path("/") - .secure(true) - .build(); - response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); - } - - public void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) { - Cookie[] cookies = request.getCookies(); - - if (cookies != null && cookies.length > 0) { - for (Cookie cookie : cookies) { - if (name.equals(cookie.getName())) { - cookie.setValue(""); - cookie.setPath("/"); - cookie.setMaxAge(0); - response.addCookie(cookie); - } - } - } - } - - public String serialize(Object obj) { - return Base64.getUrlEncoder() - .encodeToString(SerializationUtils.serialize(obj)); - } - - public T deserialize(Cookie cookie, Class cls) { - return cls.cast( - SerializationUtils.deserialize( - Base64.getUrlDecoder().decode(cookie.getValue()) - ) - ); - } -} - diff --git a/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java b/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java deleted file mode 100644 index 50bcf8a21..000000000 --- a/src/main/java/com/gg/server/global/security/handler/OAuthAuthenticationSuccessHandler.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.gg.server.global.security.handler; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.security.UserPrincipal; -import com.gg.server.global.security.cookie.CookieUtil; -import com.gg.server.global.security.config.properties.AppProperties; -import com.gg.server.global.security.jwt.repository.JwtRedisRepository; -import com.gg.server.global.security.jwt.utils.TokenHeaders; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.ApplicationYmlRead; -import javax.servlet.http.Cookie; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -@Component -@RequiredArgsConstructor -public class OAuthAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - private final JwtRedisRepository jwtRedisRepository; - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - private final AppProperties appProperties; - private final ApplicationYmlRead applicationYmlRead; - private final CookieUtil cookieUtil; - - @Transactional - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException { - String targetUrl; - try{ - targetUrl = determineTargetUrl(request, response, authentication); - } catch (Exception e) { - targetUrl = applicationYmlRead.getFrontUrl(); - } - - if (response.isCommitted()) { - logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); - return; - } - clearAuthenticationAttributes(request, response); - getRedirectStrategy().sendRedirect(request, response, targetUrl); - } - - @Override - protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - - UserPrincipal principal = (UserPrincipal) authentication.getPrincipal(); - Cookie[] cookies = request.getCookies(); - for (Cookie cookie :cookies) { - if (cookie.getName().equals(TokenHeaders.REFRESH_TOKEN) ) { - Long existUserId = jwtRedisRepository.getUserIdFromRefToken(cookie.getValue()); - if (existUserId != null && !existUserId.equals(principal.getId())) { - jwtRedisRepository.deleteRefToken(cookie.getValue()); - return deleteKakaoUser(existUserId, response, authentication); - } - } - } - - // ์ฟ ํ‚ค ์‹œ๊ฐ„ ์„ค์ • - long refreshTokenExpiry = appProperties.getAuth().getRefreshTokenExpiry(); - - // token ์„ค์ • - String accessToken = tokenProvider.createToken(principal.getId()); - String refreshToken = tokenProvider.refreshToken(principal.getId()); - - cookieUtil.addCookie(response, TokenHeaders.REFRESH_TOKEN, refreshToken, - (int)(refreshTokenExpiry / 1000)); - - jwtRedisRepository.addRefToken(refreshToken, refreshTokenExpiry, principal.getId()); - return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl()) - .queryParam("token", accessToken) - .build().toUriString(); - } - - private String deleteKakaoUser(Long existUserId, HttpServletResponse response, Authentication authentication) { - UserPrincipal principal = (UserPrincipal) authentication.getPrincipal(); - User existUser = userRepository.findById(existUserId).orElseThrow(UserNotFoundException::new); - User newUser = userRepository.findById(principal.getId()).orElseThrow(UserNotFoundException::new); - //kakao ๊ณ„์ • ์‚ฌ์šฉ์ž๊ฐ€ 42 ์ธ์ฆ - if (existUser.getRoleType().equals(RoleType.GUEST)) { - return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl() + "/users/detail") - .queryParam("intraId", newUser.getIntraId()) - .queryParam("token", saveAndGetUserAccessToken(response, newUser, existUser)) - .build().toUriString(); - } - //๊ธฐ์กด user ์‚ฌ์šฉ์ž๊ฐ€ ์นด์นด์˜ค ์ธ์ฆ - if (newUser.getRoleType().equals(RoleType.GUEST)) { - return UriComponentsBuilder.fromUriString(applicationYmlRead.getFrontUrl() + "/users/detail") - .queryParam("intraId", existUser.getIntraId()) - .queryParam("token", saveAndGetUserAccessToken(response, existUser, newUser)) - .build().toUriString(); - } - throw new UserNotFoundException(); - } - - - private String saveAndGetUserAccessToken(HttpServletResponse response, - User remainedUser, User deletedUser) { - remainedUser.updateKakaoId(deletedUser.getKakaoId()); - // ์ฟ ํ‚ค ์‹œ๊ฐ„ ์„ค์ • - long refreshTokenExpiry = appProperties.getAuth().getRefreshTokenExpiry(); - userRepository.delete(deletedUser); - - // token ์„ค์ • - String accessToken = tokenProvider.createToken(remainedUser.getId()); - String refreshToken = tokenProvider.refreshToken(remainedUser.getId()); - jwtRedisRepository.addRefToken(refreshToken, refreshTokenExpiry, remainedUser.getId()); - - cookieUtil.addCookie(response, TokenHeaders.REFRESH_TOKEN, refreshToken, - (int)(refreshTokenExpiry / 1000)); - return accessToken; - } - - private void clearAuthenticationAttributes(HttpServletRequest request, HttpServletResponse response) { - super.clearAuthenticationAttributes(request); - } - - -} diff --git a/src/main/java/com/gg/server/global/security/info/OAuthUserInfo.java b/src/main/java/com/gg/server/global/security/info/OAuthUserInfo.java deleted file mode 100644 index 9d791b0ac..000000000 --- a/src/main/java/com/gg/server/global/security/info/OAuthUserInfo.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.global.security.info; - -import com.gg.server.domain.user.type.RoleType; -import java.util.Map; - -public abstract class OAuthUserInfo { - protected Map attributes; - - public OAuthUserInfo(Map attributes) { - this.attributes = attributes; - } - - public Map getAttributes() { - return attributes; - } - - public abstract String getIntraId(); - - public abstract String getEmail(); - - public abstract String getImageUrl(); - - public abstract RoleType getRoleType(); - - public abstract Long getKakaoId(); -} diff --git a/src/main/java/com/gg/server/global/security/info/OAuthUserInfoFactory.java b/src/main/java/com/gg/server/global/security/info/OAuthUserInfoFactory.java deleted file mode 100644 index 54dcd7a31..000000000 --- a/src/main/java/com/gg/server/global/security/info/OAuthUserInfoFactory.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gg.server.global.security.info; - -import com.gg.server.global.security.info.impl.KakaoOAuthUserInfo; -import java.util.Map; - -import com.gg.server.global.security.info.impl.FortyTwoOAuthUserInfo; - -public class OAuthUserInfoFactory { - public static OAuthUserInfo getOAuth2UserInfo(ProviderType providerType, Map attributes) { - switch (providerType) { - case FORTYTWO: return new FortyTwoOAuthUserInfo(attributes); - case KAKAO: return new KakaoOAuthUserInfo(attributes); - //case SLACK: return new FacebookOAuth2UserInfo(attributes); - default: throw new IllegalArgumentException("Invalid Provider Type."); - } - } -} diff --git a/src/main/java/com/gg/server/global/security/info/ProviderType.java b/src/main/java/com/gg/server/global/security/info/ProviderType.java deleted file mode 100644 index 0cad81700..000000000 --- a/src/main/java/com/gg/server/global/security/info/ProviderType.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.global.security.info; - -import lombok.Getter; - -@Getter -public enum ProviderType { - FORTYTWO("42"), KAKAO("KAKAO"); - - private String key; - - ProviderType(String key) { - this.key = key; - } - - public String getKey() { - return key; - } - - public static ProviderType keyOf(String key) { - for (ProviderType value : ProviderType.values()) { - if (value.key.equalsIgnoreCase(key)) { - return value; - } - } - return null; - } -} diff --git a/src/main/java/com/gg/server/global/security/info/impl/FortyTwoOAuthUserInfo.java b/src/main/java/com/gg/server/global/security/info/impl/FortyTwoOAuthUserInfo.java deleted file mode 100644 index 7f4cd88e5..000000000 --- a/src/main/java/com/gg/server/global/security/info/impl/FortyTwoOAuthUserInfo.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.gg.server.global.security.info.impl; - - -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.security.info.OAuthUserInfo; -import org.springframework.beans.factory.annotation.Value; - -import java.util.Map; - -public class FortyTwoOAuthUserInfo extends OAuthUserInfo { - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - public FortyTwoOAuthUserInfo(Map attributes) { - super(attributes); - } - - @Override - public String getIntraId() { - return attributes.get("login").toString(); - } - - public String getEmail() { - return attributes.get("email").toString(); - } - - public String getImageUrl() { - Map image = (Map) attributes.get("image"); - if (image == null) { - return defaultImageUrl; - } - if (image.get("link") == null) { - return defaultImageUrl; - } - return image.get("link").toString(); - } - - @Override - public RoleType getRoleType() { - return RoleType.USER; - } - - @Override - public Long getKakaoId() { - return null; - } -} diff --git a/src/main/java/com/gg/server/global/security/info/impl/KakaoOAuthUserInfo.java b/src/main/java/com/gg/server/global/security/info/impl/KakaoOAuthUserInfo.java deleted file mode 100644 index a20c41ff3..000000000 --- a/src/main/java/com/gg/server/global/security/info/impl/KakaoOAuthUserInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.gg.server.global.security.info.impl; - -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.global.security.info.OAuthUserInfo; -import java.util.Map; -import org.springframework.beans.factory.annotation.Value; - -public class KakaoOAuthUserInfo extends OAuthUserInfo { - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - public KakaoOAuthUserInfo(Map attributes) { - super(attributes); - } - - @Override - public String getIntraId() { - return "GUEST" + attributes.get("id").toString(); - } - - @Override - public String getEmail() { - Map kakaoAccount = (Map) attributes.get("kakao_account"); - if (kakaoAccount.get("email") == null) - return null; - return kakaoAccount.get("email").toString(); - } - - @Override - public String getImageUrl() { - Map properties = (Map) attributes.get("properties"); - return properties.get("profile_image").toString(); - } - - @Override - public RoleType getRoleType() { - return RoleType.GUEST; - } - - @Override - public Long getKakaoId() { - return (Long) attributes.get("id"); - } -} diff --git a/src/main/java/com/gg/server/global/security/jwt/repository/JwtRedisRepository.java b/src/main/java/com/gg/server/global/security/jwt/repository/JwtRedisRepository.java deleted file mode 100644 index 51181ae53..000000000 --- a/src/main/java/com/gg/server/global/security/jwt/repository/JwtRedisRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.global.security.jwt.repository; - -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -import java.util.concurrent.TimeUnit; - -@Repository -@RequiredArgsConstructor -public class JwtRedisRepository { - private final RedisTemplate redisTemplate; - - public void addRefToken(String refreshToken, long timeOut, Long userId) { - redisTemplate.opsForValue().set(refreshToken, userId.toString(), timeOut, TimeUnit.MILLISECONDS); - } - - public Long getUserIdFromRefToken(String refToken){ - String userId = redisTemplate.opsForValue().get(refToken); - if (userId == null) - return null; - return Long.valueOf(userId); - } - - public void deleteRefToken(String refToken) { - redisTemplate.delete(refToken); - } -} diff --git a/src/main/java/com/gg/server/global/security/jwt/utils/AuthTokenProvider.java b/src/main/java/com/gg/server/global/security/jwt/utils/AuthTokenProvider.java deleted file mode 100644 index f42c81ffd..000000000 --- a/src/main/java/com/gg/server/global/security/jwt/utils/AuthTokenProvider.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.gg.server.global.security.jwt.utils; - -import com.gg.server.global.security.config.properties.AppProperties; -import com.gg.server.global.security.UserPrincipal; -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.Keys; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; - -import java.security.Key; -import java.util.*; - -@Slf4j -@Component -public class AuthTokenProvider { - - private AppProperties appProperties; - private final Key key; - private final Key refreshKey; - - public AuthTokenProvider(AppProperties appProperties) { - this.appProperties = appProperties; - key = Keys.hmacShaKeyFor(appProperties.getAuth().getTokenSecret().getBytes()); - refreshKey = Keys.hmacShaKeyFor(appProperties.getAuth().getRefreshTokenSecret().getBytes()); - log.info(key.getAlgorithm()); - } - public String refreshToken(Long userId) { - Date now = new Date(); - Date expiryDate = new Date(now.getTime() + - appProperties.getAuth().getRefreshTokenExpiry()); - return Jwts.builder() - .setSubject(userId.toString()) - .setIssuedAt(new Date()) - .setExpiration(expiryDate) - .signWith(refreshKey) - .compact(); - } - - public String createToken(Long userId) { - Date now = new Date(); - Date expiryDate = new Date(now.getTime() + - appProperties.getAuth().getTokenExpiry()); - return Jwts.builder() - .setSubject(Long.toString(userId)) - .setIssuedAt(new Date()) - .setExpiration(expiryDate) - .signWith(key) - .compact(); - } - - private Claims getClaims(String token, Key key) { - try { - return Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody(); - } catch (SecurityException e) { - log.info("Invalid JWT signature."); - } catch (MalformedJwtException e) { - log.info("Invalid JWT token."); - } catch (ExpiredJwtException e) { - log.info("Expired JWT token."); - } catch (UnsupportedJwtException e) { - log.info("Unsupported JWT token."); - } catch (IllegalArgumentException e) { - log.info("JWT token compact of handler are invalid."); - } - return null; - } - - public Long getUserIdFromAccessToken(String accessToken) { - Claims claims = getClaims(accessToken, key); - if (claims == null) - return null; - return Long.valueOf(claims.getSubject()); - } - -} diff --git a/src/main/java/com/gg/server/global/security/jwt/utils/TokenAuthenticationFilter.java b/src/main/java/com/gg/server/global/security/jwt/utils/TokenAuthenticationFilter.java deleted file mode 100644 index d0230b893..000000000 --- a/src/main/java/com/gg/server/global/security/jwt/utils/TokenAuthenticationFilter.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.gg.server.global.security.jwt.utils; - -import com.gg.server.global.security.config.properties.AppProperties; -import com.gg.server.global.security.cookie.CookieUtil; -import com.gg.server.global.security.service.CustomUserDetailsService; -import com.gg.server.global.utils.HeaderUtil; -import io.jsonwebtoken.Claims; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import static org.apache.commons.lang3.StringUtils.isEmpty; - -@Slf4j -@RequiredArgsConstructor -@Component -public class TokenAuthenticationFilter extends OncePerRequestFilter { - private final AuthTokenProvider tokenProvider; - private final CustomUserDetailsService customUserDetailsService; - - @Override - protected void doFilterInternal( - HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - try { - String tokenHeader = request.getHeader(HttpHeaders.AUTHORIZATION); - if (isEmpty(tokenHeader) || !tokenHeader.startsWith("Bearer ")) { - filterChain.doFilter(request, response); - return; - } - OAuth2AuthenticationToken authentication = validate(request); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - } catch (Exception e) { - log.error("Security Context์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ์„ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", e); - } - filterChain.doFilter(request, response); - } - - private OAuth2AuthenticationToken validate(HttpServletRequest request) { - String accessToken = HeaderUtil.getAccessToken(request); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - //access token ๊ฒ€์ฆ - if (userId != null){ - UserDetails userDetails = customUserDetailsService.loadUserById(userId); - return new OAuth2AuthenticationToken((OAuth2User) userDetails, userDetails.getAuthorities(), "42"); - } - throw new RuntimeException("token not validated"); - } - -} diff --git a/src/main/java/com/gg/server/global/security/jwt/utils/TokenHeaders.java b/src/main/java/com/gg/server/global/security/jwt/utils/TokenHeaders.java deleted file mode 100644 index 72ccbd160..000000000 --- a/src/main/java/com/gg/server/global/security/jwt/utils/TokenHeaders.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.gg.server.global.security.jwt.utils; - -public class TokenHeaders { - public static final String REFRESH_TOKEN = "refresh_token"; - public static final String ACCESS_TOKEN = "access_token"; -} diff --git a/src/main/java/com/gg/server/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java b/src/main/java/com/gg/server/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java deleted file mode 100644 index a18aee3bd..000000000 --- a/src/main/java/com/gg/server/global/security/repository/OAuthAuthorizationRequestBasedOnCookieRepository.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.gg.server.global.security.repository; - - -import com.gg.server.global.security.cookie.CookieUtil; -import com.nimbusds.oauth2.sdk.util.StringUtils; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; -import org.springframework.stereotype.Repository; - -@Repository -@RequiredArgsConstructor -public class OAuthAuthorizationRequestBasedOnCookieRepository implements AuthorizationRequestRepository { - - public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; - public static final String REDIRECT_URI_PARAM_COOKIE_NAME = "redirect_uri"; - private static final int cookieExpireSeconds = 180; - private final CookieUtil cookieUtil; - - @Override - public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { - return cookieUtil.getCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) - .map(cookie -> cookieUtil.deserialize(cookie, OAuth2AuthorizationRequest.class)) - .orElse(null); - } - - @Override - public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) { - if (authorizationRequest == null) { - cookieUtil.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - cookieUtil.deleteCookie(request, response, REDIRECT_URI_PARAM_COOKIE_NAME); - return; - } - - cookieUtil.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, cookieUtil.serialize(authorizationRequest), - cookieExpireSeconds); - String redirectUriAfterLogin = request.getParameter(REDIRECT_URI_PARAM_COOKIE_NAME); - if (StringUtils.isNotBlank(redirectUriAfterLogin)) { - cookieUtil.addCookie(response, REDIRECT_URI_PARAM_COOKIE_NAME, redirectUriAfterLogin, - cookieExpireSeconds); - } - } - - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) { - return this.loadAuthorizationRequest(request); - } - -} - diff --git a/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java b/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java deleted file mode 100644 index a7442973c..000000000 --- a/src/main/java/com/gg/server/global/security/service/CustomOAuth2UserService.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.gg.server.global.security.service; - -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.UserPrincipal; -import com.gg.server.global.security.info.OAuthUserInfo; -import com.gg.server.global.security.info.OAuthUserInfoFactory; -import com.gg.server.global.security.info.ProviderType; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.utils.aws.AsyncNewUserImageUploader; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.InternalAuthenticationServiceException; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; - -@Service -@RequiredArgsConstructor -@Transactional -public class CustomOAuth2UserService extends DefaultOAuth2UserService { - private final UserRepository userRepository; - private final AsyncNewUserImageUploader asyncNewUserImageUploader; - private final RankRepository rankRepository; - private final SeasonRepository seasonRepository; - private final RankRedisRepository rankRedisRepository; - private final TierRepository tierRepository; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - @Override - public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - OAuth2User user = super.loadUser(userRequest); - - try { - return this.process(userRequest, user); - } catch (AuthenticationException ex) { - throw ex; - } catch (Exception ex) { - ex.printStackTrace(); - throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause()); - } - } - - private OAuth2User process(OAuth2UserRequest userRequest, OAuth2User user) { - ProviderType providerType = ProviderType.keyOf(userRequest.getClientRegistration().getRegistrationId().toUpperCase()); - User savedUser; - OAuthUserInfo userInfo = OAuthUserInfoFactory.getOAuth2UserInfo(providerType, user.getAttributes()); - if (providerType.equals(ProviderType.FORTYTWO)) { - savedUser = userRepository.findByIntraId(userInfo.getIntraId()) - .orElse(null); - } else { - savedUser = userRepository.findByKakaoId(userInfo.getKakaoId()) - .orElse(null); - } - if (savedUser == null) { - savedUser = createUser(userInfo); - if (providerType.equals(ProviderType.FORTYTWO)) - createUserRank(savedUser); - if (userInfo.getImageUrl().startsWith("https://cdn.intra.42.fr/")) { - asyncNewUserImageUploader.upload(userInfo.getIntraId(), userInfo.getImageUrl()); - } - } - return UserPrincipal.create(savedUser, user.getAttributes()); - } - - private void createUserRank(User savedUser) { - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - seasonRepository.findCurrentAndNewSeason(LocalDateTime.now()).forEach( - season -> { - Rank userRank = Rank.from(savedUser, season, season.getStartPpp(), tier); - rankRepository.save(userRank); - RankRedis rankRedis = RankRedis.from(UserDto.from(savedUser), season.getStartPpp(), tier.getImageUri()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(hashKey, savedUser.getId(), rankRedis); - } - ); - } - - private User createUser(OAuthUserInfo userInfo) { - User user = User.builder() - .intraId(userInfo.getIntraId()) - .roleType(userInfo.getRoleType()) - .kakaoId(userInfo.getKakaoId()) - .snsNotiOpt(SnsType.EMAIL) - .racketType(RacketType.NONE) - .totalExp(0) - .eMail(userInfo.getEmail()) - .build(); - return userRepository.saveAndFlush(user); - } -} diff --git a/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java b/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java deleted file mode 100644 index a27fd87a2..000000000 --- a/src/main/java/com/gg/server/global/security/service/CustomUserDetailsService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.global.security.service; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.service.UserFindService; -import com.gg.server.global.security.UserPrincipal; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class CustomUserDetailsService implements UserDetailsService { - - private final UserFindService userFindService; - @Override - public UserDetails loadUserByUsername(String username) throws UserNotFoundException { - User user = userFindService.findByIntraId(username); - return UserPrincipal.create(user); - } - - public UserDetails loadUserById(Long id) { - User user = userFindService.findUserById(id); - return UserPrincipal.create(user); - } -} diff --git a/src/main/java/com/gg/server/global/utils/ApplicationYmlRead.java b/src/main/java/com/gg/server/global/utils/ApplicationYmlRead.java deleted file mode 100644 index 6680c480b..000000000 --- a/src/main/java/com/gg/server/global/utils/ApplicationYmlRead.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.global.utils; - -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -import java.util.Map; - -@Configuration -@Setter -@ConfigurationProperties(prefix = "info") -public class ApplicationYmlRead { - private Map web; - - public String getFrontUrl() { - return web.get("frontUrl"); - } - - public String getDomain(){ - return web.get("domain"); - } - - - public String getFrontLoginUrl() { - return web.get("frontUrl") + "/login"; - } -} diff --git a/src/main/java/com/gg/server/global/utils/AsyncMailSender.java b/src/main/java/com/gg/server/global/utils/AsyncMailSender.java deleted file mode 100644 index aa5163d27..000000000 --- a/src/main/java/com/gg/server/global/utils/AsyncMailSender.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.gg.server.global.utils; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; - -import javax.mail.internet.MimeMessage; - -@Component -@AllArgsConstructor -@Slf4j -public class AsyncMailSender { - private final JavaMailSender javaMailSender; - - @Async("asyncExecutor") - public void send(MimeMessage message) { - try { - javaMailSender.send(message); - } catch(Exception ex) { - log.error(ex.getMessage()); - } - } -} diff --git a/src/main/java/com/gg/server/global/utils/BaseTimeEntity.java b/src/main/java/com/gg/server/global/utils/BaseTimeEntity.java deleted file mode 100644 index 8bef5cfe4..000000000 --- a/src/main/java/com/gg/server/global/utils/BaseTimeEntity.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.global.utils; - -import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.time.LocalDateTime; - -@Getter -@MappedSuperclass -@EntityListeners(AuditingEntityListener.class) -public abstract class BaseTimeEntity { - @CreatedDate - @Column(updatable = false, nullable = false) - private LocalDateTime createdAt; - - @LastModifiedDate - private LocalDateTime modifiedAt; - -} diff --git a/src/main/java/com/gg/server/global/utils/BusinessChecker.java b/src/main/java/com/gg/server/global/utils/BusinessChecker.java deleted file mode 100644 index 9f7ea08ec..000000000 --- a/src/main/java/com/gg/server/global/utils/BusinessChecker.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.gg.server.global.utils; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import java.util.Collection; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * Checker. - * - *

- * ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒดํฌ์šฉ check ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค - *

- * - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class BusinessChecker { - public static void mustNotNull(Object object, ErrorCode errorCode) { - if (object == null) { - throw new BusinessException(errorCode); - } - } - - public static void mustContains(Object object, Collection collection, ErrorCode errorCode) { - if (!collection.contains(object)) { - throw new BusinessException(errorCode); - } - } - - public static void mustNotContains(Object object, Collection collection, ErrorCode errorCode) { - if (collection.contains(object)) { - throw new BusinessException(errorCode); - } - } - - public static void mustNotExceed(int size, Collection collection, ErrorCode errorCode) { - if (collection.size() > size) { - throw new BusinessException(errorCode); - } - } -} diff --git a/src/main/java/com/gg/server/global/utils/EloRating.java b/src/main/java/com/gg/server/global/utils/EloRating.java deleted file mode 100644 index 4de09cc34..000000000 --- a/src/main/java/com/gg/server/global/utils/EloRating.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.gg.server.global.utils; - -public class EloRating { - public static Integer pppChange(Integer myPPP, Integer opponentPPP, Boolean isWin, Boolean isOneSide) { - Double we = 1.0 / (Math.pow(10.0, (opponentPPP - myPPP) / 400.0) + 1.0); - Double change = 40 * ((isWin ? 1 : 0) - we); - if (isOneSide) { - change = change + change * 0.21; - } - if (change < 0) { - change = change * 0.9; - } - return change.intValue(); - } -} diff --git a/src/main/java/com/gg/server/global/utils/ExpLevelCalculator.java b/src/main/java/com/gg/server/global/utils/ExpLevelCalculator.java deleted file mode 100644 index 7257dca5a..000000000 --- a/src/main/java/com/gg/server/global/utils/ExpLevelCalculator.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.global.utils; - -public class ExpLevelCalculator { - private static Integer expPerGame = 100; - private static Integer expBonus = 10; - private static int[] accumulatedExpForEachLevel = { - 0, 100, 200, 300, 500, 700, 900, 1200, 1500, 1800, - 2200, 2600, 3000, 3400, 3800, 4300, 4800, 5300, 5800, 6300, - 6900, 7500, 8100, 8700, 9300, 10000, 10700, 11400, 12100, 12800, - 13600, 14400, 15200, 16000, 16800, 17700, 18600, 19500, 20400, 21300, - 22300, 25100, Integer.MAX_VALUE - }; - - private static int[] expForEachLevel = { - 0, 100, 100, 100, 200, 200, 200, 300, 300, 300, - 400, 400, 400, 400, 400, 500, 500, 500, 500, 500, - 600, 600, 600, 600, 600, 700, 700, 700, 700, 700, - 800, 800, 800, 800, 800, 900, 900, 900, 900, 900, - 1000, 2800, Integer.MAX_VALUE - }; - - public static int getLevel(int total_exp) { - int i = 0; - while (total_exp >= accumulatedExpForEachLevel[i]) { - ++i; - } - return i; - } - - public static int getCurrentLevelMyExp(int total_exp) { - int level = getLevel(total_exp); - return total_exp - accumulatedExpForEachLevel[level - 1]; - } - - public static int getLevelMaxExp(int level) { - return expForEachLevel[level]; - } - - public static int getExpPerGame() { - return expPerGame; - } - - public static int getExpBonus() { - return expBonus; - } -} diff --git a/src/main/java/com/gg/server/global/utils/FileDownloader.java b/src/main/java/com/gg/server/global/utils/FileDownloader.java deleted file mode 100644 index c01c64a28..000000000 --- a/src/main/java/com/gg/server/global/utils/FileDownloader.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.gg.server.global.utils; - -import org.apache.http.client.HttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; - -@Component -public class FileDownloader { - private RestTemplate restTemplate; - - public FileDownloader() { - HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); - factory.setConnectTimeout(5000); // ํƒ€์ž„์•„์›ƒ ์„ค์ • 5์ดˆ - factory.setReadTimeout(5000); // ํƒ€์ž„์•„์›ƒ ์„ค์ • 5์ดˆ - - //Apache HttpComponents : ๊ฐ ํ˜ธ์ŠคํŠธ(IP์™€ Port์˜ ์กฐํ•ฉ)๋‹น ์ปค๋„ฅ์…˜ ํ’€์— ์ƒ์„ฑ๊ฐ€๋Šฅํ•œ ์ปค๋„ฅ์…˜ ์ˆ˜ - HttpClient httpClient = HttpClientBuilder.create() - .setMaxConnTotal(50)//์ตœ๋Œ€ ์ปค๋„ฅ์…˜ ์ˆ˜ - .setMaxConnPerRoute(20).build(); - factory.setHttpClient(httpClient); - - // 2. RestTemplate ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. - this.restTemplate = new RestTemplate(factory); - } - - public byte[] downloadFromUrl(String imageUrl) { - UriComponents uri = UriComponentsBuilder.fromHttpUrl(imageUrl).build(false); - return restTemplate.getForObject(uri.toString(), byte[].class); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/utils/HeaderUtil.java b/src/main/java/com/gg/server/global/utils/HeaderUtil.java deleted file mode 100644 index 25f5352e8..000000000 --- a/src/main/java/com/gg/server/global/utils/HeaderUtil.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.gg.server.global.utils; - -import javax.servlet.http.HttpServletRequest; - -public class HeaderUtil { - - private final static String HEADER_AUTHORIZATION = "Authorization"; - private final static String TOKEN_PREFIX = "Bearer "; - - public static String getAccessToken(HttpServletRequest request) { - String headerValue = request.getHeader(HEADER_AUTHORIZATION); - - if (headerValue == null) { - return null; - } - - if (headerValue.startsWith(TOKEN_PREFIX)) { - return headerValue.substring(TOKEN_PREFIX.length()); - } - return null; - } -} diff --git a/src/main/java/com/gg/server/global/utils/ImageResizingUtil.java b/src/main/java/com/gg/server/global/utils/ImageResizingUtil.java deleted file mode 100644 index bd114844e..000000000 --- a/src/main/java/com/gg/server/global/utils/ImageResizingUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.global.utils; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -public class ImageResizingUtil { - public static byte[] resizeImageBytes(byte[] downloadedImageBytes, double ratio) throws IOException { - InputStream inputStream = new ByteArrayInputStream(downloadedImageBytes); - BufferedImage image = resize(ImageIO.read(inputStream), ratio); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(image, "jpeg", baos); - return baos.toByteArray(); - } - - private static BufferedImage resize(BufferedImage img, double ratio) { - int newWidth = (int) (img.getWidth() * ratio); - int newHeight = (int) (img.getHeight() * ratio); - Image imageToResize = img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH); - BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB); - resizedImage.getGraphics().drawImage(imageToResize, 0, 0, newWidth, newHeight, null); - return resizedImage; - } -} diff --git a/src/main/java/com/gg/server/global/utils/ItemImageHandler.java b/src/main/java/com/gg/server/global/utils/ItemImageHandler.java deleted file mode 100644 index dfcd319c9..000000000 --- a/src/main/java/com/gg/server/global/utils/ItemImageHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.gg.server.global.utils; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.gg.server.domain.item.data.Item; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - -@Component -public class ItemImageHandler { - private final AmazonS3 amazonS3; - - public ItemImageHandler(AmazonS3 amazonS3) { - this.amazonS3 = amazonS3; - } - - @Value("${cloud.aws.s3.bucket}") - private String bucketName; - - @Value("${cloud.aws.s3.dir}") - private String dir; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - - public String updateAndGetS3ImageUri(MultipartFile multipartFile, Item item) throws IOException { - String itemFileName = item.getName() + "-" + UUID.randomUUID() + ".jpeg"; - if (itemFileName.equals("small_default.jpeg")) - return defaultImageUrl; - else { - String s3ImageUrl = uploadToS3(multipartFile, itemFileName); - return s3ImageUrl; - } - } - - public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException { - String s3FileName = dir + fileName; - InputStream inputStream = multipartFile.getInputStream(); - ObjectMetadata objMeta = new ObjectMetadata(); - objMeta.setContentLength(multipartFile.getSize()); - amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl(CannedAccessControlList.PublicRead)); - return amazonS3.getUrl(bucketName, s3FileName).toString(); - } -} diff --git a/src/main/java/com/gg/server/global/utils/JpegMultipartFile.java b/src/main/java/com/gg/server/global/utils/JpegMultipartFile.java deleted file mode 100644 index 84a8fb806..000000000 --- a/src/main/java/com/gg/server/global/utils/JpegMultipartFile.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.gg.server.global.utils; - -import org.springframework.web.multipart.MultipartFile; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -public class JpegMultipartFile implements MultipartFile { - - private final byte[] bytes; - String name; - String originalFilename; - String contentType; - boolean isEmpty; - long size; - - public JpegMultipartFile(byte[] bytes, String name) { - this.bytes = bytes; - this.name = name; - this.originalFilename = name + ".jpeg"; - this.contentType = "image/jpeg"; - this.size = bytes.length; - this.isEmpty = false; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getOriginalFilename() { - return originalFilename; - } - - @Override - public String getContentType() { - return contentType; - } - - @Override - public boolean isEmpty() { - return isEmpty; - } - - @Override - public long getSize() { - return size; - } - - @Override - public byte[] getBytes() throws IOException { - return bytes; - } - - @Override - public InputStream getInputStream() { - return new ByteArrayInputStream(bytes); - } - - @Override - public void transferTo(File dest) throws IllegalStateException { - } -} diff --git a/src/main/java/com/gg/server/global/utils/UserImageHandler.java b/src/main/java/com/gg/server/global/utils/UserImageHandler.java deleted file mode 100644 index a29e0037d..000000000 --- a/src/main/java/com/gg/server/global/utils/UserImageHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gg.server.global.utils; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.data.UserImageRepository; -import com.gg.server.domain.user.exception.UserImageNullException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; -import java.util.UUID; - -@Component -public class UserImageHandler { - private final AmazonS3 amazonS3; - private final FileDownloader fileDownloader; - - public UserImageHandler(AmazonS3 amazonS3, FileDownloader fileDownloader, - UserImageRepository userImageRepository) { - this.amazonS3 = amazonS3; - this.fileDownloader = fileDownloader; - this.userImageRepository = userImageRepository; - } - - @Value("${cloud.aws.s3.bucket}") - private String bucketName; - - @Value("${cloud.aws.s3.dir}") - private String dir; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - private final UserImageRepository userImageRepository; - - public String uploadAndGetS3ImageUri(String intraId, String imageUrl) { - if (!isStringValid(intraId) || !isStringValid(imageUrl)) { - return defaultImageUrl; - } - byte[] downloadedImageBytes = fileDownloader.downloadFromUrl(imageUrl); - try { - byte[] resizedImageBytes = ImageResizingUtil.resizeImageBytes(downloadedImageBytes, 0.5); - MultipartFile multipartFile = new JpegMultipartFile(resizedImageBytes, intraId); - return uploadToS3(multipartFile, multipartFile.getOriginalFilename()); - } catch (IOException e) { - return defaultImageUrl; - } - } - - public String updateAndGetS3ImageUri(MultipartFile multipartFile, User user) throws IOException - { - String updateFileName = user.getIntraId() + "-" + UUID.randomUUID().toString() + ".jpeg"; - if (updateFileName.equals("small_default.jpeg")) - return defaultImageUrl; - else { - String s3ImageUrl = uploadToS3(multipartFile, updateFileName);; - return s3ImageUrl; - } - } - - private Boolean isStringValid(String intraId) { - return intraId != null && intraId.length() != 0; - } - - public String uploadToS3(MultipartFile multipartFile, String fileName) throws IOException{ - String s3FileName = dir + fileName; - InputStream inputStream = multipartFile.getInputStream(); - ObjectMetadata objMeta = new ObjectMetadata(); - objMeta.setContentLength(multipartFile.getSize()); - amazonS3.putObject(new PutObjectRequest(bucketName, s3FileName, inputStream, objMeta).withCannedAcl(CannedAccessControlList.PublicRead)); - return amazonS3.getUrl(bucketName, s3FileName).toString(); - } -} diff --git a/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java b/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java deleted file mode 100644 index 36fabe80f..000000000 --- a/src/main/java/com/gg/server/global/utils/argumentresolver/LoginMemberArgumentResolver.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.global.utils.argumentresolver; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.HeaderUtil; -import lombok.RequiredArgsConstructor; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -import javax.servlet.http.HttpServletRequest; - -@RequiredArgsConstructor -public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - - @Override - public boolean supportsParameter(MethodParameter parameter) { - boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class); - boolean hasUserType = UserDto.class.isAssignableFrom(parameter.getParameterType()); - return hasLoginAnnotation && hasUserType; - } - - @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { - HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); - String accessToken = HeaderUtil.getAccessToken(request); - Long loginUserId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(loginUserId).orElseThrow(); - UserDto userDto = UserDto.from(user); - return userDto; - } -} diff --git a/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java b/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java deleted file mode 100644 index 5dcce6806..000000000 --- a/src/main/java/com/gg/server/global/utils/aws/AsyncNewItemImageUploader.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.gg.server.global.utils.aws; - -import com.gg.server.domain.item.data.Item; -import com.gg.server.global.utils.ItemImageHandler; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; - -@Component -public class AsyncNewItemImageUploader { - private final ItemImageHandler itemImageHandler; - - @Value("${info.image.itemNotFoundUrl}") - private String defaultImageUrl; - - public AsyncNewItemImageUploader(ItemImageHandler itemImageHandler) { - this.itemImageHandler = itemImageHandler; - } - - @Transactional - public void upload(Item item, - MultipartFile multipartFile) throws IOException { - String s3ImageUrl = itemImageHandler.updateAndGetS3ImageUri(multipartFile, item); - if (s3ImageUrl == null) { - item.imageUpdate(defaultImageUrl); - } else { - item.imageUpdate(s3ImageUrl); - } - } -} diff --git a/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java b/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java deleted file mode 100644 index 72ef157d6..000000000 --- a/src/main/java/com/gg/server/global/utils/aws/AsyncNewUserImageUploader.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.gg.server.global.utils.aws; - -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.data.UserImageRepository; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.utils.UserImageHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import java.io.IOException; -import java.time.LocalDateTime; - -@Slf4j -@Component -public class AsyncNewUserImageUploader { - private final UserImageHandler userImageHandler; - private final UserRepository userRepository; - @PersistenceContext - private EntityManager entityManager; - - @Value("${info.image.defaultUrl}") - private String defaultImageUrl; - private final UserImageRepository userImageRepository; - - public AsyncNewUserImageUploader(UserImageHandler userImageHandler, UserRepository userRepository, - UserImageRepository userImageRepository) { - this.userImageHandler = userImageHandler; - this.userRepository = userRepository; - this.userImageRepository = userImageRepository; - } - - @Async("asyncExecutor") - @Transactional - public void upload(String intraId, String imageUrl) { - String s3ImageUrl = userImageHandler.uploadAndGetS3ImageUri(intraId, imageUrl); - if (defaultImageUrl.equals(s3ImageUrl)) { - return ; - } - userRepository.findByIntraId(intraId).ifPresent(user -> { - UserImage userImage = new UserImage(user, (s3ImageUrl != null) ? s3ImageUrl : defaultImageUrl, - LocalDateTime.now(), null, true); - userImageRepository.save(userImage); - userRepository.updateUserImage(user.getId(), userImage.getImageUri()); - }); - } - - @Transactional - public void update(String intraId, MultipartFile multipartFile) throws IOException { - User user = userRepository.findByIntraId(intraId).get(); - String s3ImageUrl = userImageHandler.updateAndGetS3ImageUri(multipartFile, user); - s3ImageUrl = s3ImageUrl == null ? defaultImageUrl : s3ImageUrl; - UserImage userImage = new UserImage(user, s3ImageUrl, LocalDateTime.now(), null, true); - userImageRepository.saveAndFlush(userImage); - user.updateImageUri(s3ImageUrl); - } -} diff --git a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounter.java b/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounter.java deleted file mode 100644 index b7a5c9a69..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounter.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import lombok.Getter; -import org.springframework.stereotype.Component; -import org.springframework.web.context.annotation.RequestScope; - -@Component -@RequestScope -@Getter -public class ApiQueryCounter { - private int count; - - public void increaseCount() { - this.count++; - } -} diff --git a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounterAop.java b/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounterAop.java deleted file mode 100644 index 120c9a167..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryCounterAop.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.cglib.proxy.Proxy; -import org.springframework.stereotype.Component; - -@Component -@Aspect -public class ApiQueryCounterAop { - - private final ApiQueryCounter apiQueryCounter; - - public ApiQueryCounterAop(final ApiQueryCounter apiQueryCounter) { - this.apiQueryCounter = apiQueryCounter; - } - - @Around("execution(* javax.sql.DataSource.getConnection())") - public Object getConnection(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { - Object connection = proceedingJoinPoint.proceed(); - return Proxy.newProxyInstance( - connection.getClass().getClassLoader(), - connection.getClass().getInterfaces(), - new ConnectionProxyHandler(connection, apiQueryCounter) - ); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryInspector.java b/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryInspector.java deleted file mode 100644 index 2d7d236df..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/ApiQueryInspector.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import org.hibernate.resource.jdbc.spi.StatementInspector; -import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; - -import java.util.Objects; - -@Component -public class ApiQueryInspector implements StatementInspector { - - private final ApiQueryCounter apiQueryCounter; - - public ApiQueryInspector(final ApiQueryCounter apiQueryCounter) { - this.apiQueryCounter = apiQueryCounter; - } - - @Override - public String inspect(final String sql) { - if (isInRequestScope()) { - apiQueryCounter.increaseCount(); - } - return sql; - } - - private boolean isInRequestScope() { - return Objects.nonNull(RequestContextHolder.getRequestAttributes()); - } -} diff --git a/src/main/java/com/gg/server/global/utils/querytracker/ConnectionProxyHandler.java b/src/main/java/com/gg/server/global/utils/querytracker/ConnectionProxyHandler.java deleted file mode 100644 index 3a5a6f5d6..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/ConnectionProxyHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import org.springframework.cglib.proxy.InvocationHandler; -import org.springframework.cglib.proxy.Proxy; - -import java.lang.reflect.Method; - -public class ConnectionProxyHandler implements InvocationHandler { - - private final Object connection; - private final ApiQueryCounter apiQueryCounter; - - public ConnectionProxyHandler(final Object connection, final ApiQueryCounter apiQueryCounter) { - this.connection = connection; - this.apiQueryCounter = apiQueryCounter; - } - - @Override - public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { - Object invokeResult = method.invoke(connection, args); // (1) - if (method.getName().equals("prepareStatement")) { - return Proxy.newProxyInstance( - invokeResult.getClass().getClassLoader(), - invokeResult.getClass().getInterfaces(), - new PreparedStatementProxyHandler(invokeResult, apiQueryCounter) - ); - } - return invokeResult; - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/utils/querytracker/LoggingInterceptor.java b/src/main/java/com/gg/server/global/utils/querytracker/LoggingInterceptor.java deleted file mode 100644 index 95d8387e3..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/LoggingInterceptor.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -@Slf4j -@Component -public class LoggingInterceptor implements HandlerInterceptor { - - private static final String QUERY_COUNT_LOG_FORMAT = "STATUS_CODE: {}, METHOD: {}, URL: {}, QUERY_COUNT: {}"; - - private final ApiQueryCounter apiQueryCounter; - - public LoggingInterceptor(final ApiQueryCounter apiQueryCounter) { - this.apiQueryCounter = apiQueryCounter; - } - - @Override - public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, - final Object handler, final Exception ex) { - final int queryCount = apiQueryCounter.getCount(); - - log.info(QUERY_COUNT_LOG_FORMAT, response.getStatus(), request.getMethod(), request.getRequestURI(), - queryCount); - } -} \ No newline at end of file diff --git a/src/main/java/com/gg/server/global/utils/querytracker/PreparedStatementProxyHandler.java b/src/main/java/com/gg/server/global/utils/querytracker/PreparedStatementProxyHandler.java deleted file mode 100644 index 7dfff27a5..000000000 --- a/src/main/java/com/gg/server/global/utils/querytracker/PreparedStatementProxyHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gg.server.global.utils.querytracker; - -import org.springframework.cglib.proxy.InvocationHandler; -import org.springframework.web.context.request.RequestContextHolder; - -import java.lang.reflect.Method; -import java.util.Objects; - -public class PreparedStatementProxyHandler implements InvocationHandler { - - private final Object preparedStatement; - private final ApiQueryCounter apiQueryCounter; - - public PreparedStatementProxyHandler(final Object preparedStatement, final ApiQueryCounter apiQueryCounter) { - this.preparedStatement = preparedStatement; - this.apiQueryCounter = apiQueryCounter; - } - - @Override // (1) - public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { - if (isExecuteQuery(method) && isInRequestScope()) { // (2) - apiQueryCounter.increaseCount(); - } - return method.invoke(preparedStatement, args); // (3) - } - - private boolean isExecuteQuery(final Method method) { - String methodName = method.getName(); - return methodName.equals("executeQuery") || methodName.equals("execute") || methodName.equals("executeUpdate"); - } - - private boolean isInRequestScope() { - return Objects.nonNull(RequestContextHolder.getRequestAttributes()); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/ServerApplicationTests.java b/src/test/java/com/gg/server/ServerApplicationTests.java deleted file mode 100644 index 41edb5630..000000000 --- a/src/test/java/com/gg/server/ServerApplicationTests.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server; - -import com.gg.server.utils.annotation.IntegrationTest; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.TimeZone; - -@IntegrationTest -class ServerApplicationTests { - - @Test - void contextLoads() { - } - - @Test - @DisplayName("TimeZone Test") - public void TimeZoneTest() throws Exception { - TimeZone tz = TimeZone.getDefault(); - - Assertions.assertThat(tz.getID()).isEqualTo("Asia/Seoul"); - } -} diff --git a/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerFailTest.java b/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerFailTest.java deleted file mode 100644 index 69d181cf4..000000000 --- a/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerFailTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.gg.server.admin.announcement.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.announcement.data.AnnouncementAdminRepository; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -public class AnnouncementAdminControllerFailTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - AnnouncementAdminRepository announcementAdminRepository; - - @Test - @DisplayName("fail currentPage[Get]/pingpong/admin/announcement") - void failAnnouncementList1() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 0; - Integer pageSize = 5;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("fail pageSize[Get]/pingpong/admin/announcement") - void failAnnouncementList2() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 2; - Integer pageSize = 0;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } -} diff --git a/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerTest.java b/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerTest.java deleted file mode 100644 index d25c1b935..000000000 --- a/src/test/java/com/gg/server/admin/announcement/controller/AnnouncementAdminControllerTest.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.gg.server.admin.announcement.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.announcement.data.AnnouncementAdminRepository; -import com.gg.server.admin.announcement.dto.AnnouncementAdminAddDto; -import com.gg.server.admin.announcement.dto.AnnouncementAdminListResponseDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.announcement.exception.AnnounceNotFoundException; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class AnnouncementAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - AnnouncementAdminRepository announcementAdminRepository; - - @Test - @DisplayName("[Get]/pingpong/admin/announcement") - void getAnnouncementList() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 2; - Integer pageSize = 5;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/announcement?page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - //ResponseEntity announceListDtoResponse = objectMapper - // .readValue(contentAsString, new TypeReference>() {}); - //AnnouncementAdminListResponseDto announceListDto = announceListDtoResponse.getBody(); - AnnouncementAdminListResponseDto announceListDto = objectMapper.readValue(contentAsString, AnnouncementAdminListResponseDto.class); - - } - - @Test - @DisplayName("[Post]/pingpong/admin/announcement") - void addAnnouncement() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - testDataUtils.createAnnouncements(testDataUtils.createAdminUser(), 20); - //๊ณต์ง€์‚ฌํ•ญ 1๊ฐœ ์ •์ฑ… ๋•Œ๋ฌธ์— ๊ธฐ์กด ๊ณต์ง€์‚ฌํ•ญ ์ง€์šธ ๊ฒƒ - Announcement delDto = announcementAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new AnnounceNotFoundException()); - announcementAdminRepository.delete(delDto); - - AnnouncementAdminAddDto addDto = new AnnouncementAdminAddDto("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜", "testId"); - - String content = objectMapper.writeValueAsString(addDto); - String url = "/pingpong/admin/announcement"; - - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - Announcement result = announcementAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new AnnounceNotFoundException()); - - assertThat(result.getContent()).isEqualTo(addDto.getContent()); - assertThat(result.getCreatorIntraId()).isEqualTo(addDto.getCreatorIntraId()); - assertThat(result.getDeletedAt()).isNull(); - } - - @Test - @DisplayName("fail[Post]/pingpong/admin/announcement") - void addAnnouncementFail() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - AnnouncementAdminAddDto addDto = new AnnouncementAdminAddDto("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜", null); - - String content = objectMapper.writeValueAsString(addDto); - String url = "/pingpong/admin/announcement"; - - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - - } - - @Test - @DisplayName("[Put]/pingpong/admin/announcement") - void putAnnouncement() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - testDataUtils.createAnnouncement(testDataUtils.createAdminUser(), "testContent"); - - //๊ณต์ง€์‚ฌํ•ญ 1๊ฐœ ์ •์ฑ… ๋•Œ๋ฌธ์— ๊ธฐ์กด ๊ณต์ง€์‚ฌํ•ญ ์ง€์šธ ๊ฒƒ -// Announcement delDto = announcementAdminRepository.findFirstByOrderByIdDesc(); -// announcementAdminRepository.delete(delDto); - //๊ณต์ง€์‚ฌํ•ญ ์—†์œผ๋ฉด ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ณผ์ • ๋„ฃ์–ด ์ค„๊ฒƒ - - String url = "/pingpong/admin/announcement/"; - - String contentAsString = mockMvc.perform(delete(url + "deleterTestId") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - Announcement result = announcementAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new AnnounceNotFoundException()); - - assertThat(result.getDeleterIntraId()).isEqualTo("deleterTestId"); - assertThat(result.getDeletedAt()).isNotNull(); - System.out.println(result.getId()); - System.out.println(result.getDeleterIntraId()); - System.out.println(result.getDeletedAt()); - } - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java deleted file mode 100644 index 12136f17f..000000000 --- a/src/test/java/com/gg/server/admin/coin/controller/CoinAdminControllerTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gg.server.admin.coin.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.coin.dto.CoinUpdateRequestDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class CoinAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - UserRepository userRepository; - - @Test - @DisplayName("PUT /pingpong/admin/coin") - public void updateCoinTest() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String creatorId = userRepository.getById(userId).getIntraId(); - int beforeCoin = userRepository.getById(userId).getGgCoin(); - int changeCoin = 10; - CoinUpdateRequestDto coinUpdateRequestDto = new CoinUpdateRequestDto(creatorId, changeCoin, "๊ด€๋ฆฌ์ž ์ฝ”์ธ ์ง€๊ธ‰ ํ…Œ์ŠคํŠธ"); - mockMvc.perform(put("/pingpong/admin/coin").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(coinUpdateRequestDto))) - .andExpect(status().isNoContent()); - Assertions.assertThat(userRepository.getById(userId).getGgCoin()).isEqualTo(beforeCoin + changeCoin); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java deleted file mode 100644 index 9d1330471..000000000 --- a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerFailTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.gg.server.admin.coin.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; -import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -public class CoinPolicyAdminControllerFailTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - CoinPolicyAdminRepository coinPolicyAdminRepository; - - @Test - @DisplayName("[Post FAIL]/pingpong/admin/coinpolicy") - void addAnnouncement() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1,2,5,-1); - - String content = objectMapper.writeValueAsString(addDto); - String url = "/pingpong/admin/coinpolicy"; - - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } -} diff --git a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java b/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java deleted file mode 100644 index fdc351425..000000000 --- a/src/test/java/com/gg/server/admin/coin/controller/CoinPolicyAdminControllerTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.gg.server.admin.coin.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.coin.data.CoinPolicyAdminRepository; -import com.gg.server.admin.coin.dto.CoinPolicyAdminAddDto; -import com.gg.server.admin.coin.dto.CoinPolicyAdminListResponseDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.coin.data.CoinPolicy; -import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.util.stream.IntStream; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class CoinPolicyAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - CoinPolicyAdminRepository coinPolicyAdminRepository; - - @Test - @DisplayName("[Get]/pingpong/admin/coinpolicy") - void getCoinPolicy() throws Exception { - User admin = testDataUtils.createAdminUser(); - IntStream.range(0, 3).forEach(i -> testDataUtils - .createCoinPolicy(admin, 1, 2, 3, 4)); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Integer currentPage = 1; - Integer pageSize = 5;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/coinpolicy?page=" + currentPage + "&size=" + pageSize; - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - CoinPolicyAdminListResponseDto result = objectMapper.readValue(contentAsString, CoinPolicyAdminListResponseDto.class); - assertThat(result.getCoinPolicyList().size()).isEqualTo(3); - System.out.println(result.getCoinPolicyList().get(0).getCoinPolicyId()); - System.out.println(result.getCoinPolicyList().get(0).getCreateUserId()); - System.out.println(result.getCoinPolicyList().get(0).getAttendance()); - System.out.println(result.getCoinPolicyList().get(0).getNormal()); - System.out.println(result.getCoinPolicyList().get(0).getRankWin()); - System.out.println(result.getCoinPolicyList().get(0).getRankLose()); - - } - - @Test - @DisplayName("[Post]/pingpong/admin/coinpolicy") - void addCoinPolicy() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - CoinPolicyAdminAddDto addDto = new CoinPolicyAdminAddDto(1,2,5,0); - - String content = objectMapper.writeValueAsString(addDto); - String url = "/pingpong/admin/coinpolicy"; - - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - CoinPolicy result = coinPolicyAdminRepository.findFirstByOrderByIdDesc().orElseThrow(()-> new CoinPolicyNotFoundException()); - - assertThat(result.getAttendance()).isEqualTo(addDto.getAttendance()); - assertThat(result.getNormal()).isEqualTo(addDto.getNormal()); - assertThat(result.getRankWin()).isEqualTo(addDto.getRankWin()); - assertThat(result.getRankLose()).isEqualTo(addDto.getRankLose()); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java b/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java deleted file mode 100644 index 05ac3012e..000000000 --- a/src/test/java/com/gg/server/admin/feedback/controller/FeedbackAdminControllerTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.gg.server.admin.feedback.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.feedback.data.FeedbackAdminRepository; -import com.gg.server.admin.feedback.dto.FeedbackListAdminResponseDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class FeedbackAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - FeedbackAdminRepository feedbackAdminRepository; - @Autowired - UserRepository userRepository; - - @Test - @DisplayName("[Get]/pingpong/admin/feedback") - void getFeedback() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - - for (int i = 0; i < 6; i++) { - Feedback feedback = Feedback.builder() - .category(FeedbackType.ETC) - .content("test" + i) - .user(testDataUtils.createNewUser()) - .build(); - feedbackAdminRepository.save(feedback); - } - - Integer currentPage = 1; - Integer pageSize = 5;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/feedback?page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - - FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); - assertThat(result.getFeedbackList().size()).isEqualTo(5); - System.out.println(result.getFeedbackList().get(0).getId()); - System.out.println(result.getFeedbackList().get(0).getContent()); - - } - - @Test - @DisplayName("[Patch]pingpong/admin/feedback/{id}") - void patchFeedback() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Feedback feedback = Feedback.builder() - .category(FeedbackType.ETC) - .content("test1234") - .user(userRepository.findById(userId).get()) - .build(); - feedbackAdminRepository.save(feedback); - - String url = "/pingpong/admin/feedback/" + feedback.getId().toString(); - Boolean status = feedback.getIsSolved(); - - String contentAsString = mockMvc.perform(patch(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - - } - - @Test - @DisplayName("[get]pingpong/admin/feedback?intraId=${intraId}&page=${pageNumber}&size={size}") - void findFeedbackByIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - User user = userRepository.findById(userId).get(); - - Feedback feedback = Feedback.builder() - .category(FeedbackType.ETC) - .content("test1234") - .user(user) - .build(); - feedbackAdminRepository.save(feedback); - - Integer currentPage = 1; - Integer pageSize = 5;//ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ํฌ๊ธฐ๊ฐ€ ์‹ค์ œ ๋””๋น„ ์ •๋ณด๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•  ๊ฒƒ - - String url = "/pingpong/admin/feedback?intraId=" + user.getIntraId() + "&page=" + currentPage + "&size=" + pageSize; - Boolean status = feedback.getIsSolved(); - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - FeedbackListAdminResponseDto result = objectMapper.readValue(contentAsString, FeedbackListAdminResponseDto.class); - assertThat(result.getFeedbackList().size()).isBetween(0, 5); - assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); - assertThat(result.getFeedbackList().get(0).getContent()).isEqualTo("test1234"); - assertThat(result.getFeedbackList().get(0).getIntraId()).isEqualTo(user.getIntraId()); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java b/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java deleted file mode 100644 index 8bb1bf9dc..000000000 --- a/src/test/java/com/gg/server/admin/game/controller/GameAdminControllerTest.java +++ /dev/null @@ -1,269 +0,0 @@ -package com.gg.server.admin.game.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.game.dto.GameLogListAdminResponseDto; -import com.gg.server.admin.game.dto.RankGamePPPModifyReqDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.dto.request.RankResultReqDto; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.service.GameUpdateService; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.util.ArrayList; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; - -import static java.lang.Thread.sleep; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -@DisplayName("[Admin] Game Admin Controller Integration Test") -class GameAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - GameRepository gameRepository; - - @Autowired - UserRepository userRepository; - - @Autowired - GameUpdateService gameUpdateService; - - @Autowired - GameService gameService; - - @Autowired - RankRepository rankRepository; - - @Autowired - RankRedisRepository rankRedisRepository; - - @AfterEach - void redisDown() { - rankRedisRepository.deleteAll(); - } - - @Nested - @DisplayName("[GET] /pingpong/admin/games/users?intraId=${intraId}&page=${pageNumber}&size={sizeNum}") - class GetUserGameList { - String accessToken; - Long userId; - User user; - Season season; - - static final int TOTAL_PAGE_SIZE = 18; - static final int TOURNAMENT_GAME_SIZE = 4; - static final String INTRA_ID = "nheo"; - - @BeforeEach - void setUp() { - accessToken = testDataUtils.getAdminLoginAccessToken(); - userId = tokenProvider.getUserIdFromAccessToken(accessToken); - user = testDataUtils.createNewUser(INTRA_ID); - season = testDataUtils.createSeason(); - testDataUtils.createUserRank(user, "status message", season); - for (int i = 0; i < TOTAL_PAGE_SIZE; i++) { - testDataUtils.createMockMatchWithMockRank(user, season, LocalDateTime.now().minusMinutes(20 + i * 15), LocalDateTime.now().minusMinutes(5 + i * 15)); - } - for (int i = TOTAL_PAGE_SIZE; i< TOTAL_PAGE_SIZE + TOURNAMENT_GAME_SIZE; i++) { - testDataUtils.createMockMatch(testDataUtils.createNewUser("testUser"+i), season, - LocalDateTime.now().minusMinutes(20 + i * 15), LocalDateTime.now().minusMinutes(5 + i * 15), Mode.TOURNAMENT); - } - } - private GameLogListAdminResponseDto getPageResult(int currentPage, int pageSize) - throws Exception { - String url = "/pingpong/admin/games/users?intraId=" - + INTRA_ID + "&page=" + currentPage + "&size=" + pageSize; - - String contentAsString = mockMvc - .perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - return objectMapper.readValue(contentAsString, GameLogListAdminResponseDto.class); - } - @Test - @Transactional - @DisplayName("First page") - void getUserGameListFirstPage() throws Exception { - //given - int pageSize = 5; - //when - GameLogListAdminResponseDto result = getPageResult(1, pageSize); - //then - assertThat(result.getGameLogList().size()).isEqualTo(pageSize); - } - - @Test - @Transactional - @DisplayName("Middle page") - void getUserGameListMidPage() throws Exception { - //given - int pageSize = 5; - //when - GameLogListAdminResponseDto result = getPageResult(2, pageSize); - //then - assertThat(result.getGameLogList().size()).isEqualTo(pageSize); - } - - @Test - @Transactional - @DisplayName("End page") - void getUserGameListEndPage() throws Exception { - //given - int pageSize = 5; - //when - GameLogListAdminResponseDto result = getPageResult(4, pageSize); - //then - assertThat(result.getGameLogList().size()).isEqualTo(TOTAL_PAGE_SIZE % pageSize); - } - } - - @Test - @DisplayName("[PUT] /pingpong/admin/games") - @Transactional - public void ๊ด€๋ฆฌ์ž๊ฒŒ์ž„์ „์ ์ˆ˜์ •ํ…Œ์ŠคํŠธ() throws Exception { - String url = "/pingpong/admin/games"; - Mode currentMatchMode = Mode.RANK; - Season season = testDataUtils.createSeason(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long adminUserId = tokenProvider.getUserIdFromAccessToken(accessToken); - User adminUser = userRepository.findById(adminUserId).get(); - ArrayList tierList = testDataUtils.createTierSystem("pinpong"); - GameInfoDto game1Info = testDataUtils.createGameWithTierAndRank(adminUser, LocalDateTime.now().minusMinutes(5), LocalDateTime.now().plusMinutes(5), season, currentMatchMode, tierList.get(0)); - - User enemyUser1 = userRepository.findById(game1Info.getEnemyUserId()).get(); - - RankResultReqDto rankResultReqDto = new RankResultReqDto(game1Info.getGameId(), - game1Info.getMyTeamId(), - 2, - game1Info.getEnemyTeamId(), - 1); - gameService.createRankResult(rankResultReqDto, adminUserId); - - Rank adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - Rank enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), - season.getId()).get(); - // win 1, losses 0, ppp 1020 -// System.out.println("MANGO ADMIN1 before DB PPP : " + adminUserRank.getPpp()); - assertThat(adminUserRank.getLosses()).isEqualTo(0); - assertThat(adminUserRank.getWins()).isEqualTo(1); - // win 0, losses 1, ppp 982 -// System.out.println("MANGO ENEMY1 before DB PPP : " + enemyUser1Rank.getPpp()); - assertThat(enemyUser1Rank.getWins()).isEqualTo(0); - assertThat(enemyUser1Rank.getLosses()).isEqualTo(1); - - RankGamePPPModifyReqDto modifyReqDto = new RankGamePPPModifyReqDto(game1Info.getMyTeamId(), 1, game1Info.getEnemyTeamId(), 0); - mockMvc.perform(put("/pingpong/admin/games/" + game1Info.getGameId()) - .content(objectMapper.writeValueAsString(modifyReqDto)) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - GameTeamUser historyGame1 = gameRepository.findTeamsByGameIsIn(List.of(game1Info.getGameId())).get(0); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - enemyUser1Rank = rankRepository.findByUserIdAndSeasonId(enemyUser1.getId(), season.getId()) - .get(); - // win 1, losses 0, ppp 1020 - // MANGO ADMIN1 after DB - assertThat(adminUserRank.getPpp()).isEqualTo(1020); - assertThat(adminUserRank.getWins()).isEqualTo(1); - assertThat(adminUserRank.getLosses()).isEqualTo(0); - // win 0, losses 1, ppp 982 - // MANGO ENEMY1 after DB - assertThat(enemyUser1Rank.getWins()).isEqualTo(0); - assertThat(enemyUser1Rank.getLosses()).isEqualTo(1); - assertThat(enemyUser1Rank.getPpp()).isEqualTo(982); - ////////////////////////////// - sleep(1000); - ////////////////////////////// - GameInfoDto game2Info = testDataUtils.createGameWithTierAndRank(adminUser, LocalDateTime.now().minusMinutes(4), LocalDateTime.now().plusMinutes(6), season, currentMatchMode, tierList.get(0)); - User enemyUser2 = userRepository.findById(game2Info.getEnemyUserId()).get(); - - rankResultReqDto = new RankResultReqDto(game2Info.getGameId(), - game2Info.getMyTeamId(), - 1, - game2Info.getEnemyTeamId(), - 2); - gameService.createRankResult(rankResultReqDto, adminUserId); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - Rank enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), - season.getId()).get(); - // win 1, losses 1, ppp 1001 - // MANGO ADMIN2 before DB - assertThat(adminUserRank.getWins()).isEqualTo(1); - assertThat(adminUserRank.getLosses()).isEqualTo(1); - assertThat(adminUserRank.getPpp()).isEqualTo(1001); - // win1, losses 0, ppp 1021 - // MANGO ENEMY2 before DB - assertThat(enemyUser2Rank.getWins()).isEqualTo(1); - assertThat(enemyUser2Rank.getLosses()).isEqualTo(0); - assertThat(enemyUser2Rank.getPpp()).isEqualTo(1021); - - modifyReqDto = new RankGamePPPModifyReqDto(game2Info.getMyTeamId(), 2, game2Info.getEnemyTeamId(), 1); - mockMvc.perform(put("/pingpong/admin/games/" + game2Info.getGameId()) - .content(objectMapper.writeValueAsString(modifyReqDto)) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - adminUserRank = rankRepository.findByUserIdAndSeasonId(adminUserId, season.getId()).get(); - enemyUser2Rank = rankRepository.findByUserIdAndSeasonId(enemyUser2.getId(), season.getId()).get(); - // win 2, losses 0, ppp 1038 -// System.out.println("MANGO ADMIN2 after DB PPP : " + adminUserRank.getPpp() + ", WIN: " -// + adminUserRank.getWins() + ", LOSSES" + adminUserRank.getLosses()); - assertThat(adminUserRank.getWins()).isEqualTo(2); - assertThat(adminUserRank.getLosses()).isEqualTo(0); - assertThat(adminUserRank.getPpp()).isEqualTo(1038); - // win 0, losses 1, ppp - System.out.println("MANGO ENEMY2 after DB PPP : " + enemyUser2Rank.getPpp() + ", WIN: " - + enemyUser2Rank.getWins() + ", LOSSES" + enemyUser2Rank.getLosses()); - assertThat(enemyUser2Rank.getWins()).isEqualTo(0); - assertThat(enemyUser2Rank.getLosses()).isEqualTo(1); -// assertThat(enemyUser2Rank.getPpp()).isEqualTo() - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java b/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java deleted file mode 100644 index 9bb2a6c13..000000000 --- a/src/test/java/com/gg/server/admin/item/controller/ItemAdminControllerTest.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.gg.server.admin.item.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.item.data.ItemAdminRepository; -import com.gg.server.admin.item.dto.ItemListResponseDto; -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.admin.item.service.ItemAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.utils.ItemImageHandler; -import com.gg.server.utils.ItemTestUtils; -import com.gg.server.utils.TestDataUtils; -import java.util.List; -import javax.transaction.Transactional; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.web.servlet.MockMvc; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class ItemAdminControllerTest { - @Autowired - ItemAdminService itemAdminService; - @Autowired - UserRepository userRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - ItemAdminRepository itemAdminRepository; - @Autowired - MockMvc mockMvc; - @Autowired - ItemTestUtils itemTestUtils; - @MockBean - ItemImageHandler ItemImageHandler; - - Item item; - @BeforeEach - void setUp() { - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "content", - "subContent", 100, 50, ItemType.EDGE); - item = itemTestUtils.createItem(testDataUtils.createAdminUserForItem(), dto); - } - - @Test - @DisplayName("GET /pingpong/admin/items/history") - public void getAllItemHistoryTest() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Integer page = 1; - Integer size = 20; - String url = "/pingpong/admin/items/history?page=" + page + "&size=" + size; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - ItemListResponseDto expect = itemAdminService.getAllItemHistory(pageable); - System.out.println(expect.getHistoryList()); - ItemListResponseDto result = objectMapper.readValue(contentAsString, ItemListResponseDto.class); - System.out.println(expect.getHistoryList().get(0)); - System.out.println(result.getHistoryList().get(0)); - assertThat(result.getHistoryList().get(0).getItemId()); - assertThat(result.getHistoryList().get(0).getName()); - assertThat(result.getHistoryList().get(0).getMainContent()); - assertThat(result.getHistoryList().get(0).getSubContent()); - assertThat(result.getHistoryList().get(0).getPrice()); - } - - @Test - @DisplayName("POST /pingpong/admin/items/history/{itemId}") - public void updateItemTest() throws Exception { - Mockito.when(ItemImageHandler.uploadToS3(Mockito.any(), Mockito.anyString())) - .thenAnswer(invocation -> invocation.getArgument(1, String.class)); - - - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String creatorId = userRepository.getById(userId).getIntraId(); - MockMultipartFile image = new MockMultipartFile("imgData", "imagefile.jpeg", "image/jpeg", "<>".getBytes()); - MockMultipartFile jsonFile = new MockMultipartFile("updateItemInfo", "", - "application/json", - ("{\"name\": \"TEST\", " - + "\"mainContent\": \"TESTING\", " - + "\"subContent\": \"TESTING\", " - + "\"price\": 42, " - + "\"discount\": 50, " - + "\"itemType\": \"MEGAPHONE\"}").getBytes()); - String contentAsString = mockMvc.perform(multipart("/pingpong/admin/items/{itemId}", item.getId()) - .file(image) - .file(jsonFile) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("DELETE /pingpong/admin/items/{itemId}") - public void deleteItemTest() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String deleterId = userRepository.getById(userId).getIntraId(); - - String contentAsString = mockMvc.perform(delete("/pingpong/admin/items/{itemId}", item.getId()) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - List list = itemAdminRepository.findAll(); - assertThat(list.get(0).getDeleterIntraId()).isEqualTo(deleterId); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java b/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java deleted file mode 100644 index d227592b7..000000000 --- a/src/test/java/com/gg/server/admin/megaphone/controller/MegaphoneAdminControllerTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gg.server.admin.megaphone.controller; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import javax.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class MegaphoneAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - AuthTokenProvider tokenProvider; - - @Test - @DisplayName("[GET] /pingpong/admin/megaphones/history?page={page}&size={pageSize}&intraId={intraId}") - void getMegaphoneListTest() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/admin/megaphones/history?page=1&size=30"; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java b/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java deleted file mode 100644 index 1bc7d42ce..000000000 --- a/src/test/java/com/gg/server/admin/noti/controller/NotiAdminControllerTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.gg.server.admin.noti.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.noti.data.NotiAdminRepository; -import com.gg.server.admin.noti.dto.NotiAdminDto; -import com.gg.server.admin.noti.dto.NotiListAdminResponseDto; -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import javax.transaction.Transactional; - -import java.util.List; -import java.util.UUID; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -class NotiAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - NotiAdminService notiAdminService; - @Autowired - NotiAdminRepository notiAdminRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - - @Test - @DisplayName("GET /pingpong/admin/notifications") - @Transactional - public void getAllNotiTest() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - String testMessage = "Test notification"; - notiAdminService.sendAnnounceNotiToUser(new SendNotiAdminRequestDto(user.getIntraId(), testMessage)); - String url = "/pingpong/admin/notifications?page=1&size=20"; - String url2 = "/pingpong/admin/notifications?page=1&q=\"" + user.getIntraId() + "\""; - - //when - //200 ์„ฑ๊ณต(์ „์ฒด์กฐํšŒ) - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); - //200 ์„ฑ๊ณต(๊ฒ€์ƒ‰์กฐํšŒ) - String contentAsString2 = mockMvc.perform(get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, NotiListAdminResponseDto.class); - Pageable pageable = PageRequest.of(0, 20); - Sort.by("createdAt").descending().and(Sort.by("user.intraId").ascending()); - - //then - List notiList1 = notiAdminRepository.findAll(pageable).getContent(); - List expectedNotiAdminDtoList = actureResponse1.getNotiList(); - for (int i = 0; i < notiList1.size(); i++) { - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIntraId()).isEqualTo(expectedNotiAdminDtoList.get(i).getIntraId()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getMessage()).isEqualTo(expectedNotiAdminDtoList.get(i).getMessage()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getIsChecked()).isEqualTo(expectedNotiAdminDtoList.get(i).getIsChecked()); - Assertions.assertThat(expectedNotiAdminDtoList.get(i).getType()).isEqualTo(expectedNotiAdminDtoList.get(i).getType()); - } - - List notiList2 = notiRepository.findByUser(user); - Assertions.assertThat(notiList2.size()).isEqualTo(1); - Noti expectedNoti2 = notiList2.get(0); - NotiAdminDto actureNotiResponseDto2 = actureResponse2.getNotiList().get(0); - Assertions.assertThat(expectedNoti2.getUser().getIntraId()).isEqualTo(actureNotiResponseDto2.getIntraId()); - Assertions.assertThat(expectedNoti2.getMessage()).isEqualTo(testMessage); - Assertions.assertThat(expectedNoti2.getIsChecked()).isFalse(); - Assertions.assertThat(expectedNoti2.getType()).isEqualTo(NotiType.ANNOUNCE); - } - - @Test - @DisplayName("POST /pingpong/admin/notifications") - @Transactional - public void sendNotiToUserTest() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - String url = "/pingpong/admin/notifications"; - String wrongIntraId = UUID.randomUUID().toString().substring(0, 30); - String expectedMessage = "test ์•Œ๋ฆผ message "; - - //when - //201 ์„ฑ๊ณต - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(user.getIntraId(), expectedMessage)))) - .andExpect(status().isCreated()); - - //404 ์กด์žฌํ•˜์ง€ ์•Š๋Š” intraId - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new SendNotiAdminRequestDto(wrongIntraId, expectedMessage)))) - .andExpect(status().isNotFound()); - - //then - List notiList = notiRepository.findByUser(user); - Assertions.assertThat(notiList.size()).isEqualTo(1); - Noti actureNoti = notiList.get(0); - Assertions.assertThat(actureNoti.getUser()).isEqualTo(user); - Assertions.assertThat(actureNoti.getMessage()).isEqualTo(expectedMessage); - Assertions.assertThat(actureNoti.getIsChecked()).isFalse(); - Assertions.assertThat(actureNoti.getType()).isEqualTo(NotiType.ANNOUNCE); - } -} diff --git a/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java b/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java deleted file mode 100644 index 59d2efca6..000000000 --- a/src/test/java/com/gg/server/admin/penalty/controller/PenaltyAdminControllerTest.java +++ /dev/null @@ -1,352 +0,0 @@ -package com.gg.server.admin.penalty.controller; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.admin.penalty.data.PenaltyUserAdminRedisRepository; -import com.gg.server.admin.penalty.dto.PenaltyListResponseDto; -import com.gg.server.admin.penalty.dto.PenaltyRequestDto; -import com.gg.server.admin.penalty.service.PenaltyAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.penalty.data.Penalty; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.domain.penalty.type.PenaltyType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class PenaltyAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @Autowired - UserRepository userRepository; - @Autowired - PenaltyUserAdminRedisRepository penaltyUserAdminRedisRepository; - @Autowired - PenaltyAdminRepository penaltyAdminRepository; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - RedisConnectionFactory redisConnectionFactory; - @Autowired - PenaltyAdminService penaltyAdminService; - - private final String headUrl = "/pingpong/admin/"; - - @AfterEach - void clear() { - RedisConnection connection = redisConnectionFactory.getConnection(); - connection.flushDb(); - connection.close(); - } - - @Test - @DisplayName("POST : penalty๋ฅผ ๋ถ€์—ฌ๋ฐ›์ง€ ์•Š์€ ์œ ํšจํ•œ intraId์— penalty ๋ถ€์—ฌ") - public void giveUserPenaltyforFirstTimeWithValidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty"; - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().isCreated()); - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - //redis - Assertions.assertThat(penaltyUser).isPresent(); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(3 * 60); - Assertions.assertThat( - Duration.between(penaltyUser.get().getStartTime(), - penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(3 * 60 * 60); - Assertions.assertThat(penaltyUser.get().getReason()); - //mySQL - List penalties = penaltyAdminRepository.findAll(); - Assertions.assertThat(penalties.stream().anyMatch(ele -> ele.getUser().getIntraId().equals(intraId) - && ele.getPenaltyTime().equals(3 * 60))).isEqualTo(true); - } - - @Test - @DisplayName("POST : penalty๋ฅผ ๋ถ€์—ฌ๋ฐ›์€ ์œ ํšจํ•œ intraId์— penalty ๋ถ€์—ฌ") - public void giveUserPenaltyRepeatablyWithValidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty"; - //ํŒจ๋„ํ‹ฐ ๋‘๋ฒˆ ๋ถ€์—ฌ - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().isCreated()); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 2, "test2")))) - .andExpect(status().isCreated()); - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - //redis ํ™•์ธ - Assertions.assertThat(penaltyUser).isPresent(); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(5 * 60); - Assertions.assertThat( - Duration.between(penaltyUser.get().getStartTime(), - penaltyUser.get().getReleaseTime()).getSeconds()).isEqualTo(5 * 60 * 60); - Assertions.assertThat(penaltyUser.get().getReason()); - //mySQL ํ™•์ธ - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Assertions.assertThat(userPenalties.size()).isEqualTo(2); - Duration duration = Duration.between(userPenalties.get(0).getStartTime(), userPenalties.get(1).getStartTime()); - Assertions.assertThat(duration.getSeconds()).isEqualTo(3 * 60 * 60); - } - - - @Test - @DisplayName("POST ์œ ํšจํ•˜์ง€ ์•Š์€ intraId์— penalty ๋ถ€์—ฌ") - public void giveUserPenaltyWithInvalidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - String intraId = "invalid!"; - String url = "/pingpong/admin/penalty"; - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new PenaltyRequestDto(intraId, 3, "test1")))) - .andExpect(status().is4xxClientError()); - } - - @Test - @DisplayName("GET pagination ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") - public void checkPagination() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 20๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ - for (int i = 0; i < 20; i++) { - User newUser = testDataUtils.createNewUser(); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } - - @Test - @DisplayName("GET parameter ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") - public void checkInputException() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/admin/penalty?page=-1&size=10¤t=false"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); - String url2 = "/pingpong/admin/penalty?page=2&size=0¤t=false"; - String contentAsString2 = mockMvc.perform( - get(url2).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()).andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("GET pagination keyword ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ") - public void checkPaginationWithKeyword() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 40๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ - //๊ทธ์ค‘ 20๋ช…๋งŒ intraId์— testํฌํ•จ - for (int i = 0; i < 20; i++) { - String intraId = UUID.randomUUID().toString().substring(0, 4) + "test" + UUID.randomUUID().toString() - .substring(0, 4); - User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, - RoleType.USER); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - for (int i = 0; i < 20; i++) { - String intraId = "dummy" + String.valueOf(i); - User newUser = testDataUtils.createNewUser(intraId, "test", RacketType.NONE, SnsType.EMAIL, - RoleType.USER); - users.add(newUser); - penaltyAdminService.givePenalty(newUser.getIntraId(), 3, "test" + String.valueOf(i)); - } - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true&intraId=test"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } - - @Test - @DisplayName("DELETE ํŒจ๋„ํ‹ฐ ์‚ญ์ œ - ์œ ์ € ํŒจ๋„ํ‹ฐ๊ฐ€ 1๋ฒˆ๋งŒ ๋ถ€๊ณผ๋œ ๊ฒฝ์šฐ") - public void deleteExistPenaltyUser() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - penaltyAdminService.givePenalty(intraId, 3, "test!"); - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Long penaltyId = userPenalties.get(0).getId(); - String url = "/pingpong/admin/penalty/" + penaltyId.toString(); - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()); - //Redis์— penaltyUser ์—†๋Š”์ง€ ํ™•์ธ - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - Assertions.assertThat(penaltyUser).isEmpty(); - //MySQL์— penalty ์—†๋Š”์ง€ ํ™•์ธ - List afterPenalties = penaltyAdminRepository.findAll(); - boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); - Assertions.assertThat(isPresent).isEqualTo(false); - } - - @Test - @DisplayName("DELETE ํŒจ๋„ํ‹ฐ ์‚ญ์ œ - ์œ ์ € ํŒจ๋„ํ‹ฐ๊ฐ€ 2๋ฒˆ ๋ถ€๊ณผ๋œ ๊ฒฝ์šฐ") - public void deleteExistPenaltyUserOfTwicePenalty() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - penaltyAdminService.givePenalty(intraId, 3, "test!"); - penaltyAdminService.givePenalty(intraId, 2, "test2"); - List penalties = penaltyAdminRepository.findAll(); - List userPenalties = penalties.stream().filter(ele -> ele.getUser().getIntraId().equals(intraId)) - .collect(Collectors.toList()); - Long penaltyId = userPenalties.get(0).getId(); - String url = "/pingpong/admin/penalty/" + penaltyId.toString(); - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()); - //Redis์— penaltyUser ์žˆ๋Š”์ง€ ํ™•์ธ - Optional penaltyUser = penaltyUserAdminRedisRepository.findByIntraId(intraId); - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(2 * 60); - - //MySQL์— penalty ์—†๋Š”์ง€ ํ™•์ธ - List afterPenalties = penaltyAdminRepository.findAll(); - boolean isPresent = afterPenalties.stream().anyMatch(ele -> ele.getId().equals(penaltyId)); - Assertions.assertThat(isPresent).isEqualTo(false); - } - - @Test - @DisplayName("DELETE ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒจ๋„ํ‹ฐ ์œ ์ € ์‚ญ์ œ") - public void deleteInvalidPenaltyUser() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //user์— ํŒจ๋„ํ‹ฐ๋Š” ๋ถ€์—ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. - User newUser = testDataUtils.createNewUser(); - String intraId = newUser.getIntraId(); - String url = "/pingpong/admin/penalty/users/" + intraId; - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()); - } - - @Test - @DisplayName("DELETE ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒจ๋„ํ‹ฐ ์œ ์ € ์‚ญ์ œ") - public void deleteInvalidIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //30์ž ์ด์ƒ - String intraId = UUID.randomUUID().toString(); - String url = "/pingpong/admin/penalty/users/" + intraId; - mockMvc.perform( - delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()); - } - - @Test - @DisplayName("get pingpong/admin/penalty?page={page}&size={pageSize}¤t=true") - public void getCurrentPenalties() throws Exception { - List users = new ArrayList(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - //penalty user 20๋ช… ๋„ฃ๊ณ  ํ…Œ์ŠคํŠธ - for (int i = 0; i < 20; i++) { - User newUser = testDataUtils.createNewUser(); - users.add(newUser); - } - - //๊ณผ๊ฑฐ penalty๋“ค db์— ์ €์žฅ - for (int i = 0; i < 20; i++) { - Penalty penalty = new Penalty(users.get(i), PenaltyType.NOSHOW, "test", LocalDateTime.now().minusHours(3), 120); - penaltyAdminRepository.save(penalty); - } - - //ํ˜„์žฌ ํŒจ๋„ํ‹ฐ ๋ถ€์—ฌ - for (int i = 0; i < 20; i++) { - penaltyAdminService.givePenalty(users.get(i).getIntraId(), 3, "test" + String.valueOf(i)); - } - - - - List sizeCounts = new ArrayList(); - Integer totalPages = -1; - for (int i = 1; i <= 3; i++) { - String url = "/pingpong/admin/penalty?page=" + String.valueOf(i)+"&size=10¤t=true"; - String contentAsString = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); - PenaltyListResponseDto penaltyListResponseDto = objectMapper.readValue(contentAsString, - PenaltyListResponseDto.class); - sizeCounts.add(penaltyListResponseDto.getPenaltyList().size()); - totalPages = penaltyListResponseDto.getTotalPage(); - } - Assertions.assertThat(sizeCounts).isEqualTo(List.of(10, 10, 0)); - Assertions.assertThat(totalPages).isEqualTo(2); - } -} diff --git a/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java b/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java deleted file mode 100644 index 2faf794e4..000000000 --- a/src/test/java/com/gg/server/admin/receipt/controller/ReceiptAdminControllerTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.gg.server.admin.receipt.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.admin.receipt.data.ReceiptAdminRepository; -import com.gg.server.admin.receipt.dto.ReceiptListResponseDto; -import com.gg.server.admin.receipt.service.ReceiptAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.ItemTestUtils; -import com.gg.server.utils.TestDataUtils; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class ReceiptAdminControllerTest { - @Autowired - ReceiptAdminService receiptAdminService; - @Autowired - ReceiptAdminRepository receiptAdminRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - MockMvc mockMvc; - @Autowired - ItemTestUtils itemTestUtils; - Item item; - User user; - @BeforeEach - void setUp() { - user = testDataUtils.createNewUser(); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", "subContent", - 100, 50, ItemType.EDGE); - item = itemTestUtils.createItem(testDataUtils.createAdminUserForItem(), dto); - } - - @Test - @DisplayName("GET /pingpong/admin/receipt") - public void getAllReceipt() throws Exception { - itemTestUtils.purchaseItem(user, user, item); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Integer page = 1; - Integer size = 20; - String url = "/pingpong/admin/receipt?page=" + page + "&size=" + size; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - ReceiptListResponseDto expect = receiptAdminService.getAllReceipt(pageable); - ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); - assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo(expect.getReceiptList().get(0).getReceiptId()); - assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo(expect.getReceiptList().get(0).getCreatedAt()); - assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo(expect.getReceiptList().get(0).getItemName()); - assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo(expect.getReceiptList().get(0).getItemPrice()); - assertThat(result.getReceiptList().size()).isEqualTo(expect.getReceiptList().size()); - assertThat(result.getReceiptList().size()).isEqualTo(1); - } - - @Test - @DisplayName("GET /pingpong/admin/receipt") - public void findByIntraId() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Integer page = 1; - Integer size = 20; - User targetUser = testDataUtils.createNewUser("david"); - itemTestUtils.purchaseItem(user, user, item); - itemTestUtils.purchaseItem(targetUser, targetUser, item); - - String url = "/pingpong/admin/receipt?page=" + page + "&size=" + size + "&intraId=" + targetUser.getIntraId(); - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - ReceiptListResponseDto expect = receiptAdminService.findByIntraId(targetUser.getIntraId(), pageable); - ReceiptListResponseDto result = objectMapper.readValue(contentAsString, ReceiptListResponseDto.class); - assertThat(result.getReceiptList().get(0).getReceiptId()).isEqualTo(expect.getReceiptList().get(0).getReceiptId()); - assertThat(result.getReceiptList().get(0).getCreatedAt()).isEqualTo(expect.getReceiptList().get(0).getCreatedAt()); - assertThat(result.getReceiptList().get(0).getItemName()).isEqualTo(expect.getReceiptList().get(0).getItemName()); - assertThat(result.getReceiptList().get(0).getItemPrice()).isEqualTo(expect.getReceiptList().get(0).getItemPrice()); - assertThat(result.getReceiptList().size()).isEqualTo(expect.getReceiptList().size()); - assertThat(result.getReceiptList().size()).isEqualTo(1); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java b/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java deleted file mode 100644 index ee80537de..000000000 --- a/src/test/java/com/gg/server/admin/season/SeasonAdminControllerTest.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.gg.server.admin.season; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.rank.service.RankAdminService; -import com.gg.server.admin.rank.service.RankRedisAdminService; -import com.gg.server.admin.season.data.SeasonAdminRepository; -import com.gg.server.admin.season.dto.SeasonAdminDto; -import com.gg.server.admin.season.dto.SeasonCreateRequestDto; -import com.gg.server.admin.season.dto.SeasonListAdminResponseDto; -import com.gg.server.admin.season.dto.SeasonUpdateRequestDto; -import com.gg.server.admin.season.service.SeasonAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.exception.SeasonForbiddenException; -import com.gg.server.domain.season.exception.SeasonNotFoundException; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import com.google.common.net.HttpHeaders; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class SeasonAdminControllerTest { - @Autowired - MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - private SeasonAdminRepository seasonAdminRepository; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - RankRepository rankRepository; - - @Autowired - RankRedisRepository rankRedisRepository; - - @Autowired - SeasonAdminService seasonAdminService; - - @Autowired - RankAdminService rankAdminService; - - @Autowired - RankRedisAdminService rankRedisAdminService; - - SeasonListAdminResponseDto responseDto; - Long dbSeasonId; - - - @AfterEach - void tearDown() { - rankRedisRepository.deleteAll(); - } - - @Test - @DisplayName("[GET]pingpong/admin/seasons") - void getAdminSeasons() throws Exception { - testDataUtils.createTierSystem("pingpong"); - testDataUtils.createSeason(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - String contentAsString = mockMvc.perform(MockMvcRequestBuilders.get("/pingpong/admin/seasons") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - SeasonListAdminResponseDto seasonListAdminResponseDto = objectMapper.readValue(contentAsString, SeasonListAdminResponseDto.class); - System.out.println(seasonListAdminResponseDto.getSeasonList().size()); - } - - @Test - @DisplayName("[POST]/pingpong/admin/seasons") - void createSeasons() throws Exception { - List pingpong = testDataUtils.createTierSystem("pingpong"); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - SeasonCreateRequestDto seasonCreateReqeustDto = new SeasonCreateRequestDto( - "redis1", - LocalDateTime.now().plusHours(25), - 1000, - 500); - String content = objectMapper.writeValueAsString(seasonCreateReqeustDto); - - String contentAsString = mockMvc.perform(MockMvcRequestBuilders.post("/pingpong/admin/seasons") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - dbSeasonId = rankRepository.findFirstByOrderByCreatedAtDesc().get().getSeason().getId(); - String redisHashKey = RedisKeyManager.getHashKey(dbSeasonId); - - - if (rankRedisRepository.findRankByUserId(redisHashKey, userId) == null) - throw new SeasonNotFoundException(); - System.out.println(rankRedisRepository.findRankByUserId(redisHashKey, userId).getIntraId()); - } - - - @Test - @DisplayName("[Delete]/pingpong/admin/season/{seasonId}") - void deleteSeasons() throws Exception { - testDataUtils.createTierSystem("pingpong"); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Season newSeason = Season.builder() - .seasonName("redis1") - .startTime(LocalDateTime.now().plusDays(1)) - .endTime(LocalDateTime.now().plusDays(10)) - .startPpp(1000) - .pppGap(500) - .build(); - seasonAdminRepository.save(newSeason); - Long seasonId = newSeason.getId(); - - SeasonAdminDto seasonAdminDto = seasonAdminService.findSeasonById(seasonId); - if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { - rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); - rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); - } - dbSeasonId = seasonId; - - String contentAsString = mockMvc.perform(MockMvcRequestBuilders.delete("/pingpong/admin/seasons/" + dbSeasonId) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - try { - String redisHashKey = RedisKeyManager.getHashKey(dbSeasonId); - if (rankRedisRepository.findRankByUserId(redisHashKey, userId) != null) - throw new SeasonForbiddenException(); - } - catch(RedisDataNotFoundException ex){ - System.out.println("success: ๋ ˆ๋””์Šค๊ฐ€ ์ง€์›Œ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค"); - } - } - - @Test - @DisplayName("[Put]/pingpong/admin/seasons/{seasonId}") - void updateSeasons() throws Exception { - testDataUtils.createTierSystem("pingpong"); - testDataUtils.createSeason(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Season newSeason = Season.builder() - .seasonName("redis1") - .startTime(LocalDateTime.now().plusHours(25)) - .endTime(LocalDateTime.now().plusDays(10)) - .startPpp(1000) - .pppGap(500) - .build(); - seasonAdminRepository.save(newSeason); - Long seasonId = newSeason.getId(); - - SeasonAdminDto seasonAdminDto = seasonAdminService.findSeasonById(seasonId); - if (LocalDateTime.now().isBefore(seasonAdminDto.getStartTime())) { - rankAdminService.addAllUserRankByNewSeason(seasonAdminDto); - rankRedisAdminService.addAllUserRankByNewSeason(seasonAdminDto); - } - dbSeasonId = seasonId; - SeasonUpdateRequestDto seasonUpdateRequestDto = new SeasonUpdateRequestDto( - "putSeasonTestName", - LocalDateTime.now().plusHours(25), - 1000, - 500); - - String content = objectMapper.writeValueAsString(seasonUpdateRequestDto); - - String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/pingpong/admin/seasons/" + dbSeasonId) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - assertThat(seasonAdminRepository.findById(dbSeasonId).get().getSeasonName()) - .isEqualTo(seasonUpdateRequestDto.getSeasonName()); - } - - @Test - @DisplayName("Fail[Put]/pingpong/admin/seasons/{seasonId}") - void failUpdateSeasons() throws Exception {//ํ˜„์žฌ ์‹œ์ฆŒ์„ ๋ณ€๊ฒฝํ•  ๋•Œ 400๋ฒˆ๋Œ€ ์ƒํƒœ์ฝ”๋“œ ๋ฐ˜ํ™˜ - testDataUtils.createTierSystem("pingpong"); - testDataUtils.createSeason(); - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - Long nowSeasonId = seasonAdminRepository.findCurrentSeason(LocalDateTime.now().plusMinutes(1)).get().getId(); - SeasonUpdateRequestDto seasonUpdateRequestDto = new SeasonUpdateRequestDto( - "putSeasonTestName", - LocalDateTime.now().plusHours(25), - 1000, - 500); - - String content = objectMapper.writeValueAsString(seasonUpdateRequestDto); - - String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/pingpong/admin/seasons/" + nowSeasonId) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError())//403๋ฐ˜ํ™˜ - .andReturn().getResponse().getContentAsString(); - - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerFailTest.java b/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerFailTest.java deleted file mode 100644 index e70c2b819..000000000 --- a/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerFailTest.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.gg.server.admin.slotmanagement.controller; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.slotmanagement.data.adminSlotManagementRepository; -import com.gg.server.admin.slotmanagement.dto.SlotCreateRequestDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -public class SlotAdminControllerFailTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - adminSlotManagementRepository adminSlotManagementRepository; - - @Autowired - SlotManagementRepository slotManagementRepository; - -//์ด๊ฑฐ ํ…Œ์ŠคํŠธ ํ• ๋ ค๋ฉด ๋””๋น„ ๋‚ด์šฉ ๋ชจ๋‘ ์ง€์›Œ์•ผ ํ•จ -// @Test -// @DisplayName("fail[Get]/pingpong/admin/slot-management") -// void failGetSlotSetting() throws Exception { -// String accessToken = testDataUtils.getLoginAccessToken(); -// Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); -// -// String contentAsString = mockMvc.perform(get("/pingpong/admin/slot-management").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) -// .andExpect(status().isBadRequest()) -// .andReturn().getResponse().getContentAsString(); -// -// System.out.println(contentAsString); -// } - - @Test - @DisplayName("fail[Post]/pingpong/admin/slot-management") - void failModifySlotSetting() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,20,null,LocalDateTime.now().plusDays(2)); - String content = objectMapper.writeValueAsString(test); - - String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("fail[Post]/pingpong/admin/slot-management") - void ์—”๋“œํƒ€์ž„_๋ฏธ๋ž˜์‹œ์ _๋ณด๋‹ค_๊ฐ€๊นŒ์šธ_๊ฒฝ์šฐ() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,20,1,LocalDateTime.now().plusHours(1)); - String content = objectMapper.writeValueAsString(test); - - String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("fail[Post]/pingpong/admin/slot-management") - void ์ธํ„ฐ๋ฒŒ์ด7์ผ๋•Œ() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,7,1,LocalDateTime.now().plusHours(1)); - String content = objectMapper.writeValueAsString(test); - - String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("fail[Post]/pingpong/admin/slot-management") - void ์ƒ๋Œ€๋ฐฉ๊ณต๊ฐœ์‹œ๊ฐ„์ด๊ฒŒ์ž„์‹œ๊ฐ„๋ณด๋‹คํด๋–„() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,10,15,LocalDateTime.now().plusHours(1)); - String content = objectMapper.writeValueAsString(test); - - String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("fail[Delete]/pingpong/admin/slot-management") - void ์Šฌ๋กฏ์ •๋ณด๊ฐ€ํ˜„์žฌ์ ์šฉ์ค‘์ธ๊ฒฝ์šฐ() throws Exception { - SlotManagement preSlot = SlotManagement.builder() - .futureSlotTime(12) - .pastSlotTime(0) - .openMinute(5) - .gameInterval(15) - .startTime(LocalDateTime.now().minusDays(1)) - .build(); - slotManagementRepository.save(preSlot); - - String accessToken = testDataUtils.getAdminLoginAccessToken(); - - List slotManagements = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); - for (SlotManagement slot : slotManagements) { - System.out.println("-----------------------"); - System.out.println(slot.getFutureSlotTime()); - System.out.println(slot.getPastSlotTime()); - System.out.println(slot.getOpenMinute()); - System.out.println(slot.getStartTime()); - System.out.println(slot.getEndTime()); - System.out.println(slot.getId()); - } - - String contentAsString = mockMvc.perform(delete("/pingpong/admin/slot-management") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is4xxClientError()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - List slotManagements2 = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); - for (SlotManagement slot : slotManagements2) { - System.out.println("-----------------------"); - System.out.println(slot.getFutureSlotTime()); - System.out.println(slot.getPastSlotTime()); - System.out.println(slot.getOpenMinute()); - System.out.println(slot.getStartTime()); - System.out.println(slot.getEndTime()); - System.out.println(slot.getId()); - } - } -} diff --git a/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerTest.java b/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerTest.java deleted file mode 100644 index ca76ed77e..000000000 --- a/src/test/java/com/gg/server/admin/slotmanagement/controller/SlotAdminControllerTest.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.gg.server.admin.slotmanagement.controller; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.slotmanagement.data.adminSlotManagementRepository; -import com.gg.server.admin.slotmanagement.dto.SlotAdminDto; -import com.gg.server.admin.slotmanagement.dto.SlotCreateRequestDto; -import com.gg.server.admin.slotmanagement.dto.SlotListAdminResponseDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class SlotAdminControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - adminSlotManagementRepository adminSlotManagementRepository; - - @Autowired - SlotManagementRepository slotManagementRepository; - - @BeforeEach - void setUp() { - SlotManagement preSlot = SlotManagement.builder() - .futureSlotTime(12) - .pastSlotTime(0) - .openMinute(5) - .gameInterval(15) - .startTime(LocalDateTime.now().minusDays(1)) - .build(); - slotManagementRepository.save(preSlot); - } - - @Test - @DisplayName("[Get]/pingpong/admin/slot-management") - void getSlotSetting1() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,20,1,LocalDateTime.now().plusHours(13)); - System.out.println(test.getStartTime()); - String content = objectMapper.writeValueAsString(test); - mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - SlotCreateRequestDto test2 = new SlotCreateRequestDto(4,1,20,1,LocalDateTime.now().plusHours(48)); - System.out.println(test.getStartTime()); - String content2 = objectMapper.writeValueAsString(test2); - mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content2) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - String contentAsString = mockMvc.perform(get("/pingpong/admin/slot-management").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - SlotListAdminResponseDto slotAdminDto = objectMapper.readValue(contentAsString, SlotListAdminResponseDto.class); - - for(SlotAdminDto dto : slotAdminDto.getSlotList()){ - System.out.println(dto.getFutureSlotTime()); - System.out.println(dto.getPastSlotTime()); - System.out.println(dto.getInterval()); - System.out.println(dto.getOpenMinute()); - System.out.println(dto.getStartTime()); - System.out.println(dto.getEndTime()); - System.out.println("----------------------"); - } - } - - @Test - @DisplayName("[Get]/pingpong/admin/slot-management") - void getSlotSetting2() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - String contentAsString = mockMvc.perform(get("/pingpong/admin/slot-management").header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - SlotListAdminResponseDto slotAdminDto = objectMapper.readValue(contentAsString, SlotListAdminResponseDto.class); - - for(SlotAdminDto dto : slotAdminDto.getSlotList()){ - System.out.println(dto.getFutureSlotTime()); - System.out.println(dto.getPastSlotTime()); - System.out.println(dto.getInterval()); - System.out.println(dto.getOpenMinute()); - System.out.println(dto.getStartTime()); - System.out.println(dto.getEndTime()); - System.out.println("----------------------"); - } - } - - @Test - @DisplayName("[Post]/pingpong/admin/slot-management") - void modifySlotSetting() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,20,1,LocalDateTime.now().plusHours(13)); - System.out.println(test.getStartTime()); - String content = objectMapper.writeValueAsString(test); - - String contentAsString = mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - List slotList = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); - for(SlotManagement slot : slotList){ - System.out.println(slot.getFutureSlotTime()); - System.out.println(slot.getPastSlotTime()); - System.out.println(slot.getGameInterval()); - System.out.println(slot.getOpenMinute()); - System.out.println(slot.getStartTime()); - System.out.println(slot.getEndTime()); - System.out.println("----------------------"); - } - } - - @Test - @DisplayName("[Delete]/pingpong/admin/slot-management") - void delSlotSetting() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - SlotCreateRequestDto test = new SlotCreateRequestDto(4,1,20,1,LocalDateTime.now().plusHours(13)); - System.out.println(test.getStartTime()); - String content = objectMapper.writeValueAsString(test); - - mockMvc.perform(post("/pingpong/admin/slot-management") - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - String contentAsString = mockMvc.perform(delete("/pingpong/admin/slot-management") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - List slotList = adminSlotManagementRepository.findAllByOrderByCreatedAtDesc(); - for(SlotManagement slot : slotList){ - System.out.println(slot.getFutureSlotTime()); - System.out.println(slot.getPastSlotTime()); - System.out.println(slot.getGameInterval()); - System.out.println(slot.getOpenMinute()); - System.out.println(slot.getStartTime()); - System.out.println(slot.getEndTime()); - System.out.println("----------------------"); - } - } - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminControllerTest.java b/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminControllerTest.java deleted file mode 100644 index 213d54668..000000000 --- a/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminControllerTest.java +++ /dev/null @@ -1,967 +0,0 @@ -package com.gg.server.admin.tournament.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.tournament.dto.TournamentAdminCreateRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminAddUserRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminUpdateRequestDto; -import com.gg.server.admin.tournament.dto.TournamentGameUpdateRequestDto; -import com.gg.server.admin.tournament.service.TournamentAdminService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.utils.MatchTestUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.data.TournamentUserRepository; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.dto.TeamReqDto; -import com.gg.server.domain.tournament.data.*; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Random; - -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@AutoConfigureMockMvc -@RequiredArgsConstructor -@Transactional -class TournamentAdminControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - TournamentAdminService tournamentAdminService; - - @Autowired - TournamentRepository tournamentRepository; - - @Autowired - TournamentUserRepository tournamentUserRepository; - - @Autowired - TournamentGameRepository tournamentGameRepository; - - @Autowired - PChangeRepository pChangeRepository; - - @Autowired - private MatchTestUtils matchTestUtils; - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์ˆ˜์ •_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") - class TournamentAdminControllerUpdateTest { - @BeforeEach - void beforeEach() { - testDataUtils.createSlot(15); - } - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_์„ฑ๊ณต") - void success() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), - TournamentStatus.BEFORE); - - TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto ( - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + tournament.getId(); - - String content = objectMapper.writeValueAsString(updateDto); - - // when - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - // then - Tournament result = tournamentRepository.findById(tournament.getId()).get(); - assertThat(result.getTitle()).isEqualTo(tournament.getTitle()); - assertThat(result.getContents()).isEqualTo(tournament.getContents()); - assertThat(result.getStartTime()).isEqualTo(updateDto.getStartTime()); - assertThat(result.getEndTime()).isEqualTo(updateDto.getEndTime()); - assertThat(result.getType()).isEqualTo(updateDto.getType()); - assertThat(result.getStatus()).isEqualTo(tournament.getStatus()); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") - void tournamentNotFound() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + 1111; - - String content = objectMapper.writeValueAsString(updateDto); - // when, then - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๊ธฐ๊ฐ„_๊ฒน์น˜๋Š”_๊ฒฝ์šฐ") - void tournamentConflicted() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournamentAlreadyExist = testDataUtils.createTournament( - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), - TournamentStatus.BEFORE); - - Tournament tournamentToChange = testDataUtils.createTournament( - LocalDateTime.now().plusDays(3).withHour(18).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(20).withMinute(0), - TournamentStatus.BEFORE); - - // ๊ฒน์น˜๋Š” ์‹œ๊ฐ„ ์กฐ์ ˆ - TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( - LocalDateTime.now().plusDays(3).withHour(13).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(15).withMinute(0), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); - - String content = objectMapper.writeValueAsString(updateDto); - - // when, then - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isConflict()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("๊ธฐ๊ฐ„๋‚ด_๊ฒŒ์ž„_์กด์žฌ") - void gameAlreadyExist() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - - GameInfoDto game = testDataUtils.createGame(testDataUtils.createNewUser("testUser"), - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(14).withMinute(15), - testDataUtils.createSeason(), Mode.NORMAL); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), - TournamentStatus.BEFORE); - - // ๊ฒน์น˜๋Š” ์‹œ๊ฐ„ ์กฐ์ ˆ - TournamentAdminUpdateRequestDto updateDto = testDataUtils.createUpdateRequestDto( - tournament.getStartTime().plusDays(1), - tournament.getEndTime().plusDays(1), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + tournament.getId(); - - String content = objectMapper.writeValueAsString(updateDto); - - // when, then - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isConflict()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") - void canNotUpdate() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament liveTournament = testDataUtils.createTournament( - LocalDateTime.now().minusHours(1).withMinute(0), - LocalDateTime.now().plusHours(2).withMinute(0), - TournamentStatus.LIVE); - - Tournament endedTournament = testDataUtils.createTournament( - LocalDateTime.now().minusHours(3).withMinute(0), - LocalDateTime.now().minusHours(1).withMinute(0), - TournamentStatus.END); - - TournamentAdminUpdateRequestDto updateTournamentDto = testDataUtils.createUpdateRequestDto( - LocalDateTime.now().plusDays(2).plusHours(3).withMinute(0), - LocalDateTime.now().plusDays(2).plusHours(5).withMinute(0), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + liveTournament.getId(); - - String content = objectMapper.writeValueAsString(updateTournamentDto); - - // when live tournament test, then - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - url = "/pingpong/admin/tournaments/" + endedTournament.getId(); - - // when ended tournament test, then - contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์ž˜๋ชป๋œ_๊ธฐ๊ฐ„") - void wrongTournamentTime() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournamentToChange = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), - TournamentStatus.BEFORE); - - TournamentAdminUpdateRequestDto updateDto1 = testDataUtils.createUpdateRequestDto( - tournamentToChange.getStartTime(), - tournamentToChange.getStartTime(), - TournamentType.MASTER); - - TournamentAdminUpdateRequestDto updateDto2 = testDataUtils.createUpdateRequestDto( - tournamentToChange.getEndTime(), - tournamentToChange.getStartTime(), - TournamentType.MASTER); - - TournamentAdminUpdateRequestDto updateDto3 = testDataUtils.createUpdateRequestDto( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(5), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(5), - TournamentType.MASTER); - - String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); - // when startTime == endTime, then - String content = objectMapper.writeValueAsString(updateDto1); - - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - // when startTime > endTime test, then - content = objectMapper.writeValueAsString(updateDto2); - - contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - // when startTime minute invalid test, then - content = objectMapper.writeValueAsString(updateDto3); - - contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ_dto") - void wrongDto() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournamentToChange = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(2).withHour(16).withMinute(0), - TournamentStatus.BEFORE); - - TournamentAdminUpdateRequestDto updateDto1 = testDataUtils.createUpdateRequestDto( - tournamentToChange.getStartTime(), - tournamentToChange.getStartTime(), - null); - - String url = "/pingpong/admin/tournaments/" + tournamentToChange.getId(); - // when startTime == endTime, then - String content = objectMapper.writeValueAsString(updateDto1); - - String contentAsString = mockMvc.perform(patch(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์‚ญ์ œ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") - class TournamentAdminControllerDeleteTest { - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_์„ฑ๊ณต") - void success() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - - List tournamentGameList = testDataUtils.createTournamentGameList(tournament, 7); - - String url = "/pingpong/admin/tournaments/" + tournament.getId(); - - // when - String contentAsString = mockMvc.perform(delete(url) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - // then - tournamentRepository.findById(tournament.getId()).ifPresent( - a-> {throw new CustomRuntimeException("์‚ญ์ œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.", ErrorCode.BAD_REQUEST);}); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") - void tournamentNotFound() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - String url = "/pingpong/admin/tournaments/" + 1111; - - // when, then - String contentAsString = mockMvc.perform(delete(url) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") - void canNotDelete() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament liveTournament = testDataUtils.createTournament( - LocalDateTime.now().minusHours(1), - LocalDateTime.now().plusHours(2), - TournamentStatus.LIVE); - - Tournament endedTournament = testDataUtils.createTournament( - LocalDateTime.now().minusHours(3), - LocalDateTime.now().minusHours(1), - TournamentStatus.END); - - String url = "/pingpong/admin/tournaments/" + liveTournament.getId(); - - // when live tournament test, then - String contentAsString = mockMvc.perform(delete(url) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - - url = "/pingpong/admin/tournaments/" + endedTournament.getId(); - - // when ended tournament test, then - contentAsString = mockMvc.perform(delete(url) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ด€๋ฆฌ_์ƒ์„ฑ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") - class TournamentAdminControllerCreateTest { - @BeforeEach - void beforeEach() { - testDataUtils.createSlot(15); - } - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„ฑ๊ณต") - void success() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - - TournamentAdminCreateRequestDto createDto = testDataUtils.createRequestDto( - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), - TournamentType.ROOKIE); - - String url = "/pingpong/admin/tournaments"; - String content = objectMapper.writeValueAsString(createDto); - - //when, then - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("๊ธฐ๊ฐ„๋‚ด_๊ฒŒ์ž„_์กด์žฌ") - void gameAlreadyExist() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - GameInfoDto game = testDataUtils.createGame(testDataUtils.createNewUser("testUser"), - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(14).withMinute(15), - testDataUtils.createSeason(), Mode.NORMAL); - - TournamentAdminCreateRequestDto createDto = testDataUtils.createRequestDto( - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), - TournamentType.ROOKIE); - - String url = "/pingpong/admin/tournaments"; - String content = objectMapper.writeValueAsString(createDto); - - // when, then - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isConflict()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ DTO - ๊ธธ์ด ์ดˆ๊ณผ") - void invalidLength() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - int leftLimit = 97; // letter 'a' - int rightLimit = 122; // letter 'z' - int targetStringLength = 3100; - Random random = new Random(); - String contents = random.ints(leftLimit, rightLimit + 1) - .limit(targetStringLength) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - TournamentAdminCreateRequestDto createDto = new TournamentAdminCreateRequestDto( - "1st rookie tournament", - contents, - LocalDateTime.now().plusDays(3).withHour(14).withMinute(0), - LocalDateTime.now().plusDays(3).withHour(16).withMinute(0), - TournamentType.ROOKIE); - - String url = "/pingpong/admin/tournaments"; - String content = objectMapper.writeValueAsString(createDto); - - //when, then - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - } - - @Nested - @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ถ”๊ฐ€_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") - class TournamentAdminControllerAddUserTest { - @Test - @DisplayName("์œ ์ €_์ถ”๊ฐ€_์„ฑ๊ณต") - void success() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament1 = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - Tournament tournament2 = testDataUtils.createTournament( - LocalDateTime.now().plusDays(3).plusHours(1), - LocalDateTime.now().plusDays(3).plusHours(3), - TournamentStatus.BEFORE); - User user = testDataUtils.createNewUser("testUser"); - testDataUtils.createTournamentUser(user, tournament2, true); - - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); - - String url = "/pingpong/admin/tournaments/" + tournament1.getId() + "/users"; - String content = objectMapper.writeValueAsString(requestDto); - - // when - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - // then - System.out.println(contentAsString); - tournament1.getTournamentUsers().stream().filter(tu->tu.getUser().equals(user)).findAny() - .orElseThrow(()->new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); - tournamentUserRepository.findAllByTournamentId(tournament1.getId()) - .stream().filter(tu-> tu.getUser().getIntraId().equals(requestDto.getIntraId())) - .findAny().orElseThrow(()->new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€ ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—†๋Š”_๊ฒฝ์šฐ") - void tournamentNotFound() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - User user = testDataUtils.createNewUser("test"); - - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); - - String url = "/pingpong/admin/tournaments/" + 9999 + "/users"; - - String content = objectMapper.writeValueAsString(requestDto); - - // when, then - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - - } - - @Test - @DisplayName("์ด๋ฏธ_์‹œ์ž‘ํ–ˆ๊ฑฐ๋‚˜_์ข…๋ฃŒ๋œ_ํ† ๋„ˆ๋จผํŠธ_์ˆ˜์ •") - void canNotUpdate() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(0).plusHours(-1), - LocalDateTime.now().plusDays(0).plusHours(1), - TournamentStatus.LIVE); - User user = testDataUtils.createNewUser("test"); - - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); - - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; - - String content = objectMapper.writeValueAsString(requestDto); - - // when, then - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") - void userNotFound() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("nobody"); - - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; - - String content = objectMapper.writeValueAsString(requestDto); - - // when, then - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("ํ•ด๋‹น_ํ† ๋„ˆ๋จผํŠธ_์ฐธ๊ฐ€์ž์ธ_๊ฒฝ์šฐ") - void alreadyTournamentParticipant() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - - User user = testDataUtils.createNewUser("test"); - TournamentUser participant = testDataUtils.createTournamentUser(user, tournament, false); - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); - - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; - String content = objectMapper.writeValueAsString(requestDto); - - // when, then - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isConflict()) - .andReturn().getResponse().getContentAsString(); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๋Œ€๊ธฐ์ž_์‹ ์ฒญ") - void waitUserTest() throws Exception { - // given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - tokenProvider.getUserIdFromAccessToken(accessToken); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - - User user = testDataUtils.createNewUser("testUser0"); - for (int i=1; i<=8; i++) { - testDataUtils.createTournamentUser(testDataUtils.createNewUser("testUser" + i), tournament, true); - } - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto(user.getIntraId()); - - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/users"; - String content = objectMapper.writeValueAsString(requestDto); - - // when - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - // then - tournamentUserRepository.findAllByTournamentId(tournament.getId()).stream() - .filter(tu->tu.getUser().getIntraId().equals(user.getIntraId())).findAny() - .filter(tu->!tu.getIsJoined()).orElseThrow(()->new CustomRuntimeException("waitlist ์ œ๋Œ€๋กœ ๋“ฑ๋ก ์•ˆ๋จ", ErrorCode.BAD_REQUEST)); - } - } - - @Nested - @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‚ญ์ œ_์ปจํŠธ๋กค๋Ÿฌ_ํ…Œ์ŠคํŠธ") - class TournamentAdminControllerDeleteUserTest { - @Test - @DisplayName("์œ ์ €_์‚ญ์ œ_์„ฑ๊ณต") - void success() throws Exception { - // given - int maxTournamentUser = 8; - String accessToken = testDataUtils.getAdminLoginAccessToken(); - - Tournament tournament = testDataUtils.createTournament( - LocalDateTime.now().plusDays(2).plusHours(1), - LocalDateTime.now().plusDays(2).plusHours(3), - TournamentStatus.BEFORE); - - for (int i=0; i tournamentUserList = tournament.getTournamentUsers(); - tournamentUserList.stream().filter(tu->tu.getUser().equals(user)).findAny() - .ifPresent(a->{throw new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ฆฌ์ŠคํŠธ์— ์‚ญ์ œ ์•ˆ๋จ", ErrorCode.BAD_REQUEST);}); - tournamentUserRepository.findByTournamentIdAndUserId(tournament.getId(), user.getId()) - .ifPresent(a->{throw new CustomRuntimeException("ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ๋ ˆํฌ์—์„œ ์‚ญ์ œ ์•ˆ๋จ", ErrorCode.BAD_REQUEST);}); - for (int i=0; i ์ฐธ์—ฌ์ž ์ „ํ™˜ ์ œ๋Œ€๋กœ ์•ˆ๋จ", ErrorCode.BAD_REQUEST); - } - } - for (int i=maxTournamentUser; i allTournamentGames; - Season season; - @BeforeEach - void setUp() { - // ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑํ•˜๊ณ  8๊ฐ• & 4๊ฐ•์€ ๊ฒŒ์ž„ ์ ์ˆ˜ ์ž…๋ ฅํ•˜๊ณ  ์ข…๋ฃŒ๋œ ์ƒํƒœ์ด๊ณ  ๊ฒฐ์Šน์ „ ๋งค์นญ๋œ ์ƒํƒœ๋กœ ์ดˆ๊ธฐํ™” - season = testDataUtils.createSeason(); - testDataUtils.createSlotManagement(15); - tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "test"); - allTournamentGames = testDataUtils.createTournamentGameList(tournament, 7); - tournament.updateStatus(TournamentStatus.LIVE); - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); - - accessToken = testDataUtils.getAdminLoginAccessToken(); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ฒŒ์ž„_์ˆ˜์ •_์„ฑ๊ณต") - void updateTournamentGameSuccess() throws Exception { - // given - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/games"; - - int myTeamScore = 2; - int otherTeamScore = 1; - TournamentGame tournamentGame = allTournamentGames.stream().filter(tg -> tg.getTournamentRound() == TournamentRound.SEMI_FINAL_1).findAny().orElseThrow(); - TournamentGame nextTournamentGame = allTournamentGames.stream().filter(tg -> tg.getTournamentRound() == TournamentRound.THE_FINAL).findAny().orElseThrow(); - User user1 = tournamentGame.getGame().getTeams().get(0).getTeamUsers().get(0).getUser(); - User user2 = tournamentGame.getGame().getTeams().get(1).getTeamUsers().get(0).getUser(); - testDataUtils.createUserRank(user1, "" ,season); - testDataUtils.createUserRank(user2, "" ,season); - - TournamentGameUpdateRequestDto requestDto = new TournamentGameUpdateRequestDto(tournamentGame.getId(), nextTournamentGame.getId(), - new TeamReqDto(tournamentGame.getGame().getTeams().get(0).getId(), myTeamScore), - new TeamReqDto(tournamentGame.getGame().getTeams().get(1).getId(), otherTeamScore)); - - String content = objectMapper.writeValueAsString(requestDto); - // when - mockMvc.perform(patch(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .content(content) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentGame resTournamentGame = tournamentGameRepository.findById(tournamentGame.getId()).orElseThrow(); - assertThat(resTournamentGame.getGame().getTeams().get(0).getScore()).isEqualTo(myTeamScore); - assertThat(resTournamentGame.getGame().getTeams().get(1).getScore()).isEqualTo(otherTeamScore); - assertThat(pChangeRepository.findByUserIdAndGameId(user1.getId(), tournamentGame.getGame().getId())).isNotEmpty(); - assertThat(pChangeRepository.findByUserIdAndGameId(user2.getId(), tournamentGame.getGame().getId())).isNotEmpty(); - } - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๊ฒŒ์ž„_์ˆ˜์ •_๋ถˆ๊ฐ€๋Šฅ") - void updateTournamentGameEnable() throws Exception { - // given - String url = "/pingpong/admin/tournaments/" + tournament.getId() + "/games"; - int myTeamScore = 2; - int otherTeamScore = 1; - TournamentGame tournamentGame = allTournamentGames.stream().filter(tg -> tg.getTournamentRound() == TournamentRound.QUARTER_FINAL_1).findAny().orElseThrow(); - TournamentGame nextTournamentGame = allTournamentGames.stream().filter(tg -> tg.getTournamentRound() == TournamentRound.SEMI_FINAL_1).findAny().orElseThrow(); - TournamentGameUpdateRequestDto requestDto = new TournamentGameUpdateRequestDto(tournamentGame.getId(), nextTournamentGame.getId(), - new TeamReqDto(tournamentGame.getGame().getTeams().get(0).getId(), myTeamScore), - new TeamReqDto(tournamentGame.getGame().getTeams().get(1).getId(), otherTeamScore)); - - String content = objectMapper.writeValueAsString(requestDto); - // when - mockMvc.perform(patch(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .content(content) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(); - } - - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminUserControllerTest.java b/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminUserControllerTest.java deleted file mode 100644 index 498e0e2da..000000000 --- a/src/test/java/com/gg/server/admin/tournament/controller/TournamentAdminUserControllerTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.gg.server.admin.tournament.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.dto.TournamentUserListResponseDto; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -@Slf4j -public class TournamentAdminUserControllerTest { - - @Autowired - MockMvc mockMvc; - @Autowired - TestDataUtils testDataUtils; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - - String accessToken; - final int joinUserCnt = 8; - final int notJoinUserCnt = 4; - String testName = "42_gg_tester_"; - Tournament tournament; - String adminUrl = "/pingpong/admin/tournaments/"; - @BeforeEach - void beforeEach() { - User tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, SnsType.SLACK, RoleType.ADMIN); - accessToken = tokenProvider.createToken(tester.getId()); - tournament = testDataUtils.createTournamentWithUser(joinUserCnt, notJoinUserCnt, testName); - } - - @Nested - @DisplayName("/pingpong/admin/tournaments") - class FindTournamentUser { - - @Test - @DisplayName("[Get] /{tournamentId}/users") - void getAllTournamentUser() throws Exception { - // given - - String url = adminUrl + tournament.getId() + "/users"; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentUserListResponseDto resp = objectMapper.readValue(contentAsString, TournamentUserListResponseDto.class); - - // then - assertThat(resp.getUsers().size()).isEqualTo(joinUserCnt+ notJoinUserCnt); - for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { - assertThat(resp.getUsers().get(i).getIntraId()).isEqualTo(testName + i); - } - } - - @Test - @DisplayName("[Get] /{tournamentId}/users?isJoined=true") - void getAllTournamentUserByIsJoined() throws Exception { - - // given - String url = adminUrl + tournament.getId() + "/users" + "?isJoined=true"; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentUserListResponseDto resp = objectMapper.readValue(contentAsString, TournamentUserListResponseDto.class); - - // then - assertThat(resp.getUsers().size()).isEqualTo(joinUserCnt); - for (int i = 0; i < joinUserCnt; i++) { - assertThat(resp.getUsers().get(i).getIntraId()).isEqualTo(testName + i); - assertThat(resp.getUsers().get(i).getIsJoined()).isEqualTo(true); - } - } - } -} diff --git a/src/test/java/com/gg/server/admin/tournament/service/TournamentAdminServiceTest.java b/src/test/java/com/gg/server/admin/tournament/service/TournamentAdminServiceTest.java deleted file mode 100644 index 6eccffb1b..000000000 --- a/src/test/java/com/gg/server/admin/tournament/service/TournamentAdminServiceTest.java +++ /dev/null @@ -1,582 +0,0 @@ -package com.gg.server.admin.tournament.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.when; - -import com.gg.server.admin.tournament.dto.TournamentAdminCreateRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminAddUserRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminUpdateRequestDto; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.data.TournamentGameRepository; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.data.TournamentUserRepository; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.exception.TournamentNotFoundException; -import com.gg.server.domain.tournament.exception.TournamentUpdateException; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.config.ConstantConfig; -import com.gg.server.utils.ReflectionUtilsForUnitTest; -import com.gg.server.utils.annotation.UnitTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@UnitTest -@ExtendWith(MockitoExtension.class) -class TournamentAdminServiceTest { - @Mock - TournamentRepository tournamentRepository; - @Mock - TournamentGameRepository tournamentGameRepository; - @Mock - TournamentUserRepository tournamentUserRepository; - @Mock - SlotManagementRepository slotManagementRepository; - @Mock - UserRepository userRepository; - @Mock - GameRepository gameRepository; - @Mock - ConstantConfig constantConfig; - @InjectMocks - TournamentAdminService tournamentAdminService; - - // ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์ƒ์„ฑ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") - class TournamentAdminServiceCreateTest { - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ ์„ฑ๊ณต") - void success() { - // given - TournamentAdminCreateRequestDto requestDto = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 14, 0), getTargetTime(3, 16, 0)); - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentGame tournamentGame = createTournamentGame(tournament, TournamentRound.THE_FINAL); - - given(slotManagementRepository.findCurrent(requestDto.getStartTime())).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findAllBetween(requestDto.getStartTime(), requestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(gameRepository.findAllBetweenTournament(requestDto.getStartTime(), requestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(tournamentRepository.save(any(Tournament.class))).willReturn(tournament); - - // when - tournamentAdminService.createTournament(requestDto); - } - - @Test - @DisplayName("์œ ํšจํ•˜์ง€ ์•Š์€ ์‹œ๊ฐ„ ์ž…๋ ฅ") - public void invalidTime() { - when(constantConfig.getAllowedMinimalStartDays()).thenReturn(2); - //given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - getTargetTime(0, 0, 0), getTargetTime(0, 1, 0)); - - TournamentAdminCreateRequestDto requestDto1 = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(1, 1, 0), getTargetTime(1, 3, 0)); - TournamentAdminCreateRequestDto requestDto2 = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 3, 0), getTargetTime(3, 1, 0)); - TournamentAdminCreateRequestDto requestDto3 = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 3, 0), getTargetTime(3, 3, 0)); - TournamentAdminCreateRequestDto requestDto4 = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 1, 10), getTargetTime(3, 2, 10)); - given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn(Optional.of(createSlot(15))); - // when, then - assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto1)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto2)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto3)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.createTournament(requestDto4)) - .isInstanceOf(TournamentUpdateException.class); - } - - @Test - @DisplayName("๊ธฐ์กด์— ์žˆ๋Š” ํ† ๋„ˆ๋จผํŠธ์™€ ๊ฒน์น˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„") - public void tournamentTimeConflict() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(3, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminCreateRequestDto createRequestDto = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 11, 0), getTargetTime(3, 13, 0)); - given(slotManagementRepository.findCurrent(createRequestDto.getStartTime())).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findAllBetween(createRequestDto.getStartTime(), createRequestDto.getEndTime())) - .willReturn(tournamentList); - - // when, then - assertThatThrownBy(() -> tournamentAdminService.createTournament(createRequestDto)) - .isInstanceOf(TournamentConflictException.class); - } - - @Test - @DisplayName("๊ธฐ์กด์— ์žˆ๋Š” ๊ฒŒ์ž„๊ณผ ๊ฒน์น˜๋Š” ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„") - void gameAlreadyExist() { - // given - TournamentAdminCreateRequestDto tournamentAdminCreateRequestDto = createTournamentCreateRequestDto( - "1st tournament", - getTargetTime(3, 10, 0), getTargetTime(3, 12, 0)); - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentGame tournamentGame = createTournamentGame(tournament, TournamentRound.THE_FINAL); - List gameList = new ArrayList<>(); - gameList.add(new Game()); - given(slotManagementRepository.findCurrent(tournamentAdminCreateRequestDto.getStartTime())).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findAllBetween(tournamentAdminCreateRequestDto.getStartTime(), tournamentAdminCreateRequestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(gameRepository.findAllBetweenTournament(tournamentAdminCreateRequestDto.getStartTime(), tournamentAdminCreateRequestDto.getEndTime())) - .willReturn(gameList); - - // when - assertThatThrownBy(() -> tournamentAdminService.createTournament(tournamentAdminCreateRequestDto)) - .isInstanceOf(TournamentConflictException.class); - ; - } - } - - // ํ† ๋„ˆ๋จผํŠธ ์ˆ˜์ • ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค ์ˆ˜์ • ํ…Œ์ŠคํŠธ") - class TournamentAdminServiceUpdateTest { - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_์„ฑ๊ณต") - public void success() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( - getTargetTime(3, 14, 0), getTargetTime(3, 16, 0)); - given(slotManagementRepository.findCurrent(updateRequestDto.getStartTime())).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(gameRepository.findAllBetweenTournament(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(tournamentRepository.save(any(Tournament.class))).willReturn(tournament); - // when - Tournament changedTournament = tournamentAdminService.updateTournamentInfo(1L, updateRequestDto); - // then - assertThat(changedTournament.getId()).isEqualTo(tournament.getId()); - assertThat(changedTournament.getTitle()).isEqualTo(updateRequestDto.getTitle()); - assertThat(changedTournament.getContents()).isEqualTo(updateRequestDto.getContents()); - assertThat(changedTournament.getStartTime()).isEqualTo(updateRequestDto.getStartTime()); - assertThat(changedTournament.getEndTime()).isEqualTo(updateRequestDto.getEndTime()); - assertThat(changedTournament.getType()).isEqualTo(updateRequestDto.getType()); - assertThat(changedTournament.getStatus()).isEqualTo(tournament.getStatus()); - } - - @Test - @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") - public void tournamentNotFound() { - // given - Tournament tournament = createTournament(1234L, TournamentStatus.BEFORE, - getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); - TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( - getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); - - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.empty()); - // when, then - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) - .isInstanceOf(TournamentNotFoundException.class); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๋ถˆ๊ฐ€_์ƒํƒœ") - public void canNotUpdate() { - // given - Tournament tournamentLive = createTournament(1L, TournamentStatus.LIVE, - LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); - Tournament tournamentEnd = createTournament(2L, TournamentStatus.END, - LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); - TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( - getTargetTime(3, 10, 0), getTargetTime(3, 12, 0)); - given(tournamentRepository.findById(tournamentLive.getId())).willReturn(Optional.of(tournamentLive)); - given(tournamentRepository.findById(tournamentEnd.getId())).willReturn(Optional.of(tournamentEnd)); - // when, then - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournamentLive.getId(), updateRequestDto)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournamentEnd.getId(), updateRequestDto)) - .isInstanceOf(TournamentUpdateException.class); - } - - @Test - @DisplayName("์—…๋ฐ์ดํŠธ_ํ† ๋„ˆ๋จผํŠธ_Dto_Invalid_Time") - public void Dto_Invalid_Time() { - when(constantConfig.getAllowedMinimalStartDays()).thenReturn(2); - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); - TournamentAdminUpdateRequestDto invalidRequestDto1 = createTournamentAdminUpdateRequestDto( - getTargetTime(2, 3, 0), getTargetTime(2, 1, 0)); - TournamentAdminUpdateRequestDto invalidRequestDto2 = createTournamentAdminUpdateRequestDto( - invalidRequestDto1.getStartTime(), invalidRequestDto1.getStartTime()); - TournamentAdminUpdateRequestDto invalidRequestDto3 = createTournamentAdminUpdateRequestDto( - getTargetTime(1, 23, 0), getTargetTime(2, 1, 0)); - TournamentAdminUpdateRequestDto invalidRequestDto4 = createTournamentAdminUpdateRequestDto( - getTargetTime(2, 20, 1), getTargetTime(2, 23, 0)); - - given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - // when then - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto1)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto2)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto3)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), invalidRequestDto4)) - .isInstanceOf(TournamentUpdateException.class); - } - - @Test - @DisplayName("Dto_๊ธฐ๊ฐ„_ํ† ๋„ˆ๋จผํŠธ_๊ธฐ๊ฐ„_๊ฒน์นจ") - public void tournamentTimeConflict() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(3, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( - getTargetTime(3, 12, 0), getTargetTime(3, 14, 0)); - given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) - .willReturn(tournamentList); - // when, then - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) - .isInstanceOf(TournamentConflictException.class); - } - - @Test - @DisplayName("Dto_๊ธฐ๊ฐ„_๊ฒŒ์ž„_๊ฒน์นจ") - public void gameTimeConflict() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 10, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminUpdateRequestDto updateRequestDto = createTournamentAdminUpdateRequestDto( - getTargetTime(3, 1, 0), getTargetTime(3, 3, 0)); - List gameList = new ArrayList<>(); - gameList.add(new Game()); - given(slotManagementRepository.findCurrent(any(LocalDateTime.class))).willReturn(Optional.of(createSlot(15))); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - given(tournamentRepository.findAllBetween(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())) - .willReturn(new ArrayList<>()); - given(gameRepository.findAllBetweenTournament(updateRequestDto.getStartTime(), updateRequestDto.getEndTime())).willReturn(gameList); - // when, then - assertThatThrownBy(() -> tournamentAdminService.updateTournamentInfo(tournament.getId(), updateRequestDto)) - .isInstanceOf(TournamentConflictException.class); - } - } - - // ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ด€๋ฆฌ์ž ์„œ๋น„์Šค ์‚ญ์ œ ํ…Œ์ŠคํŠธ") - class TournamentAdminServiceDeleteTest { - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_์„ฑ๊ณต") - void success() { - // given - int tournamentGameCnt = 7; - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); - List tournamentGameList = createTournamentGames(1L, tournament, tournamentGameCnt); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - // when, then - tournamentAdminService.deleteTournament(tournament.getId()); - } - @Test - @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") - public void tournamentNotFound() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - getTargetTime(2, 1, 0), getTargetTime(2, 3, 0)); - given(tournamentRepository.findById(1L)).willReturn(Optional.empty()); - // when, then - assertThatThrownBy(() -> tournamentAdminService.deleteTournament(tournament.getId())) - .isInstanceOf(TournamentNotFoundException.class); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์‚ญ์ œ_๋ถˆ๊ฐ€_์ƒํƒœ") - public void canNotDelete() { - // given - Tournament liveTournament = createTournament(1L, TournamentStatus.LIVE, - LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); - Tournament endTournament = createTournament(1L, TournamentStatus.END, - LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); - given(tournamentRepository.findById(liveTournament.getId())).willReturn(Optional.of(liveTournament)); - given(tournamentRepository.findById(endTournament.getId())).willReturn(Optional.of(endTournament)); - // when, then - assertThatThrownBy(() -> tournamentAdminService.deleteTournament(liveTournament.getId())) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.deleteTournament(endTournament.getId())) - .isInstanceOf(TournamentUpdateException.class); - } - - } - - @Nested - @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ถ”๊ฐ€_ํ…Œ์ŠคํŠธ") - class TournamentAdminServiceAddUserTest { - @Test - @DisplayName("์œ ์ €_์ถ”๊ฐ€_์„ฑ๊ณต") - public void success() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("testUser"); - User user = createUser("testUser"); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(userRepository.findByIntraId("testUser")).willReturn(Optional.of(user)); - given(tournamentUserRepository.save(any(TournamentUser.class))).willReturn(null); - // when, then - tournamentAdminService.addTournamentUser(1L, requestDto); - } - - @Test - @DisplayName("ํƒ€๊ฒŸ_ํ† ๋„ˆ๋จผํŠธ_์—†์Œ") - public void tournamentNotFound() { - // given - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); - - given(tournamentRepository.findById(any(Long.class))).willReturn(Optional.empty()); - // when, then - assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(1L, requestDto)) - .isInstanceOf(TournamentNotFoundException.class); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์—…๋ฐ์ดํŠธ_๋ถˆ๊ฐ€_์ƒํƒœ") - public void canNotAdd() { - // given - Tournament tournamentLive = createTournament(1L, TournamentStatus.LIVE, - LocalDateTime.now().plusHours(-1).withMinute(0), LocalDateTime.now().plusHours(1).withMinute(0)); - Tournament tournamentEnd = createTournament(2L, TournamentStatus.END, - LocalDateTime.now().plusHours(-4).withMinute(0), LocalDateTime.now().plusHours(-2).withMinute(0)); - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); - given(tournamentRepository.findById(tournamentLive.getId())).willReturn(Optional.of(tournamentLive)); - given(tournamentRepository.findById(tournamentEnd.getId())).willReturn(Optional.of(tournamentEnd)); - // when, then - assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournamentLive.getId(), requestDto)) - .isInstanceOf(TournamentUpdateException.class); - assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournamentEnd.getId(), requestDto)) - .isInstanceOf(TournamentUpdateException.class); - } - - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") - public void userNotFound() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - getTargetTime(0, 14, 0), getTargetTime(0, 16, 0)); - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("test"); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(userRepository.findByIntraId("test")).willReturn(Optional.empty()); - - // when then - assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournament.getId(), requestDto)) - .isInstanceOf(UserNotFoundException.class); - } - - @Test - @DisplayName("์ด๋ฏธ_ํ•ด๋‹น_ํ† ๋„ˆ๋จผํŠธ_์ฐธ๊ฐ€์ค‘์ธ_์œ ์ €") - public void alreadyTournamentParticipant() { - // given - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); - Tournament tournament = tournamentList.get(0); - TournamentAdminAddUserRequestDto requestDto = new TournamentAdminAddUserRequestDto("testUser"); - User user = createUser("testUser"); - TournamentUser tournamentUser = new TournamentUser(user, tournament, true, LocalDateTime.now()); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(userRepository.findByIntraId("testUser")).willReturn(Optional.of(user)); - - // when, then - assertThatThrownBy(() -> tournamentAdminService.addTournamentUser(tournament.getId(), requestDto)) - .isInstanceOf(TournamentConflictException.class); - } - } - - @Nested - @DisplayName("๊ด€๋ฆฌ์ž_ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‚ญ์ œ_ํ…Œ์ŠคํŠธ") - class TournamentAdminServiceDeleteUserTest { - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_์œ ์ €") - public void userNotFound() { - //given - List tournamentList = createTournaments(1L, 2, getTargetTime(2, 1, 0)); - Tournament tournament = tournamentList.get(0); - User user = createUser("user"); - given(tournamentRepository.findById(1L)).willReturn(Optional.of(tournament)); - given(userRepository.findById(null)).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(() -> tournamentAdminService.deleteTournamentUser(tournament.getId(), user.getId())) - .isInstanceOf(UserNotFoundException.class); - } - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ requestDto - * @param startTime ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @return - */ - private TournamentAdminCreateRequestDto createTournamentCreateRequestDto(String title, LocalDateTime startTime, LocalDateTime endTime) { - return new TournamentAdminCreateRequestDto( - title, - "์ œ 1ํšŒ ๋ฃจํ‚ค์ „ ๋งŽ๊ด€๋ถ€!!", - startTime, - endTime, - TournamentType.ROOKIE - ); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” ์ƒ์„ฑ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ๋ช‡ ๋ฒˆ์งธ ๊ฒŒ์ž„์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด - * @return ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - */ - private TournamentGame createTournamentGame(Tournament tournament, TournamentRound round) { - TournamentGame tournamentGame = new TournamentGame(null, tournament, round); - return tournamentGameRepository.save(tournamentGame); - } - - /** - * ํ˜„์žฌ ์‹œ๊ฐ„์—์„œ days hours, ๋งŒํผ ์ฐจ์ด๋‚˜๋Š” ์‹œ๊ฐ„์„ ๊ตฌํ•œ๋‹ค. - * @param days - * @param hours - * @return - */ - private LocalDateTime getTargetTime(int days, int hours, int minutes) { - return LocalDateTime.now().plusDays(days).withHour(hours).withMinute(minutes); - } - - /** - * ๊ฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ดˆ๊ธฐํ™” ๋œ ํ† ๋„ˆ๋จผํŠธ๋ฅผ ๋ฐ˜ํ™˜ - * @param id - * @param status - * @param startTime - * @param endTime - * @return - */ - private Tournament createTournament(Long id, TournamentStatus status, LocalDateTime startTime, LocalDateTime endTime) { - Tournament tournament = Tournament.builder() - .title(id + "st tournament") - .contents("") - .startTime(startTime) - .endTime(endTime) - .type(TournamentType.ROOKIE) - .status(status) - .build(); - ReflectionUtilsForUnitTest.setFieldWithReflection(tournament, "id", id); - return tournament; - } - - /** - *
id ๋ถ€ํ„ฐ cnt๊ฐœ ๋งŒํผ์˜ ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
- * ๊ฐ ํ† ๋„ˆ๋จผํŠธ๋Š” 1์‹œ๊ฐ„ ๊ธธ์ด์ด๋ฉฐ, ํ† ๋„ˆ๋จผํŠธ๊ฐ„ 1์‹œ๊ฐ„์˜ ๊ฐ„๊ฒฉ์ด ์žˆ๋‹ค. - * @param id - * @param cnt - * @param startTime - * @return - */ - private List createTournaments(Long id, long cnt, LocalDateTime startTime) { - List tournamentList = new ArrayList<>(); - for (long i=0; i createTournamentGames(Long id, Tournament tournament, int cnt) { - List tournamentGameList = new ArrayList<>(); - TournamentRound [] values = TournamentRound.values(); - while (--cnt >= 0) { - tournamentGameList.add(new TournamentGame(null, tournament, values[cnt])); - } - return tournamentGameList; - } - - private SlotManagement createSlot(int gameInterval) { - return SlotManagement.builder() - .pastSlotTime(0) - .futureSlotTime(0) - .openMinute(0) - .gameInterval(gameInterval) - .startTime(LocalDateTime.now().minusHours(1)) - .build(); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java b/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java deleted file mode 100644 index 1aca93555..000000000 --- a/src/test/java/com/gg/server/admin/user/controller/UserAdminControllerTest.java +++ /dev/null @@ -1,256 +0,0 @@ -package com.gg.server.admin.user.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.user.data.UserAdminRepository; -import com.gg.server.admin.user.data.UserImageAdminRepository; -import com.gg.server.admin.user.dto.UserDetailAdminResponseDto; -import com.gg.server.admin.user.dto.UserImageAdminDto; -import com.gg.server.admin.user.dto.UserImageListAdminResponseDto; -import com.gg.server.admin.user.dto.UserSearchAdminDto; -import com.gg.server.admin.user.dto.UserSearchAdminResponseDto; -import com.gg.server.admin.user.service.UserAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.util.List; -import javax.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.test.web.servlet.MockMvc; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -class UserAdminControllerTest { - - @Autowired - UserAdminService userAdminService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - UserAdminRepository userAdminRepository; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @Autowired - UserImageAdminRepository userImageAdminRepository; - - @BeforeEach - public void setUp() { - testDataUtils.createTierSystem("pingpong"); - testDataUtils.createSeason(); - } - - @Test - @DisplayName("GET /pingpong/admin/users") - @Transactional - public void userSearchAllTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - int page = 1; - int size = 20; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); - String url = "/pingpong/admin/users?page=1"; - String url2 = "/pingpong/admin/users?page=1&intraId=" + user.getIntraId(); - //when - //200 ์„ฑ๊ณต - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse1 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - //200 ์„ฑ๊ณต - contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse2 = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - - //then - List userList1 = userAdminRepository.findAll(pageable).getContent(); - List actureUserList1 = actureResponse1.getUserSearchAdminDtos(); - for (int i = 0; i < userList1.size(); i++) { - Assertions.assertThat(userList1.get(i).getIntraId()).isEqualTo(actureUserList1.get(i).getIntraId()); - } - - List userList2 = userAdminRepository.findAll(pageable).getContent(); - List actureUserList2 = actureResponse2.getUserSearchAdminDtos(); - for (int i = 0; i < userList1.size(); i++) { - Assertions.assertThat(userList2.get(i).getIntraId()).isEqualTo(actureUserList2.get(i).getIntraId()); - } - } - - @Test - @DisplayName("์œ ์ € ํ•„ํ„ฐ๋ง ์กฐํšŒ ํ…Œ์ŠคํŠธ") - @Transactional - public void ์œ ์ €ํ•„ํ„ฐ๋ง์กฐํšŒํ…Œ์ŠคํŠธ() throws Exception { - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.findById(userId).get(); - int page = 1; - int size = 20; - Pageable pageable = PageRequest.of(page - 1, size, Sort.by("intraId").ascending()); - String url = "/pingpong/admin/users?page=1&userFilter=\"" + user.getIntraId() + "\""; - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserSearchAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserSearchAdminResponseDto.class); - - List actureUserList = actureResponse.getUserSearchAdminDtos(); - for (UserSearchAdminDto userDto : actureUserList) - Assertions.assertThat(userDto.getIntraId()).isEqualTo(user.getIntraId()); - } - - @Test - @DisplayName("GET /pingpong/admin/users/{intraId}") - @Transactional - public void userGetDetailTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = testDataUtils.createNewUser("nheo"); - User target = userRepository.findByIntraId(user.getIntraId()).get(); - String url = "/pingpong/admin/users/" + user.getIntraId(); - UserDetailAdminResponseDto expectedResponse = userAdminService.getUserDetailByIntraId(user.getIntraId()); - - //when - //200 ์„ฑ๊ณต - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserDetailAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserDetailAdminResponseDto.class); - - //then - Assertions.assertThat(actureResponse.getUserId()).isEqualTo(expectedResponse.getUserId()); - Assertions.assertThat(actureResponse.getIntraId()).isEqualTo(expectedResponse.getIntraId()); - Assertions.assertThat(actureResponse.getUserImageUri()).isEqualTo(expectedResponse.getUserImageUri()); - Assertions.assertThat(actureResponse.getRacketType()).isEqualTo(expectedResponse.getRacketType()); -// Assertions.assertThat(actureResponse.getStatusMessage()).isEqualTo(expecxtedResponse.getStatusMessage()); - Assertions.assertThat(actureResponse.getWins()).isEqualTo(expectedResponse.getWins()); - Assertions.assertThat(actureResponse.getLosses()).isEqualTo(expectedResponse.getLosses()); - Assertions.assertThat(actureResponse.getPpp()).isEqualTo(expectedResponse.getPpp()); - Assertions.assertThat(actureResponse.getEmail()).isEqualTo(expectedResponse.getEmail()); - Assertions.assertThat(actureResponse.getRoleType()).isEqualTo(expectedResponse.getRoleType()); - Assertions.assertThat(actureResponse.getExp()).isEqualTo(expectedResponse.getExp()); - Assertions.assertThat(actureResponse.getCoin()).isEqualTo(expectedResponse.getCoin()); - } - - /** - * ์ถ”๊ฐ€์ ์œผ๋กœ ์˜๋„ ํ™•์ธ์ด ํ•„์š”ํ•œ ํ…Œ์ŠคํŠธ - * @throws Exception - */ - @Test - @DisplayName("DELETE /pingpong/admin/users/{intraId}") - @Transactional - public void deleteUserProfileImageTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User klew = testDataUtils.createNewUser("klew"); - User user = userRepository.findByIntraId(klew.getIntraId()).get(); - testDataUtils.createUserImages(user, 2); - String url = "/pingpong/admin/users/images/" + user.getIntraId(); - UserImage PrevUserImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); - //when - //200 ์„ฑ๊ณต - mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()); - -// UserImage CurrentUserImage = userImageAdminRepository.findTopByUserAndIsCurrentIsTrueOrderByCreatedAtDesc(user).orElseThrow(UserNotFoundException::new); -// Assertions.assertThat(PrevUserImage.getId()).isNotEqualTo(CurrentUserImage.getId()); - } - - @Test - @DisplayName("GET /pingpong/admin/users/delete-list") - @Transactional - public void getUserImageDeleteListTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - int page = 1; - int size = 30; - String url = "/pingpong/admin/users/delete-list?page=1"; - - //when - //200 ์„ฑ๊ณต - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); - - //then - //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ - List actureUserImageList = actureResponse.getUserImageList(); - for (UserImageAdminDto userImageDto : actureUserImageList) - Assertions.assertThat(userImageDto.getDeletedAt()).isNotEqualTo(null); - } - - @Test - @DisplayName("GET /pingpong/admin/users/images") - @Transactional - public void getUserImageListTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - String url = "/pingpong/admin/users/images?page=1"; - testDataUtils.createUserImages(testDataUtils.createNewUser(), 4); - - //when - //200 ์„ฑ๊ณต - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - //then - //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ - UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); - assertThat(actureResponse.getUserImageList().size()).isEqualTo(3); - } - - @Test - @DisplayName("GET /pingpong/admin/users/images/{intraId}") - @Transactional - public void getUserImageListByIntraIdTest() throws Exception{ - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - User user = testDataUtils.createNewUser("klew"); - String url = "/pingpong/admin/users/images/" + user.getIntraId() + "?page=1"; - testDataUtils.createUserImages(user, 3); - - //when - //200 ์„ฑ๊ณต - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - //then - //๊ฐ ์œ ์ €์˜ ์ด๋ฏธ์ง€๊ฐ€ ์‚ญ์ œ๋œ ์ด๋ฏธ์ง€์ธ์ง€ ํ™•์ธ - UserImageListAdminResponseDto actureResponse = objectMapper.readValue(contentAsString, UserImageListAdminResponseDto.class); - assertThat(actureResponse.getUserImageList().size()).isEqualTo(2); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/announcement/controller/AnnouncementControllerTest.java b/src/test/java/com/gg/server/domain/announcement/controller/AnnouncementControllerTest.java deleted file mode 100644 index edc75ffd6..000000000 --- a/src/test/java/com/gg/server/domain/announcement/controller/AnnouncementControllerTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.gg.server.domain.announcement.controller; - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.announcement.data.AnnouncementRepository; -import com.gg.server.domain.announcement.exception.AnnounceNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -class AnnouncementControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - AnnouncementRepository announcementRepository; - - @BeforeEach - void setUp() { - User admin = testDataUtils.createAdminUser(); - testDataUtils.createAnnouncements(admin, 5); - } - - @Test - @Transactional - @DisplayName("[GET]/pingpong/announcement") - void getAnnouncement() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - - String contentAsString = mockMvc.perform(get("/pingpong/announcement") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - - @Test - @Transactional - @DisplayName("[GET]/pingpong/announcement") - void getAnnouncementEmpty() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - Announcement announcement = announcementRepository.findFirstByOrderByIdDesc() - .orElseThrow(AnnounceNotFoundException::new); - - announcement.update("testId", LocalDateTime.now()); - - String contentAsString = mockMvc.perform(get("/pingpong/announcement") - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java b/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java deleted file mode 100644 index ab849ca07..000000000 --- a/src/test/java/com/gg/server/domain/coin/service/CoinHistoryServiceTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.gg.server.domain.coin.service; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.coin.data.CoinHistory; -import com.gg.server.domain.coin.data.CoinHistoryRepository; -import com.gg.server.domain.coin.data.CoinPolicy; -import com.gg.server.domain.coin.data.CoinPolicyRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@Transactional -class CoinHistoryServiceTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - CoinHistoryService coinHistoryService; - - @Autowired - CoinHistoryRepository coinHistoryRepository; - - @Autowired - UserRepository userRepository; - - @Autowired - CoinPolicyRepository coinPolicyRepository; - - @BeforeEach - void beforeEach() { - CoinPolicy coinPolicy = CoinPolicy.builder() - .user(testDataUtils.createAdminUser()) - .attendance(1) - .normal(3) - .rankWin(10) - .rankLose(5) - .build(); - coinPolicyRepository.save(coinPolicy); - } - - @Test - @DisplayName("์ถœ์„ ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") - void addAttendanceCoinHistory() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); - - coinHistoryService.addAttendanceCoinHistory(user); - - List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); - - assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); - - System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); - for(CoinHistory ch : afterCoinHistory){ - System.out.println("์ด๋ ฅ : " + ch.getHistory()); - System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); - System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); - System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); - } - } - - @Test - @DisplayName("์ผ๋ฐ˜๊ฒŒ์ž„ ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") - void addNormalCoin() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); - - coinHistoryService.addNormalCoin(user); - - List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); - - assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); - - System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); - for(CoinHistory ch : afterCoinHistory){ - System.out.println("์ด๋ ฅ : " + ch.getHistory()); - System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); - System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); - System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); - } - - - } - - @Test - @DisplayName("๋žญํฌ๊ฒŒ์ž„ win ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") - void addRankWinCoin() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); - - coinHistoryService.addRankWinCoin(user); - - List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); - - assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 1); - - System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); - for(CoinHistory ch : afterCoinHistory){ - System.out.println("์ด๋ ฅ : " + ch.getHistory()); - System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); - System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); - System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); - } - } - - @Test - @DisplayName("๋žญํฌ๊ฒŒ์ž„ lose ์žฌํ™”์ด๋ ฅ ๋“ฑ๋ก") - void addRankLoseCoin() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - int beforeCoinHistoryCount = coinHistoryRepository.findAllByUserOrderByIdDesc(user).size(); - - coinHistoryService.addRankLoseCoin(user); - coinHistoryService.addRankLoseCoin(user); - - List afterCoinHistory = coinHistoryRepository.findAllByUserOrderByIdDesc(user); - - assertThat(beforeCoinHistoryCount).isEqualTo(afterCoinHistory.size() - 2); - - System.out.println(beforeCoinHistoryCount + " < " + afterCoinHistory.size()); - for(CoinHistory ch : afterCoinHistory){ - System.out.println("์ด๋ ฅ : " + ch.getHistory()); - System.out.println("์‚ฌ์šฉ๊ฐ’ : " + ch.getAmount()); - System.out.println("์‚ฌ์šฉ์ž : " + ch.getUser().getIntraId()); - System.out.println("์ƒ์„ฑ๋‚ ์งœ : " + ch.getCreatedAt()); - } - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java b/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java deleted file mode 100644 index 6590eb462..000000000 --- a/src/test/java/com/gg/server/domain/coin/service/UserCoinChangeServiceTest.java +++ /dev/null @@ -1,222 +0,0 @@ -package com.gg.server.domain.coin.service; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.coin.data.CoinHistoryRepository; -import com.gg.server.domain.coin.data.CoinPolicy; -import com.gg.server.domain.coin.data.CoinPolicyRepository; -import com.gg.server.domain.coin.dto.UserGameCoinResultDto; -import com.gg.server.domain.coin.exception.CoinHistoryNotFoundException; -import com.gg.server.domain.coin.exception.CoinPolicyNotFoundException; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.data.ItemRepository; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@Transactional -class UserCoinChangeServiceTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - CoinHistoryService coinHistoryService; - - @Autowired - CoinHistoryRepository coinHistoryRepository; - - @Autowired - CoinPolicyRepository coinPolicyRepository; - - @Autowired - UserRepository userRepository; - - @Autowired - UserCoinChangeService userCoinChangeService; - - @Autowired - ItemRepository itemRepository; - - User admin; - - @BeforeEach - void init() { - admin = testDataUtils.createAdminUser(); - } - - @Test - @DisplayName("์ถœ์„์‹œ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") - void addAttendanceCoin() { - CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).attendance(100).build(); - coinPolicyRepository.save(coinPolicy); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - int beforeCoin = user.getGgCoin(); - - int coinIncrement = userCoinChangeService.addAttendanceCoin(user); - - assertThat(beforeCoin + coinIncrement).isEqualTo(user.getGgCoin()); - assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getAttendance()).isEqualTo(coinIncrement); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - - try{ - coinIncrement = userCoinChangeService.addAttendanceCoin(user); - }catch (Exception e){ - System.out.println(e.getMessage() + " " + e); - System.out.println("===์ถœ์„ ์ค‘๋ณต ์ œ๊ฑฐ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); - } - } - - @Test - @DisplayName("์•„์ดํ…œ ๊ตฌ๋งค์‹œ ์ฝ”์ธ์‚ฌ์šฉ ํ…Œ์ŠคํŠธ") - void purchaseItemCoin() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - user.addGgCoin(100); - int beforeCoin = user.getGgCoin(); - - Item item = new Item("๊ณผ์ž", "111", "1", "1", 100, true, 0, - ItemType.EDGE,LocalDateTime.now(), user.getIntraId()); - itemRepository.save(item); - - userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); - - assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()+coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getAmount()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - try{ - userCoinChangeService.purchaseItemCoin(item, item.getPrice(), userId); - }catch (Exception e){ - System.out.println(e.getMessage() + " " + e); - System.out.println("===coin์ด ์—†์„ ๋•Œ ๋ฐฉ์–ด๋กœ์ง ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); - } - } - - @Test - @DisplayName("์•„์ดํ…œ ์„ ๋ฌผ์‹œ ์ฝ”์ธ์‚ฌ์šฉ ํ…Œ์ŠคํŠธ") - void giftItemCoin() { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - user.addGgCoin(100); - int beforeCoin = user.getGgCoin(); - - Item item = new Item("๊ณผ์ž", "111", "1", "1", 100, true, 0, - ItemType.EDGE,LocalDateTime.now(), user.getIntraId()); - itemRepository.save(item); - - userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); - - assertThat(beforeCoin).isEqualTo(user.getGgCoin() + item.getPrice()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory() - +coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getAmount()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - - try{ - userCoinChangeService.giftItemCoin(item, item.getPrice(), user, user); - }catch (Exception e){ - System.out.println(e.getMessage() + " " + e); - System.out.println("===coin์ด ์—†์„ ๋•Œ ๋ฐฉ์–ด๋กœ์ง ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์™„๋ฃŒ==="); - } - } - - @Test - @DisplayName("๋…ธ๋ง ๊ฒŒ์ž„ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") - void addNormalGameService() { - CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).normal(100).build(); - coinPolicyRepository.save(coinPolicy); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService.addNormalGameCoin(userId); - - assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); - assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getNormal()).isEqualTo(userGameCoinResultDto.getCoinIncrement()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - } - - @Test - @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ์Šน๋ฆฌ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") - void addRankWinGameService() { - CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).rankWin(100).build(); - coinPolicyRepository.save(coinPolicy); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - Season season = testDataUtils.createSeason(); - Game mockMatch = testDataUtils.createMockMatch(user, season, - LocalDateTime.now().minusMinutes(20), - LocalDateTime.now().minusMinutes(5), Mode.RANK, 2, 1); - UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService - .addRankGameCoin(mockMatch.getId(), user.getId());//๋ณธ์ธ์˜ ๊ฒŒ์ž„Id์™€ id ๊ฐ’ - - assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); - assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankWin()) - .isEqualTo(userGameCoinResultDto.getCoinIncrement()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - } - - @Test - @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ํŒจ๋ฐฐ ์žฌํ™” ์ฆ๊ฐ€ ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ") - void addRankLoseGameService() { - CoinPolicy coinPolicy = CoinPolicy.builder().user(admin).rankLose(100).build(); - coinPolicyRepository.save(coinPolicy); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - - Season season = testDataUtils.createSeason(); - Game mockMatch = testDataUtils.createMockMatch(user, season, - LocalDateTime.now().minusMinutes(20), - LocalDateTime.now().minusMinutes(5), Mode.RANK, 1, 2); - - UserGameCoinResultDto userGameCoinResultDto = userCoinChangeService - .addRankGameCoin(mockMatch.getId(), user.getId()); - - assertThat(user.getGgCoin()).isEqualTo(userGameCoinResultDto.getAfterCoin()); - assertThat(coinPolicyRepository.findTopByOrderByCreatedAtDesc() - .orElseThrow(() -> new CoinPolicyNotFoundException()).getRankLose()) - .isEqualTo(userGameCoinResultDto.getCoinIncrement()); - System.out.println(coinHistoryRepository.findFirstByOrderByIdDesc() - .orElseThrow(() -> new CoinHistoryNotFoundException()).getHistory()); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/feedback/controller/FeedbackControllerTest.java b/src/test/java/com/gg/server/domain/feedback/controller/FeedbackControllerTest.java deleted file mode 100644 index 7f96f2ef3..000000000 --- a/src/test/java/com/gg/server/domain/feedback/controller/FeedbackControllerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.gg.server.domain.feedback.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.feedback.data.Feedback; -import com.gg.server.domain.feedback.data.FeedbackRepository; -import com.gg.server.domain.feedback.dto.FeedbackRequestDto; -import com.gg.server.domain.feedback.type.FeedbackType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -class FeedbackControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - FeedbackRepository feedbackRepository; - - @Test - @Transactional - @DisplayName("[Post]/pingpong/feedback") - void getAnnouncementList() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - System.out.println(userId); - - FeedbackRequestDto addDto = FeedbackRequestDto.builder() - .content("ํ•˜๋‚˜ํ•˜๋‚˜๋‘˜๋‘˜ํ…Œ์ŠคํŠธ") - .category(FeedbackType.ETC) - .build(); - - String content = objectMapper.writeValueAsString(addDto); - String url = "/pingpong/feedback"; - - String contentAsString = mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - Feedback result = feedbackRepository.findFirstByOrderByIdDesc(); - assertThat(result.getCategory()).isEqualTo(addDto.getCategory()); - assertThat(result.getContent()).isEqualTo(addDto.getContent()); - - System.out.println(result.getId() + ", " + result.getUser().getIntraId()); - } - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/game/GameControllerTest.java b/src/test/java/com/gg/server/domain/game/GameControllerTest.java deleted file mode 100644 index 813b5d7dd..000000000 --- a/src/test/java/com/gg/server/domain/game/GameControllerTest.java +++ /dev/null @@ -1,776 +0,0 @@ -package com.gg.server.domain.game; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GameTeamInfo; -import com.gg.server.domain.game.dto.request.RankResultReqDto; -import com.gg.server.domain.game.dto.request.TournamentResultReqDto; -import com.gg.server.domain.game.service.GameFindService; -import com.gg.server.domain.game.service.GameService; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RankRedisService; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@AutoConfigureMockMvc -@RequiredArgsConstructor -@Transactional -public class GameControllerTest { - @Autowired - GameRepository gameRepository; - @Autowired - SeasonRepository seasonRepository; - @Autowired - TeamRepository teamRepository; - @Autowired - TeamUserRepository teamUserRepository; - @Autowired - RankRedisRepository rankRedisRepository; - - @Autowired - TierRepository tierRepository; - - @Autowired - PChangeRepository pChangeRepository; - @Autowired - TournamentRepository tournamentRepository; - @Autowired - RankRedisService rankRedisService; - @Autowired - RankRepository rankRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - GameService gameService; - @Autowired - GameFindService gameFindService; - @Autowired - private MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - private String accessToken; - private Season season; - private User user1; - private User user2; - private User user3; - private Game game1; - private Game game2; - ArrayList tiers; - - @BeforeEach - void init() { - tiers = testDataUtils.createTierSystem("pingpong"); - season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 7, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), - 1000, 100)); - user1 = testDataUtils.createNewUser("test1", "test1@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - accessToken = tokenProvider.createToken(user1.getId()); - user2 = testDataUtils.createNewUser("test2", "test2@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - Tier tier = tiers.get(0); - rankRepository.save(Rank.from(user1, season, season.getStartPpp(), tier)); - rankRepository.save(Rank.from(user2, season, season.getStartPpp(), tier)); - RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp(), tier.getImageUri()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); - userRank = RankRedis.from(UserDto.from(user2), season.getStartPpp(), tier.getImageUri()); - rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank); - - game1 = gameRepository.save(new Game(season, StatusType.END, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game1, 1, false)); - Team team2 = teamRepository.save(new Team(game1, 2, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - game2 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - team1 = teamRepository.save(new Team(game2, 1, false)); - team2 = teamRepository.save(new Team(game2, 2, true)); - List teams = new ArrayList<>(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - gameService.expUpdates(game2, teams); - rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game2); - } - - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - - // GET /pingpong/games/{gameId} - @Nested - @DisplayName("๊ฒŒ์ž„ ์กฐํšŒ ํ…Œ์ŠคํŠธ") - class GetGameInfoTest { - /** - * getGameInfo() -> GameFindService.getGameInfo() - */ - @Test - @DisplayName("์œ ์ € ์ฟผ๋ฆฌ ํฌํ•จ ์„ฑ๊ณต") - public void getGameInfoTest() throws Exception { - //given - String url = "/pingpong/games/" + game1.getId().toString(); - GameTeamInfo expect = gameService.getUserGameInfo(game1.getId(), user1.getId()); - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - GameTeamInfo result = objectMapper.readValue(contentAsString, GameTeamInfo.class); - System.out.println("expect: " + expect); - System.out.println("result: " + result); - assertThat(result.getGameId()).isEqualTo(expect.getGameId()); - assertThat(result.getStartTime()).isEqualTo(expect.getStartTime()); - assertThat(result.getMatchTeamsInfo().getMyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getMyTeam().getTeamId()); - assertThat(result.getMatchTeamsInfo().getEnemyTeam().getTeamId()).isEqualTo(expect.getMatchTeamsInfo().getEnemyTeam().getTeamId()); - } - } - - // GET /pingpong/games/normal - @Nested - @DisplayName("normal ๊ฒŒ์ž„ ์กฐํšŒ") - class NormalGameListTest { - /** - * GET /pingpong/games/normal?page=1&size=10 - * normalGameList() -> GameFindService.normalGameList() - */ - @Test - @DisplayName("์กฐํšŒ ์„ฑ๊ณต") - public void success() throws Exception { - //given - testDataUtils.createGame(user1, LocalDateTime.now().minusMinutes(16), - LocalDateTime.now().minusMinutes(1), season, Mode.NORMAL); - String url = "/pingpong/games/normal?page=1&size=10"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.getNormalGameList(pageable); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - /** - * GET /pingpong/games/normal?page=1&size=10&intraId=test1 - * normalGameList() -> GameFindService.normalGameListByIntra() - */ - @Test - @DisplayName("์œ ์ € ์ฟผ๋ฆฌ ํฌํ•จ ์„ฑ๊ณต") - public void successUserQuery() throws Exception { - //given - String url = "/pingpong/games/normal?page=1&size=10&intraId=test1"; - for (int i = 0; i < 10; i++) { - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, 1, false)); - Team team2 = teamRepository.save(new Team(game, 2, true)); - List teams = new ArrayList<>(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - gameService.expUpdates(game, teams); - rankRedisService.updateRankRedis(teams.get(0), teams.get(1), game); - game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - team1 = teamRepository.save(new Team(game, 0, false)); - team2 = teamRepository.save(new Team(game, 0, false)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - teams.clear(); - teams.add(teamUserRepository.save(new TeamUser(team1, user1))); - teams.add(teamUserRepository.save(new TeamUser(team2, user2))); - game.updateStatus(); - gameService.expUpdates(game, teams); - pChangeRepository.save(new PChange(game, user1, 0, true)); - pChangeRepository.save(new PChange(game, user2, 0, true)); - } - - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.normalGameListByIntra(pageable, "test1"); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - } - - // GET /pingpong/games/rank - @Nested - @DisplayName("rank ๊ฒŒ์ž„ ์กฐํšŒ") - class RankGameListTest { - /** - * GET /pingpong/games/rank?page=1&size=10&seasonId=1 - * rankGameList() -> GameFindService.rankGameList() - */ - @Test - @DisplayName("์กฐํšŒ ์„ฑ๊ณต") - public void success() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId(); - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.rankGameList(pageable, season.getId()); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - /** - * GET /pingpong/games/rank?page=1&size=10&seasonId={seasonId}&nickname=test1 - * rankGameList() -> GameFindService.rankGameListByIntra() - */ - @Test - @DisplayName("nickname ์ฟผ๋ฆฌ ํฌํ•จ ์กฐํšŒ ์„ฑ๊ณต") - public void successNicknameQuery() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=10&seasonId=" + season.getId() + "&nickname=" + "test1"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.rankGameListByIntra(pageable, season.getId(), "test1"); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(0).getGameId().equals(expect.getGames().get(0).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - /** - * GET /pingpong/games/rank?page=1&size=0 - * allGameList() -> GameFindService.allGameList() - */ - @Test - @DisplayName("Bad Request exception ๋ฐœ์ƒ") - public void failBadRequest() throws Exception { - //given - String url = "/pingpong/games/rank?page=1&size=0"; - //then - mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - } - - // GET /pingpong/games - @Nested - @DisplayName("์ „์ฒด ๊ฒŒ์ž„ ๋ชฉ๋ก ์กฐํšŒ") - class AllGameListTest { - /** - * GET /pingpong/games?page=1&size=10 - */ - @Test - @DisplayName("์กฐํšŒ ์„ฑ๊ณต") - public void success() throws Exception { - //given - String url = "/pingpong/games?page=1&size=10"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.allGameList(pageable, null); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(result.getGames().size() - 1).getGameId().equals(expect.getGames().get(expect.getGames().size() - 1).getGameId())); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - /** - * GET /pingpong/games?page=1&size=10&nickname=test1 - */ - @Test - @DisplayName("nickname ์ฟผ๋ฆฌ ํฌํ•จ ์กฐํšŒ ์„ฑ๊ณต") - public void suceessNicknameQuery() throws Exception { - //given - String url = "/pingpong/games?page=1&size=10&nickname=test1"; - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto expect = gameFindService.allGameListUser(pageable, "test1", null); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - GameListResDto result = objectMapper.readValue(contentAsString, GameListResDto.class); - //then - System.out.println(result.getGames().size() +", " + result.getIsLast()); - System.out.println(expect.getGames().size() + ", " + expect.getIsLast()); - assertThat(result.getGames().size()).isEqualTo(expect.getGames().size()); - assertThat(result.getGames().get(result.getGames().size() - 1).getGameId()).isEqualTo(expect.getGames().get(expect.getGames().size() - 1).getGameId()); - assertThat(result.getIsLast()).isEqualTo(expect.getIsLast()); - } - - /** - * GET /pingpong/games?pageNum=1&pageSize=10&status=live - */ - @Test - @DisplayName("์ž˜๋ชป๋œ query parameter์ธ ๊ฒฝ์šฐ, Bad Request exception ๋ฐœ์ƒ") - public void failBadRequest() throws Exception { - String url = "/pingpong/games?pageNum=1&pageSize=10&status=live"; // LIVE ๋Œ€๋ฌธ์ž์—ฌ์•ผ ํ•จ - mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - } - - /** - * GET /pingpong/games?page=1&size=10&status=2 - */ - @Test - @DisplayName("์ž˜๋ชป๋œ query parameter์ธ ๊ฒฝ์šฐ, Bad Request exception ๋ฐœ์ƒ") - public void failBadRequest2() throws Exception { - String url = "/pingpong/games?page=1&size=10&status=2"; - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - System.out.println(contentAsString); - } - } - - // POST /pingpong/games/rank - @Nested - @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ์ ์ˆ˜ ๊ฒฐ๊ณผ ์ž…๋ ฅ") - class CreateRankResultTest { - /** - * POST /pingpong/games/rank - */ - @Test - @DisplayName("๋‘˜ ์ค‘ ํ•œ๋ช… ์ž…๋ ฅ ํ›„ ๋‚˜๋จธ์ง€ ํ•œ ๋ช…์ด ์ž…๋ ฅํ•  ๊ฒฝ์šฐ conflict exception ๋ฐœ์ƒ") - public void success() throws Exception { - String url = "/pingpong/games/rank"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.RANK, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - String ac2 = tokenProvider.createToken(user2.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - teamUserRepository.flush(); - gameRepository.flush(); - teamRepository.flush(); - String content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - // then - System.out.println("======================="); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse(); - System.out.println("======================="); - content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isConflict()) - .andReturn().getResponse(); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - } - - // TODO : ๋žญํฌ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์ž…๋ ฅ ์‹คํŒจ ํ…Œ์ŠคํŠธ (์ž˜๋ชป๋œ ์ ์ˆ˜ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ InvalidParameterException ๋ฐœ์ƒ) - } - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ ์ˆ˜ ๊ฒฐ๊ณผ ์ž…๋ ฅ") - class CreateTournamentResultTest { - @Test - @DisplayName("์ž…๋ ฅ ์„ฑ๊ณต") - public void success() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Tournament tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "ttt"); - List tournamentGameList = testDataUtils.createTournamentGameList(tournament, Tournament.ALLOWED_JOINED_NUMBER - 1); - // 8๊ฐ• ๊ฒฝ๊ธฐ ์ƒ์„ฑ - Game game = null; - Team team1 = null; - Team team2 = null; - for (int i = 0; i < Tournament.ALLOWED_JOINED_NUMBER / 2; ++i) { - game = new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now()); - team1 = new Team(game, -1, false); - team2 = new Team(game, -1, false); - TeamUser teamUser1 = new TeamUser(team1, tournament.getTournamentUsers().get(i * 2).getUser()); - TeamUser teamUser2 = new TeamUser(team2, tournament.getTournamentUsers().get(i * 2 + 1).getUser()); - gameRepository.save(game); - tournamentGameList.get(i).updateGame(game); - } - - testDataUtils.createUserRank(team1.getTeamUsers().get(0).getUser(), "", season); - testDataUtils.createUserRank(team2.getTeamUsers().get(0).getUser(), "", season); - - String ac1 = tokenProvider.createToken(team1.getTeamUsers().get(0).getUser().getId()); - String content = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - - //when - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsString(); - - //then - assertThat(game.getStatus()).isEqualTo(StatusType.END); - assertThat(pChangeRepository.findByUserIdAndGameId(team1.getTeamUsers().get(0).getUser().getId(), game.getId())).isNotEmpty(); - assertThat(pChangeRepository.findByUserIdAndGameId(team2.getTeamUsers().get(0).getUser().getId(), game.getId())).isNotEmpty(); - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ Game Id") - public void invalidGameId() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content = objectMapper.writeValueAsString(new TournamentResultReqDto(99999999L, team1.getId(), 1, team2.getId(), 2)); - //when - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - //then - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ Team Id") - public void invalidTeamId() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Game game2 = gameRepository.save(new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(30), LocalDateTime.now().minusMinutes(15))); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - Team team3 = teamRepository.save(new Team(game2, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content1 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), -1L, 1, team2.getId(), 2)); - String content2 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, -1L, 2)); - String content3 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, team3.getId(), 2)); - //when1 - ์กด์žฌํ•˜์ง€ ์•Š๋Š” myTeamId - String contentAsString1 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content1)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then - System.out.println(contentAsString1); - - //when2 - ์กด์žฌํ•˜์ง€ ์•Š๋Š” enemyTeamId - String contentAsString2 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content2)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then2 - System.out.println(contentAsString2); - - //when3 - game์— ์กด์žฌํ•˜์ง€ ์•Š์€ TeamId - String contentAsString3 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content3)) - .andExpect(status().isNotFound()) - .andReturn().getResponse().getContentAsString(); - //then3 - System.out.println(contentAsString2); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ ์ ์ˆ˜") - public void invalidScore() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content1 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), -1, team2.getId(), 2)); - String content2 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 1)); - String content3 = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 3, team2.getId(), 0)); - //when1 - String contentAsString1 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content1)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then1 - System.out.println(contentAsString1); - - //when2 - String contentAsString2 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content2)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then2 - System.out.println(contentAsString2); - - //when3 - String contentAsString3 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content3)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then3 - System.out.println(contentAsString3); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ Game Status") - public void invalidStatus() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Game game = gameRepository.save(new Game(season, StatusType.END, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - //when - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ด๋ฏธ ์ ์ˆ˜ ์ž…๋ ฅ์ด ์™„๋ฃŒ๋œ ๊ฒŒ์ž„") - public void scoreAlreadyEntered() throws Exception { - //given - String url = "/pingpong/games/tournament"; - Game game = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, 2, true)); - Team team2 = teamRepository.save(new Team(game, 1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 2, team2.getId(), 1)); - //when - String contentAsString = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then - System.out.println(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ Team User") - public void invalidTeamUser() throws Exception { - //given - String url = "/pingpong/games/tournament"; - user3 = testDataUtils.createNewUser("test3", "test3@email", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.TOURNAMENT, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - teamUserRepository.save(new TeamUser(team1, user3)); - teamUserRepository.save(new TeamUser(team2, user2)); - String content = objectMapper.writeValueAsString(new TournamentResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - //when - String contentAsString1 = mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - //then - System.out.println(contentAsString1); - } - } - - // POST /pingpong/games/normal - @Nested - @DisplayName("์ผ๋ฐ˜ ๊ฒŒ์ž„ ์ข…๋ฃŒ ๋ฒ„ํŠผ ํด๋ฆญ") - class CreateNormalResultTest { - /** - * POST /pingpong/games/normal - */ - @Test - @DisplayName("๊ฒŒ์ž„ ์ข…๋ฃŒ") - public void success() throws Exception { - String url = "/pingpong/games/normal"; - Game game = gameRepository.save(new Game(season, StatusType.WAIT, Mode.NORMAL, LocalDateTime.now().minusMinutes(15), LocalDateTime.now())); - Team team1 = teamRepository.save(new Team(game, -1, false)); - Team team2 = teamRepository.save(new Team(game, -1, false)); - String ac1 = tokenProvider.createToken(user1.getId()); - String ac2 = tokenProvider.createToken(user2.getId()); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - teamUserRepository.flush(); - gameRepository.flush(); - teamRepository.flush(); - String content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team1.getId(), 1, team2.getId(), 2)); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - // then - System.out.println("======================="); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac1) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse(); - System.out.println("======================="); - content = objectMapper.writeValueAsString(new RankResultReqDto(game.getId(), team2.getId(), 2, team1.getId(), 1)); - mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + ac2) - .contentType(MediaType.APPLICATION_JSON) - .content(content)) - .andExpect(status().isCreated()) - .andReturn().getResponse(); - System.out.println(user1.getTotalExp()); - System.out.println(user2.getTotalExp()); - } - // TODO HttpStatus.ACCEPTED ํ…Œ์ŠคํŠธ - service ํ•จ์ˆ˜์—์„œ BEFORE ์ƒํƒœ์ผ ๋•Œ false ๋ฆฌํ„ดํ•  ๊ฒฝ์šฐ - } - - @Nested - @DisplayName("/{gameId}/result?mode=?") - class GameChangeRestTest { - @Test - @DisplayName("๋žญํฌ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") - public void successGetRankPPPChange() throws Exception { - Game mockMatch = testDataUtils.createMockMatch(user1, season, - LocalDateTime.now().minusMinutes(16), - LocalDateTime.now().minusMinutes(1), Mode.RANK); - testDataUtils.createUserRank(user1, "hello", season, tiers.get(0)); - testDataUtils.createCoinPolicy(user1, 0, 0, 1, 0); - - String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.RANK; - String content = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println("result: " + content); - } - - @Test - @DisplayName("์ผ๋ฐ˜ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") - public void normalGameResult() throws Exception { - Game mockMatch = testDataUtils.createMockMatch(user1, season, - LocalDateTime.now().minusMinutes(16), - LocalDateTime.now().minusMinutes(1), Mode.NORMAL); - testDataUtils.createCoinPolicy(user1, 0, 1, 0, 0); - String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.NORMAL; - String content = mockMvc.perform( - get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println("result: " + content); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ ์กฐํšŒ") - public void tournamentGameResult() throws Exception { - Game mockMatch = testDataUtils.createMockMatch(user1, season, - LocalDateTime.now().minusMinutes(16), - LocalDateTime.now().minusMinutes(1), Mode.TOURNAMENT); - testDataUtils.createCoinPolicy(user1, 0, 1, 0, 0); - String url = "/pingpong/games/" + mockMatch.getId() + "/pchange/result?mode=" + Mode.TOURNAMENT; - String content = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - System.out.println("result: " + content); - } - } -} diff --git a/src/test/java/com/gg/server/domain/game/data/GameUnitTest.java b/src/test/java/com/gg/server/domain/game/data/GameUnitTest.java deleted file mode 100644 index 632deb614..000000000 --- a/src/test/java/com/gg/server/domain/game/data/GameUnitTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.gg.server.domain.game.data; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; - -import com.gg.server.domain.team.data.Team; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import com.gg.server.utils.annotation.UnitTest; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@UnitTest -@DisplayName("GameUnitTest") -class GameUnitTest { - List mockTeams; - List games; - - @BeforeEach - void setUp() { - mockTeams = IntStream.range(0, 10) - .mapToObj(i -> mock(Team.class)) - .collect(Collectors.toCollection(ArrayList::new)); - games = IntStream.range(0, 10) - .mapToObj(i -> new Game()) - .collect(Collectors.toCollection(ArrayList::new)); - } - - @Nested - @DisplayName("AddTeam") - class AddTeam { - @Test - @DisplayName("๋‹จ์ผ Team ์ถ”๊ฐ€ ์„ฑ๊ณต") - public void addSingleTeamSuccess() { - //given - Game game = games.get(0); - Team mockTeam = mockTeams.get(0); - - //when - game.addTeam(mockTeam); - - //then - assertEquals(1, game.getTeams().size()); - assertEquals(mockTeam, game.getTeams().get(0)); - } - - @Test - @DisplayName("๋‘๊ฐœ Team ์ถ”๊ฐ€ ์„ฑ๊ณต") - void addMultiTeamSuccess() { - //given - Game game = games.get(0); - - //when - game.addTeam(mockTeams.get(0)); - game.addTeam(mockTeams.get(1)); - - //then - assertEquals(2, game.getTeams().size()); - assertEquals(mockTeams.get(0), game.getTeams().get(0)); - assertEquals(mockTeams.get(1), game.getTeams().get(1)); - } - - @Test - @DisplayName("๋‘๊ฐœ ์ด์ƒ์˜ Team ์ถ”๊ฐ€ ์‹คํŒจ") - void addExceedTeamFailed() { - //given - Game game = games.get(0); - - //when - game.addTeam(mockTeams.get(0)); - game.addTeam(mockTeams.get(1)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> game.addTeam(mockTeams.get(2))); - assertEquals(ErrorCode.TEAM_SIZE_EXCEED, businessException.getErrorCode()); - assertEquals(ErrorCode.TEAM_SIZE_EXCEED.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("๋™์ผํ•œ Team ์ถ”๊ฐ€ ์‹คํŒจ") - void duplicatedTeamAddFailed() { - //given - Game game = games.get(0); - - //when - game.addTeam(mockTeams.get(0)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> game.addTeam(mockTeams.get(0))); - assertEquals(ErrorCode.TEAM_DUPLICATION, businessException.getErrorCode()); - assertEquals(ErrorCode.TEAM_DUPLICATION.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Game game = games.get(0); - - //when - Team team = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> game.addTeam(team)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/game/service/GameDBTest.java b/src/test/java/com/gg/server/domain/game/service/GameDBTest.java deleted file mode 100644 index 275962291..000000000 --- a/src/test/java/com/gg/server/domain/game/service/GameDBTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.gg.server.domain.game.service; - - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.gg.server.admin.game.service.GameAdminService; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.List; -import javax.persistence.EntityManager; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@AutoConfigureMockMvc -@Transactional -@Slf4j -public class GameDBTest { - - @Autowired - GameFindService gameFindService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - GameRepository gameRepository; - @Autowired - GameAdminService gameAdminService; - @Autowired - TeamRepository teamRepository; - @Autowired - TeamUserRepository teamUserRepository; - @Autowired - PChangeRepository pChangeRepository; - @Autowired - EntityManager em; - @Autowired - MockMvc mockMvc; - - @Test - @DisplayName(value = "Cascade ์ข…์†์‚ญ์ œํ…Œ์ŠคํŠธ") - @Transactional - public void Cascade์ข…์†์‚ญ์ œํ…Œ์ŠคํŠธ() throws Exception { - pChangeRepository.deleteAll(); - gameRepository.deleteAll(); - em.flush(); - List gameList = gameRepository.findAll(); - List teamList = teamRepository.findAll(); - List teamUserList = teamUserRepository.findAll(); - log.info("GAME LIST SIZE : " + Integer.toString(gameList.size())); - log.info("TEAM LIST SIZE: " + Integer.toString(teamList.size())); - log.info("TEAM_USER LIST SIZE: " + Integer.toString(teamUserList.size())); - Assertions.assertThat(teamList.size()).isEqualTo(0); - Assertions.assertThat(teamUserList.size()).isEqualTo(0); - } - - @Test - @DisplayName(value = "game ์ „์ ์กฐํšŒ ์ฟผ๋ฆฌ ์ˆ˜ ํ…Œ์ŠคํŠธ") - @Transactional - public void ๊ฒŒ์ž„์ „์ ์กฐํšŒ์ฟผ๋ฆฌํ…Œ์ŠคํŠธ() throws Exception { - Season season = testDataUtils.createSeason(); - User user = testDataUtils.createNewUser(); - for (int i = 0; i < 20; i++) { - testDataUtils.createMockMatch(user, season, LocalDateTime.now().minusMinutes(15 * i + 20), - LocalDateTime.now().minusMinutes(15 * i + 5), Mode.RANK, 2, 1); - } - //given - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/admin/games?page=1&seasonId=" + season.getId(); - - //when - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - } -} diff --git a/src/test/java/com/gg/server/domain/game/service/GameFindServiceTest.java b/src/test/java/com/gg/server/domain/game/service/GameFindServiceTest.java deleted file mode 100644 index a4bf97449..000000000 --- a/src/test/java/com/gg/server/domain/game/service/GameFindServiceTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.gg.server.domain.game.service; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.GameListResDto; -import com.gg.server.domain.game.dto.GameResultResDto; -import com.gg.server.domain.game.dto.GameTeamUser; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.Sort; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@Transactional -public class GameFindServiceTest { - - @Autowired - GameFindService gameFindService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - RankRedisRepository rankRedisRepository; - - @Autowired - TierRepository tierRepository; - - @Autowired - GameRepository gameRepository; - - @BeforeEach - void init() { - testDataUtils.createTierSystem("pingpong"); - Season season = testDataUtils.createSeason(); - User newUser = testDataUtils.createNewUser(); - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - String accessToken = tokenProvider.createToken(newUser.getId()); - String statusMsg = "status message test1"; - - LocalDateTime startTime = LocalDateTime.now().minusDays(1); - LocalDateTime endTime = startTime.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime, endTime); - - LocalDateTime startTime1 = LocalDateTime.now().minusDays(2); - LocalDateTime endTime1 = startTime1.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime1, endTime1); - - LocalDateTime startTime2 = LocalDateTime.now().minusDays(3); - LocalDateTime endTime2 = startTime2.plusMinutes(15); - testDataUtils.createMockMatch(newUser, season, startTime2, endTime2); - - testDataUtils.createUserRank(newUser, statusMsg, season); - RankRedis userRank = RankRedis.from(UserDto.from(newUser), season.getStartPpp(), tier.getImageUri()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, newUser.getId(), userRank); - } - - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - @Test - void ์ผ๋ฐ˜game๋ชฉ๋ก์กฐํšŒ() { - Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "startTime")); - GameListResDto response = gameFindService.getNormalGameList(pageable); - Slice games = gameRepository.findAllByModeAndStatus(Mode.NORMAL, StatusType.END, pageable); - GameListResDto expect = new GameListResDto(getGameResultList(games.getContent().stream().map(Game::getId).collect(Collectors.toList())), games.isLast()); - assertThat(response).isEqualTo(expect); - } - private List getGameResultList(List games) { - List teamViews = gameRepository.findTeamsByGameIsIn(games); - return teamViews.stream().map(GameResultResDto::new).collect(Collectors.toList()); - } - - -} diff --git a/src/test/java/com/gg/server/domain/game/service/GameServiceTest.java b/src/test/java/com/gg/server/domain/game/service/GameServiceTest.java deleted file mode 100644 index 3afe616a5..000000000 --- a/src/test/java/com/gg/server/domain/game/service/GameServiceTest.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.gg.server.domain.game.service; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.dto.request.RankResultReqDto; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.exception.RankNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tier.exception.TierNotFoundException; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@Transactional -public class GameServiceTest { - - @Autowired - RankRedisRepository rankRedisRepository; - - @Autowired - GameRepository gameRepository; - @Autowired - TeamRepository teamRepository; - - @Autowired - TeamUserRepository teamUserRepository; - - @Autowired - RankRepository rankRepository; - - @Autowired - TierRepository tierRepository; - - @Autowired - GameService gameService; - - User user1; - User user2; - Game game1; - Team team1, team2; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - - @BeforeEach - void init() { - testDataUtils.createTierSystem("pingpong"); - Season season = testDataUtils.createSeason(); - Tier tier = tierRepository.findStartTier().orElseThrow(TierNotFoundException::new); - user1 = testDataUtils.createNewUser(); - user2 = testDataUtils.createNewUser(); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); - game1 = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime, startTime.plusMinutes(15))); - team1 = teamRepository.save(new Team(game1, -1, false)); - team2 = teamRepository.save(new Team(game1, -1, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - String statusMsg = "status message test1"; - - testDataUtils.createUserRank(user1, statusMsg, season); - RankRedis userRank = RankRedis.from(UserDto.from(user1), season.getStartPpp(), tier.getImageUri()); - String redisHashKey = RedisKeyManager.getHashKey(season.getId()); - rankRedisRepository.addRankData(redisHashKey, user1.getId(), userRank); - statusMsg = "status message test2"; - testDataUtils.createUserRank(user2, statusMsg, season); - RankRedis userRank2 = RankRedis.from(UserDto.from(user2), season.getStartPpp(), tier.getImageUri()); - rankRedisRepository.addRankData(redisHashKey, user2.getId(), userRank2); - } - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - - @Test - void ppp๋ณ€ํ™”๋Ÿ‰_์กฐํšŒ_test() throws Exception { - String key = RedisKeyManager.getHashKey(game1.getSeason().getId()); - Integer user1BeforePpp = rankRedisRepository.findRankByUserId(key, user1.getId()) - .getPpp(); - System.out.println("Before ppp: " + user1BeforePpp); - assertThat(gameService.createRankResult(new RankResultReqDto(game1.getId(), team1.getId(), - 1, team2.getId(), 2), user1.getId())).isEqualTo(true); - Integer user1AfterPpp = rankRedisRepository.findRankByUserId(key, user1.getId()).getPpp(); - System.out.println("After ppp: " + rankRedisRepository.findRankByUserId(key, user1.getId()) - .getPpp()); - Rank rank = rankRepository.findByUserIdAndSeasonId(user1.getId(), game1.getSeason().getId()) - .orElseThrow(RankNotFoundException::new); - assertThat(rank.getPpp()).isEqualTo(user1AfterPpp); - assertThat(user1BeforePpp).isGreaterThan(user1AfterPpp); - } -} diff --git a/src/test/java/com/gg/server/domain/game/service/GameStatusServiceTest.java b/src/test/java/com/gg/server/domain/game/service/GameStatusServiceTest.java deleted file mode 100644 index 9a874f478..000000000 --- a/src/test/java/com/gg/server/domain/game/service/GameStatusServiceTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.gg.server.domain.game.service; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import lombok.RequiredArgsConstructor; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@RequiredArgsConstructor -@Transactional -public class GameStatusServiceTest { - @Autowired - private GameRepository gameRepository; - @Autowired private SeasonRepository seasonRepository; - @Autowired - private GameStatusService gameStatusService; - @Autowired - private RankRedisRepository rankRedisRepository; - @Autowired - TestDataUtils testDataUtils; - @Autowired - private TeamRepository teamRepository; - @Autowired - private TeamUserRepository teamUserRepository; - @Autowired - private SlotManagementRepository slotManagementRepository; - private Season season; - User user1; - User user2; - Game game1; - Game liveGame; - - @BeforeEach - void init() { - season = seasonRepository.save(new Season("test season", LocalDateTime.of(2023, 5, 14, 0, 0), LocalDateTime.of(2999, 12, 31, 23, 59), - 1000, 100)); - user1 = testDataUtils.createNewUser("test2", "test2@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - user2 = testDataUtils.createNewUser("test3", "test3@naver.com", RacketType.NONE, SnsType.EMAIL, RoleType.USER); - LocalDateTime now = LocalDateTime.now(); - LocalDateTime startTime = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), now.getHour(), now.getMinute()); - game1 = gameRepository.save(new Game(season, StatusType.BEFORE, Mode.RANK, startTime, startTime.plusMinutes(15))); - Team team1 = teamRepository.save(new Team(game1, 1, false)); - Team team2 = teamRepository.save(new Team(game1, 2, true)); - teamUserRepository.save(new TeamUser(team1, user1)); - teamUserRepository.save(new TeamUser(team2, user2)); - liveGame = gameRepository.save(new Game(season, StatusType.LIVE, Mode.RANK, startTime.minusMinutes(15), startTime)); - } - @AfterEach - public void flushRedis() { - rankRedisRepository.deleteAll(); - } - @Test - void gameBefore์ƒํƒœ๋ณ€๊ฒฝํ…Œ์ŠคํŠธ() throws Exception{ - System.out.println("g1.startTime: " + game1.getStartTime()); - System.out.println(game1.getStatus()); - gameStatusService.updateBeforeToLiveStatus(); - assertThat(game1.getStatus()).isEqualTo(StatusType.LIVE); - } - - @Test - void gameLIVE์ƒํƒœ๋ณ€๊ฒฝํ…Œ์ŠคํŠธ() throws Exception{ - gameStatusService.updateLiveToWaitStatus(); - assertThat(liveGame.getStatus()).isEqualTo(StatusType.WAIT); - } - - @Test - void game5๋ถ„์ „์•Œ๋ฆผํ…Œ์ŠคํŠธ() throws Exception{ - SlotManagement slotManagement = SlotManagement.builder() - .futureSlotTime(12) - .pastSlotTime(0) - .openMinute(5) - .gameInterval(15) - .startTime(LocalDateTime.now().minusMinutes(1)) - .build(); - slotManagementRepository.save(slotManagement); - System.out.println("=============="); - gameStatusService.imminentGame(); - } -} diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java deleted file mode 100644 index da7d65cb2..000000000 --- a/src/test/java/com/gg/server/domain/item/controller/ItemGiftControllerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.gg.server.domain.item.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.dto.ItemGiftRequestDto; -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import javax.transaction.Transactional; - -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class ItemGiftControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - private MockMvc mockMvc; - - @MockBean - private ItemService itemService; - - @Test - @DisplayName("[Post]/pingpong/items/gift/{itemId} - success") - public void giftItemSuccessTest() throws Exception { - - // given - Long testItemId = 1L; - UserDto testUser = UserDto.builder() - .id(1L) - .intraId("testIntraId") - .build(); - - ItemGiftRequestDto requestDto = new ItemGiftRequestDto("recipientId"); - - doNothing().when(itemService).giftItem(testItemId, requestDto.getOwnerId(), testUser); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - System.out.println(userId); - String url = "/pingpong/items/gift/" + testItemId; - - // when - mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(requestDto))) - .andExpect(status().isCreated()); - - } -} diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java deleted file mode 100644 index dbe2dfee5..000000000 --- a/src/test/java/com/gg/server/domain/item/controller/ItemPurchaseControllerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.gg.server.domain.item.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.web.servlet.MockMvc; -import javax.transaction.Transactional; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class ItemPurchaseControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - private MockMvc mockMvc; - - @MockBean - private ItemService itemService; - - @Test - @DisplayName("[Post]/pingpong/items/purchases/{itemId} - success") - public void purchaseItemSuccessTest() throws Exception { - - // given - Long testItemId = 1L; - UserDto testUser = UserDto.builder() - .id(1L) - .intraId("testIntraId") - .build(); - - doNothing().when(itemService).purchaseItem(testItemId, testUser); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - System.out.println(userId); - String url = "/pingpong/items/purchases/" + testItemId; - - // when - mockMvc.perform(post(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isCreated()); - - } -} diff --git a/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java deleted file mode 100644 index d974ead62..000000000 --- a/src/test/java/com/gg/server/domain/item/controller/ItemStoreListControllerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.gg.server.domain.item.controller; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.data.ItemRepository; -import com.gg.server.domain.item.dto.ItemStoreListResponseDto; -import com.gg.server.domain.item.dto.ItemStoreResponseDto; -import com.gg.server.domain.item.service.ItemService; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.boot.test.mock.mockito.MockBean; - -import static com.gg.server.domain.item.type.ItemType.*; -import static org.assertj.core.api.Assertions.assertThat; -import javax.transaction.Transactional; -import java.util.Arrays; -import java.util.List; -import static org.mockito.Mockito.when; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class ItemStoreListControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ItemRepository itemRepository; - - @MockBean - private ItemService itemService; - - @Test - @DisplayName("[Get]/pingpong/items/store") - public void getAllItemsTest() throws Exception { - - //given - List testItems = Arrays.asList( - new ItemStoreResponseDto(1L, "itemName 1", "mainContent 1","subContent 1", MEGAPHONE, "ImageUrl 1", 1000, 10, 900), - new ItemStoreResponseDto(2L, "itemName 2", "mainContent 2","subContent 2", PROFILE_IMAGE, "ImageUrl 2", 2000, 20, 1800), - new ItemStoreResponseDto(3L, "itemName 3", "mainContent 2","subContent 2", TEXT_COLOR, "ImageUrl 3", 3000, 30, 2700) - ); - ItemStoreListResponseDto testResponse = new ItemStoreListResponseDto(testItems); - when(itemService.getAllItems()).thenReturn(testResponse); - - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - System.out.println(userId); - String url = "/pingpong/items/store"; - - //when - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - //then - ItemStoreListResponseDto result = objectMapper.readValue(contentAsString, ItemStoreListResponseDto.class); - assertThat(result.getItemList()).isNotNull(); - assertThat(result.getItemList()).isNotEmpty(); - assertThat(result.getItemList()).hasSize(testItems.size()); - - for (int i = 0; i < result.getItemList().size(); i++) { - ItemStoreResponseDto actual = result.getItemList().get(i); - ItemStoreResponseDto expected = testItems.get(i); - - assertThat(actual.getItemId()).isEqualTo(expected.getItemId()); - assertThat(actual.getItemName()).isEqualTo(expected.getItemName()); - assertThat(actual.getMainContent()).isEqualTo(expected.getMainContent()); - assertThat(actual.getSubContent()).isEqualTo(expected.getSubContent()); - assertThat(actual.getItemType()).isEqualTo(expected.getItemType()); - assertThat(actual.getImageUri()).isEqualTo(expected.getImageUri()); - assertThat(actual.getOriginalPrice()).isEqualTo(expected.getOriginalPrice()); - assertThat(actual.getDiscount()).isEqualTo(expected.getDiscount()); - assertThat(actual.getSalePrice()).isEqualTo(expected.getSalePrice()); - } - - System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result)); - } -} diff --git a/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java b/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java deleted file mode 100644 index 2ee964640..000000000 --- a/src/test/java/com/gg/server/domain/item/controller/UserItemResponseControllerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.gg.server.domain.item.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.service.ItemService; -import com.gg.server.utils.TestDataUtils; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.HttpHeaders; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -public class UserItemResponseControllerTest { - - @Autowired - ItemService itemService; - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - MockMvc mockMvc; - - @Test - @DisplayName("GET /pingpong/items?page=1&size=20") - public void getItemByUser() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - - Integer page = 1; - Integer size = 20; - - String url = "/pingpong/items?page=" + page + "&size=" + size; - - mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/match/dto/MatchStatusDtoUnitTest.java b/src/test/java/com/gg/server/domain/match/dto/MatchStatusDtoUnitTest.java deleted file mode 100644 index 545eea571..000000000 --- a/src/test/java/com/gg/server/domain/match/dto/MatchStatusDtoUnitTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.gg.server.domain.match.dto; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.utils.annotation.UnitTest; -import java.time.LocalDateTime; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -@UnitTest -class MatchStatusDtoUnitTest { - - @Nested - @DisplayName("MatchStatusDto(Game game, String userIntraId, String enemyIntraId, SlotManagement slotManagement)") - class MatchStatusDtoConstructor { - Game tournamentGame; - Game rankGame; - Game normalGame; - SlotManagement slotManagement; - String userIntraId = "myId"; - String enemyIntraId = "enemyId"; - LocalDateTime time = LocalDateTime.now(); - - @BeforeEach - void setup() { - tournamentGame = mock(Game.class); - rankGame = mock(Game.class); - normalGame = mock(Game.class); - slotManagement = mock(SlotManagement.class); - when(slotManagement.getOpenMinute()).thenReturn(5); - } - - @ParameterizedTest - @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ์ธ ๊ฒฝ์šฐ ํ•ญ์ƒ Imminent") - @ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) - void IfGameTypeTournamentAlwaysImminent(int arg) { - //Arrange - when(tournamentGame.getMode()).thenReturn(Mode.TOURNAMENT); - when(tournamentGame.getStartTime()).thenReturn(time.plusMinutes(arg)); - - //Act - MatchStatusDto dto = new MatchStatusDto(tournamentGame, userIntraId, enemyIntraId, slotManagement); - - //Assert - Assertions.assertThat(dto.getIsImminent()).isEqualTo(true); - } - - @ParameterizedTest - @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์‹œ๊ฐ„์— ๋”ฐ๋ผ NotImminent") - @ValueSource(ints = {6, 7, 8, 9, 10}) - void RankAndNormalGameNotImminent(int arg) { - //Arrange - when(rankGame.getMode()).thenReturn(Mode.RANK); - when(normalGame.getMode()).thenReturn(Mode.RANK); - when(rankGame.getStartTime()).thenReturn(time.plusMinutes(arg)); - when(normalGame.getStartTime()).thenReturn(time.plusMinutes(arg)); - - //Act - MatchStatusDto rankDto = new MatchStatusDto(rankGame, userIntraId, enemyIntraId, slotManagement); - MatchStatusDto normalDto = new MatchStatusDto(normalGame, userIntraId, enemyIntraId, slotManagement); - - //Assert - Assertions.assertThat(rankDto.getIsImminent()) - .isEqualTo(normalDto.getIsImminent()) - .isEqualTo(false); - } - - @ParameterizedTest - @DisplayName("Game Mode ๊ฐ€ ํ† ๋„ˆ๋จผํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์‹œ๊ฐ„์— ๋”ฐ๋ผ Imminent") - @ValueSource(ints = {0, 1, 2, 3, 4, 5}) - void RankAndNormalGameImminent(int arg) { - //Arrange - when(rankGame.getMode()).thenReturn(Mode.RANK); - when(normalGame.getMode()).thenReturn(Mode.RANK); - when(rankGame.getStartTime()).thenReturn(time.plusMinutes(arg)); - when(normalGame.getStartTime()).thenReturn(time.plusMinutes(arg)); - - //Act - MatchStatusDto rankDto = new MatchStatusDto(rankGame, userIntraId, enemyIntraId, slotManagement); - MatchStatusDto normalDto = new MatchStatusDto(normalGame, userIntraId, enemyIntraId, slotManagement); - - //Assert - Assertions.assertThat(rankDto.getIsImminent()) - .isEqualTo(normalDto.getIsImminent()) - .isEqualTo(true); - } - } - - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java b/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java deleted file mode 100644 index 9c8eac3f5..000000000 --- a/src/test/java/com/gg/server/domain/match/service/MatchBothServiceTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.admin.penalty.type.PenaltyKey; -import com.gg.server.utils.MatchTestUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.match.data.RedisMatchTimeRepository; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import lombok.RequiredArgsConstructor; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@Transactional -@AutoConfigureMockMvc -@RequiredArgsConstructor -class MatchBothServiceTest { - @Autowired - MatchFindService matchFindService; - @Autowired - MatchService matchService; - @Autowired - RedisMatchTimeRepository redisMatchTimeRepository; - @Autowired - RedisMatchUserRepository redisMatchUserRepository; - @Autowired - RedisConnectionFactory redisConnectionFactory; - @Autowired - RedisTemplate redisTemplate; - @Autowired - MatchTestUtils matchTestSetting; - @Autowired - GameRepository gameRepository; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - PenaltyAdminRepository penaltyAdminRepository; - @Autowired - PenaltyUserRedisRepository penaltyUserRedisRepository; - @Autowired - SlotManagementRepository slotManagementRepository; - @Autowired - TestDataUtils testDataUtils; - List users; - List slotTimes; - - Season testSeason; - - @BeforeEach - void init() { - testDataUtils.createTierSystem("pingpong"); - testDataUtils.createSeason(); - Random random = new Random(); - Integer userCount = random.nextInt(10) + 5; - Integer pppGap = random.nextInt(100) + 50; - Season season = matchTestSetting.makeTestSeason(pppGap); - this.testSeason = season; - List users = new ArrayList(); - for(int i = 0; i < userCount; i++) { - User user = matchTestSetting.createUser(); - users.add(user); - } - this.users = users; - users.stream().forEach(user -> - matchTestSetting.addUsertoRankRedis(user.getId(), 1000, season.getId())); - SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); - List slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); - this.slotTimes = slotTimes; - } - @AfterEach - void clear() { - RedisConnection connection = redisConnectionFactory.getConnection(); - connection.flushDb(); - connection.close(); - } - - @DisplayName("both ๋งค์นญ ์‹œ๋ฎฌ๋ ˆ์ด์…˜") - @Test - void makeGameWithNormalAndBoth() { - System.out.println("this.users = " + this.users); - // ์œ ์ € 0 slot 2, 3, 0 ๋“ฑ๋ก ์œ ์ € 1 slot 2 - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); - - System.out.println("matchFindService.getAllMatchStatus(users.get(0).getId(), Option.BOTH) = " - + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.BOTH).getMatchBoards().get(0)); - System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); - System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); - System.out.println("matchFindService.getAllMatchStatus(users.get(1).getId(), Option.BOTH) = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), Option.BOTH)); - Optional game1 = gameRepository.findByStartTime(slotTimes.get(2)); - Assertions.assertThat(game1).isPresent(); - matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(2)); - System.out.println("matchFindService.getCurrentMatch(UserDto.from(users.get(1))) = " + matchFindService.getCurrentMatch(UserDto.from(users.get(1)))); - redisTemplate.delete(PenaltyKey.USER_ADMIN + users.get(0).getIntraId()); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(2)); - System.out.println("matchFindService = " + matchFindService.getCurrentMatch(UserDto.from(users.get(0)))); - } - - @DisplayName("๋งค์นญ ๊ฒฝ๊ธฐ ์ƒ๋Œ€๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์œ ์ €์˜ ๋งค์นญ ๊ฒฝ๊ธฐ ์ทจ์†Œ") - @Test - void cancelByNotMatchedUser() { - System.out.println("this.users = " + this.users); - // ์œ ์ € 0 slot 2, 3, 0 ๋“ฑ๋ก ์œ ์ € 1 slot 2 - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, this.slotTimes.get(2)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, this.slotTimes.get(2)); - org.junit.jupiter.api.Assertions.assertThrows(SlotNotFoundException.class, () -> { - matchService.cancelMatch(UserDto.from(users.get(2)), this.slotTimes.get(2)); - }); - } -} diff --git a/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java b/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java deleted file mode 100644 index b164c000b..000000000 --- a/src/test/java/com/gg/server/domain/match/service/MatchServiceTest.java +++ /dev/null @@ -1,540 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.admin.penalty.data.PenaltyAdminRepository; -import com.gg.server.global.exception.custom.BusinessException; -import com.gg.server.utils.MatchTestUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.match.data.RedisMatchTimeRepository; -import com.gg.server.domain.match.data.RedisMatchUser; -import com.gg.server.domain.match.data.RedisMatchUserRepository; -import com.gg.server.domain.match.dto.MatchStatusDto; -import com.gg.server.domain.match.dto.MatchStatusResponseListDto; -import com.gg.server.domain.match.dto.SlotStatusDto; -import com.gg.server.domain.match.dto.SlotStatusResponseListDto; -import com.gg.server.domain.match.exception.EnrolledSlotException; -import com.gg.server.domain.match.exception.PenaltyUserSlotException; -import com.gg.server.domain.match.type.MatchKey; -import com.gg.server.domain.match.type.Option; -import com.gg.server.domain.match.type.SlotStatus; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.penalty.redis.PenaltyUserRedisRepository; -import com.gg.server.domain.penalty.redis.RedisPenaltyUser; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.rank.service.RedisUploadService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import lombok.RequiredArgsConstructor; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTest -@Transactional -@RequiredArgsConstructor -class MatchServiceTest { - @Autowired - MatchFindService matchFindService; - @Autowired - MatchService matchService; - @Autowired - RedisMatchTimeRepository redisMatchTimeRepository; - @Autowired - RedisMatchUserRepository redisMatchUserRepository; - @Autowired - RedisConnectionFactory redisConnectionFactory; - @Autowired - RedisTemplate redisTemplate; - @Autowired - MatchTestUtils matchTestSetting; - @Autowired - GameRepository gameRepository; - @Autowired - RankRedisRepository rankRedisRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - PenaltyAdminRepository penaltyRepository; - @Autowired - PenaltyUserRedisRepository penaltyUserRedisRepository; - @Autowired - TournamentRepository tournamentRepository; - @Autowired - SlotManagementRepository slotManagementRepository; - @Autowired - TierRepository tierRepository; - @Autowired - RedisUploadService redisUploadService; - @Autowired - TestDataUtils testDataUtils; - List users; - List slotTimes; - - Season testSeason; - - - @BeforeEach - void init() { - testDataUtils.createTierSystem("pingpong"); - Random random = new Random(); - Integer userCount = random.nextInt(10) + 5; - Integer pppGap = random.nextInt(100) + 50; - Season season = matchTestSetting.makeTestSeason(pppGap); - testSeason = season; - users = new ArrayList(); - for(int i = 0; i < userCount; i++) { - User user = matchTestSetting.createUser(); - users.add(user); - } - users.stream().forEach(user -> - matchTestSetting.addUsertoRankRedis(user.getId(), random.nextInt(season.getPppGap()), season.getId())); - SlotManagement slotManagement = matchTestSetting.makeTestSlotManagement(15); - slotTimes = matchTestSetting.getTestSlotTimes(slotManagement.getGameInterval()); - } - @AfterEach - void clear() { - RedisConnection connection = redisConnectionFactory.getConnection(); - connection.flushDb(); - connection.close(); - } - - @Nested - @DisplayName("๋งค์นญ ์š”์ฒญ API ํ…Œ์ŠคํŠธ") - class MatchTest { - @DisplayName("๋งค์นญ ๊ฐ€๋Šฅ ์ƒ๋Œ€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ์— ๋“ค์–ด๊ฐ") - @Test - void addMatchDifferentOption() { - System.out.println("users = " + users); - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(0)); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - Assertions.assertThat(size).isEqualTo(2L); - } - - @DisplayName("normal both ๋งค์นญ ์‹œ ๊ฒŒ์ž„ ์ƒ์„ฑ") - @Test - void makeGameWithNormalAndBoth() { - System.out.println("users = " + users); - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.BOTH, slotTimes.get(1)); - matchService.makeMatch(UserDto.from(users.get(3)), Option.NORMAL, slotTimes.get(1)); - Optional game1 = gameRepository.findByStartTime(slotTimes.get(0)); - Optional game2 = gameRepository.findByStartTime(slotTimes.get(1)); - Assertions.assertThat(game1).isPresent(); - Assertions.assertThat(game2).isPresent(); - System.out.println("normal user + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.NORMAL)); - System.out.println(); - System.out.println("normal user both + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), Option.BOTH)); - System.out.println("both user + matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), - Option.BOTH)); - System.out.println("both user normal matchService = " + matchFindService.getAllMatchStatus(UserDto.from(users.get(1)), - Option.NORMAL)); - } - - @DisplayName("Queue์— ๋งค์นญ ๊ฐ€๋Šฅํ•œ normal ์ƒ๋Œ€๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ๊ฒŒ์ž„ ์ƒ์„ฑ") - @Test - void addMatchSameNormalOption() { - matchService.makeMatch(UserDto.from(users.get(2)), Option.RANK, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(0)); - matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(0)); - Optional game = gameRepository.findByStartTime(slotTimes.get(0)); - Assertions.assertThat(game).isEmpty(); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(slotTimes.get(0)); - Assertions.assertThat(size).isEqualTo(2L); - RedisMatchUser remainedUser = (RedisMatchUser) redisTemplate.opsForList().index(MatchKey.getTime(slotTimes.get(0)), 0); - Assertions.assertThat(remainedUser.getUserId()).isEqualTo(users.get(2).getId()); - Assertions.assertThat(notiRepository.findAllByUser(users.get(1)).size()).isEqualTo(2); - Assertions.assertThat(notiRepository.findAllByUser(users.get(0)).size()).isEqualTo(1); - Assertions.assertThat(notiRepository.findAllByUser(users.get(2)).size()).isEqualTo(0); - } - - @DisplayName("๊ฒŒ์ž„ ์žฌ์ƒ์„ฑ ํ…Œ์ŠคํŠธ") - @Test - void remakeGameAfterCancelling() { - matchService.makeMatch(UserDto.from(users.get(2)), Option.RANK, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.BOTH, slotTimes.get(0)); - matchService.cancelMatch(UserDto.from(users.get(2)), slotTimes.get(0)); - Optional game = gameRepository.findByStartTime(slotTimes.get(0)); - Assertions.assertThat(game).isPresent(); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - Assertions.assertThat(size).isEqualTo(2L); - RedisMatchUser remainedUser = (RedisMatchUser) redisTemplate.opsForList().index(MatchKey.getTime(slotTimes.get(0)), 0); - Assertions.assertThat(remainedUser.getUserId()).isEqualTo(users.get(0).getId()); - Assertions.assertThat(notiRepository.findAllByUser(users.get(1)).size()).isEqualTo(1); - Assertions.assertThat(notiRepository.findAllByUser(users.get(0)).size()).isEqualTo(1); - Assertions.assertThat(notiRepository.findAllByUser(users.get(2)).size()).isEqualTo(1); - } - - @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ random option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์—†์„ ๊ฒฝ์šฐ") - @Test - void addMatchRankOptionAndPppGapBiggerThanSeasonPppGap() { - User user1 = matchTestSetting.createUser(); - matchTestSetting.addUsertoRankRedis(user1.getId(), - testSeason.getStartPpp() + testSeason.getPppGap() + 1, testSeason.getId());//pppGap์ฐจ์ด๊ฐ€ ์ถฉ๋ถ„ํžˆ ํฐ ๊ฒฝ์šฐ - matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(0)); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - Assertions.assertThat(size).isEqualTo(3L); - Optional game = gameRepository.findByStartTime(slotTimes.get(0)); - Assertions.assertThat(game.isEmpty()).isEqualTo(true); - - } - - @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ random option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ") - @Test - void addMatchRankOptionAndPppGapSamllerThanOrEqualToSeasonPppGap() { - RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager - .getHashKey(testSeason.getId()), users.get(0).getId()); - User user1 = matchTestSetting.createUser(); - matchTestSetting.addUsertoRankRedis(user1.getId(),userRank.getPpp() + testSeason.getPppGap() - , testSeason.getId());//pppGap์ฐจ์ด๊ฐ€ pppGap๋งŒํผ - matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(0)); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - // ํ˜„์žฌ ์‹œ์Šคํ…œ ์ฝ”๋“œ์—์„œ๋Š” ๋งค์นญ๋œ ์Šฌ๋กฏ์€ ์•ˆ์ง€์šฐ๊ณ  ์žˆ์Œ, ๋งค์นญ๋˜์ง€ ์•Š์€ ์Šฌ๋กฏ๋งŒ ์‚ญ์ œ์ค‘์ด๋ฏ€๋กœ 2๊ฐ€ ๋‚˜์˜ด - Assertions.assertThat(size).isEqualTo(2L); - Optional game = gameRepository.findByStartTime(slotTimes.get(0)); - Assertions.assertThat(game.isEmpty()).isEqualTo(false); - } - - @DisplayName("Queue์— user๊ฐ€ ์„ ํƒํ•œ both option์œผ๋กœ ๋งค์นญ ๊ฐ€๋Šฅํ•œ ์ƒ๋Œ€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ") - @Test - void addMatchBothOptionAndPppGapSmallerThanOrEqualToSeasonPppGap() { - RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager - .getHashKey(testSeason.getId()), users.get(0).getId()); - User user1 = matchTestSetting.createUser(); - matchTestSetting.addUsertoRankRedis(user1.getId(),userRank.getPpp() + testSeason.getPppGap() - , testSeason.getId());//pppGap์ฐจ์ด๊ฐ€ pppGap๋งŒํผ - matchService.makeMatch(UserDto.from(user1), Option.BOTH, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(0)); - Long size = redisTemplate.opsForList().size(MatchKey.getTime(slotTimes.get(0))); - // ํ˜„์žฌ ์‹œ์Šคํ…œ ์ฝ”๋“œ์—์„œ๋Š” ๋งค์นญ๋œ ์Šฌ๋กฏ์€ ์•ˆ์ง€์šฐ๊ณ  ์žˆ์Œ, ๋งค์นญ๋˜์ง€ ์•Š์€ ์Šฌ๋กฏ๋งŒ ์‚ญ์ œ์ค‘์ด๋ฏ€๋กœ 2๊ฐ€ ๋‚˜์˜ด - Assertions.assertThat(size).isEqualTo(2L); - Optional game = gameRepository.findByStartTime(slotTimes.get(0)); - Assertions.assertThat(game.isEmpty()).isEqualTo(false); - Assertions.assertThat(game.get().getMode()).isEqualTo(Mode.RANK); - } - - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„๊ณผ ๊ฒน์น  ๊ฒฝ์šฐ ๊ฒŒ์ž„ ์ƒ์„ฑ ์•ˆ๋จ") - @Test - void addMatchTournamentTime() { - // given - Tournament tournament = Tournament.builder() - .title("test tournament") - .contents("test contents") - .startTime(LocalDateTime.now().plusHours(1)) - .endTime(LocalDateTime.now().plusHours(2)) - .type(TournamentType.MASTER) - .status(TournamentStatus.BEFORE) - .build(); - tournamentRepository.save(tournament); - - // when, then - Assertions.assertThatThrownBy(() -> matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, tournament.getStartTime())) - .isInstanceOf(TournamentConflictException.class); - - } - } - - @Nested - @DisplayName("๋งค์นญ ์ทจ์†Œ API ํ…Œ์ŠคํŠธ") - class CancelMatch { - @DisplayName("๊ฒŒ์ž„ ์ƒ์„ฑ๋˜์—ˆ์„ ๋•Œ ๊ฒฝ๊ธฐ ์ทจ์†Œ") - @Test - void cancelMatchAfterMakingGameEntity() { - //normal ๊ฒŒ์ž„ ์ƒ์„ฑ - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); - //user2 ๋‹ค๋ฅธ ์Šฌ๋กฏ ๋“ฑ๋ก - //์ฒซ๋ฒˆ์งธ ์œ ์ € ๊ฒฝ๊ธฐ ์ทจ์†Œ - org.junit.jupiter.api.Assertions.assertThrows( - EnrolledSlotException.class, - () -> matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)) - ); - matchService.cancelMatch(UserDto.from(users.get(0)), slotTimes.get(3)); - Optional game = gameRepository.findByStartTime(slotTimes.get(3)); - Assertions.assertThat(game.isEmpty()).isEqualTo(true); - // ์ทจ์†Œํ•œ ์œ ์ €๋Š” ํ์— ์—†์Œ - Assertions.assertThat(redisMatchUserRepository.countMatchTime(users.get(0).getId())).isEqualTo(0L); - // ์ทจ์†Œํ•˜์ง€ ์•Š์€ ์œ ์ €๋Š” ํ์— ์œ ์ง€ - Assertions.assertThat(redisMatchUserRepository.countMatchTime(users.get(1).getId())).isEqualTo(1L); - - //์•Œ๋žŒ ํ™•์ธ - List notifications = notiRepository.findAllByUser(users.get(1)); - System.out.println("users.get(0).getIntraId() = " + users.get(0).getIntraId()); - for (Noti noti : notifications) { - System.out.println("noti.getMessage() = " + noti.getMessage()); - } - Assertions.assertThat(notifications.size()).isEqualTo(2); - Assertions.assertThat(notifications.get(0).getType()).isEqualTo(NotiType.MATCHED); - Assertions.assertThat(notifications.get(1).getType()).isEqualTo(NotiType.CANCELEDBYMAN); - - //ํŒจ๋„ํ‹ฐ ํ™•์ธ - Optional penaltyUser = penaltyUserRedisRepository.findByIntraId(users.get(0).getIntraId()); - Assertions.assertThat(penaltyUser).isPresent(); - // ํŒจ๋„ํ‹ฐ ์‹œ๊ฐ„์€ ํ•˜๋“œ ์ฝ”๋”ฉ ์‹œ ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์šฐ๋‹ˆ Static์ด๋‚˜ enum์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š”๊ฒŒ ์ข‹์„ ๋“ฏ ํ•˜๋‹ค. - Assertions.assertThat(penaltyUser.get().getPenaltyTime()).isEqualTo(30); - org.junit.jupiter.api.Assertions.assertThrows(PenaltyUserSlotException.class, () -> { - matchService.makeMatch(UserDto.from(users.get(0)), Option.BOTH, slotTimes.get(10)); - } - ); - } - - @DisplayName("๊ฒŒ์ž„ ์ƒ์„ฑ ์ „ ๊ฒฝ๊ธฐ ์ทจ์†Œ") - @Test - void cancelBeforeMakingGameEntity() { - RankRedis userRank = rankRedisRepository.findRankByUserId(RedisKeyManager - .getHashKey(testSeason.getId()), users.get(0).getId()); - User user1 = matchTestSetting.createUser(); - matchTestSetting.addUsertoRankRedis(user1.getId(),userRank.getPpp() + testSeason.getPppGap() + 100 - , testSeason.getId()); - //๋งค์นญ์ด ์ด๋ฃจ์–ด์งˆ ์ˆ˜ ์—†๋Š” ์œ ์ € 3๋ช…์„ ํ์— ๋“ฑ๋ก - matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(user1), Option.RANK, slotTimes.get(0)); - //user1์˜ ์ทจ์†Œ - matchService.cancelMatch(UserDto.from(users.get(1)), slotTimes.get(0)); - List allMatchUsers = redisMatchTimeRepository.getAllMatchUsers(slotTimes.get(0)); - Assertions.assertThat(allMatchUsers.size()).isEqualTo(2L); - - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ์ทจ์†Œ ํ…Œ์ŠคํŠธ") - void cancelMatchedTournamentGame() { - // given - LocalDateTime time = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).withNano(0); - Game game = testDataUtils.createMockMatch(users.get(0), testSeason, time, time.withMinute(15), Mode.TOURNAMENT); - // when, then - Assertions.assertThatThrownBy(()->matchService.cancelMatch(UserDto.from(users.get(0)), game.getStartTime())) - .isInstanceOf(BusinessException.class); - } - } - - @Nested - @DisplayName("ํŠน์ • ์‹œ๊ฐ„๋Œ€์˜ ๊ฒฝ๊ธฐ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ์กฐํšŒ API ํ…Œ์ŠคํŠธ") - class GetMatchTimeScope { - @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ์ƒ์„ฑํ•œ ํ›„ ๋‚ด ํ…Œ์ด๋ธ”๋กœ ์ธ์‹") - @Test - void readMyTableAfterMakingGame() { - //normal ๊ฒŒ์ž„ ์ƒ์„ฑ - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(0)); - matchService.makeMatch(UserDto.from(users.get(0)), Option.RANK, slotTimes.get(4)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.RANK, slotTimes.get(1)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(2)); - SlotStatusResponseListDto slotStatusList = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), - Option.NORMAL); - for (int i = 0; i < 3; i++) { - System.out.println("slotTimes = " + String.valueOf(i) + slotTimes.get(i)); - } - for (List dtos : slotStatusList.getMatchBoards()) { - for (SlotStatusDto dto: dtos) { - System.out.println("dto = " + dto); - if (dto.getStartTime().equals(slotTimes.get(0))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(1))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.OPEN.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(2))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MATCH.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(4))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); - } - } - } - - } - - @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ์ƒ์„ฑ ์ „ ๋‚ด ํ…Œ์ด๋ธ”๋กœ ์ธ์‹") - @Test - void readMyTableBeforeMakingGame() { - for (int i = 0; i < 3; i++) { - matchService.makeMatch(UserDto.from(users.get(0)), Option.NORMAL, slotTimes.get(i)); - } - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); - SlotStatusResponseListDto slotStatusList = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), - Option.NORMAL); - for (List dtos : slotStatusList.getMatchBoards()) { - for (SlotStatusDto dto: dtos) { - if (dto.getStartTime().equals(slotTimes.get(0))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(1))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(2))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.MYTABLE.getCode()); - } - if (dto.getStartTime().equals(slotTimes.get(3))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); - } - } - } - - } - - @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ๋“ฑ๋ก ๋˜๋ฉด ์ œ 3์žํ•œํ…Œ closed ์ฒ˜๋ฆฌ") - @Test - void getClosedStatusOfExistGame() { - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); - SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(3)), - Option.NORMAL); - for (List dtos : allMatchStatus.getMatchBoards()) { - for (SlotStatusDto dto: dtos) { - if (dto.getStartTime().equals(slotTimes.get(3))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); - } - } - } - } - - @DisplayName("์Šฌ๋กฏ ์กฐํšŒ : ๊ฒŒ์ž„ ๋“ฑ๋ก ๋˜๋ฉด ์ œ3์ž๊ฐ€ ๋‹ค๋ฅธ ๊ฒŒ์ž„ ๋“ฑ๋กํ•ด๋„ ์ œ 3์žํ•œํ…Œ closed ์ฒ˜๋ฆฌ") - @Test - void getClosedStatusOfExistGame2() { - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(3)), Option.NORMAL, slotTimes.get(4)); - matchService.makeMatch(UserDto.from(users.get(4)), Option.NORMAL, slotTimes.get(4)); - SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(3)), - Option.NORMAL); - for (List dtos : allMatchStatus.getMatchBoards()) { - for (SlotStatusDto dto: dtos) { - if (dto.getStartTime().equals(slotTimes.get(3))) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); - } - } - } - } - - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‹œ๊ฐ„์— ๋Œ€ํ•œ ์Šฌ๋กฏ ๋ธ”๋ฝ") - @Test - @Disabled - void getClosedStatusOfTournament() { - // given - Tournament tournament = Tournament.builder() - .title("test tournament") - .contents("test contents") - .startTime(LocalDateTime.now().plusHours(1)) - .endTime(LocalDateTime.now().plusHours(2)) - .type(TournamentType.MASTER) - .status(TournamentStatus.BEFORE) - .build(); - tournamentRepository.save(tournament); - tierRepository.save(new Tier("image url")); - - // TODO ํ˜„์žฌ upload redisํ•ด๋„ redis ๋ฐ์ดํ„ฐ ์—†๋‹ค๋Š” ์—๋Ÿฌ ๋ฐœ์ƒํ•จ - redisUploadService.uploadRedis(); - // when - LocalDateTime now = LocalDateTime.now(); - SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(users.get(0)), - Option.NORMAL); - - // then - for (List dtos : allMatchStatus.getMatchBoards()) { - for (SlotStatusDto dto: dtos) { - if (dto.getStartTime().isBefore(tournament.getStartTime()) || - dto.getEndTime().isAfter(tournament.getEndTime())) { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.OPEN.getCode()); - } else { - Assertions.assertThat(dto.getStatus()).isEqualTo(SlotStatus.CLOSE.getCode()); - } - } - } - } - } - - @Nested - @DisplayName("ํ˜„์žฌ ๋งค์น˜ ์ •๋ณด ์กฐํšŒ API ํ…Œ์ŠคํŠธ") - class GetCurrentMatch { - @DisplayName("current Match ์กฐํšŒ : user๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ๋งค์นญ๋˜์—ˆ์„ ๋•Œ") - @Test - void readCurrentMatchAfterMakingGameEntity() { - //๊ฒŒ์ž„์ƒ์„ฑ - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(3)); - matchService.makeMatch(UserDto.from(users.get(2)), Option.NORMAL, slotTimes.get(3)); - UserDto userDto = UserDto.from(users.get(1)); - MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(userDto); - //user์˜ current match ํ™•์ธ - List match = currentMatch.getMatch(); - Assertions.assertThat(match.size()).isEqualTo(1); - Assertions.assertThat(match.get(0).getMyTeam().get(0)).isEqualTo(users.get(1).getIntraId()); - Assertions.assertThat(match.get(0).getEnemyTeam().get(0)).isEqualTo(users.get(2).getIntraId()); - Assertions.assertThat(match.get(0).getStartTime()).isEqualTo(slotTimes.get(3)); - Assertions.assertThat(match.get(0).getIsMatched()).isEqualTo(true); - } - - @DisplayName("current Match ์กฐํšŒ : user๊ฐ€ ๋“ฑ๋กํ•œ ์Šฌ๋กฏ์ด ๋งค์นญ๋˜์ง€ ์•Š์•˜์„ ๋•Œ") - @Test - void readCurrentMatchBeforeMakingGameEntity() { - //์œ ์ € ์Šฌ๋กฏ 3๊ฐœ ๋“ฑ๋ก ์‹œ๋„ - for (int i = 0; i < 3; i++) { - System.out.println("slotTimes = " + slotTimes.get(i)); - matchService.makeMatch(UserDto.from(users.get(1)), Option.NORMAL, slotTimes.get(i)); - } - UserDto userDto = UserDto.from(users.get(1)); - MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(userDto); - List match = currentMatch.getMatch(); - //user current match ํ™•์ธ - Assertions.assertThat(match.size()).isEqualTo(3); - for (int i = 0; i < 3; i++) { - System.out.println("match = " + match.get(i).getStartTime()); - Assertions.assertThat(match.get(i).getMyTeam().size()).isEqualTo(0); - Assertions.assertThat(match.get(i).getEnemyTeam().size()).isEqualTo(0); - Assertions.assertThat(match.get(i).getStartTime()).isEqualTo(slotTimes.get(i)); - Assertions.assertThat(match.get(i).getIsMatched()).isEqualTo(false); - } - } - - @DisplayName("Guest User slot ์กฐํšŒ") - @Test - void readAllSlotsAndCurrentMatchForGuset() { - User guestUser = matchTestSetting.createGuestUser(); - MatchStatusResponseListDto currentMatch = matchFindService.getCurrentMatch(UserDto.from(guestUser)); - SlotStatusResponseListDto allMatchStatus = matchFindService.getAllMatchStatus(UserDto.from(guestUser), - Option.NORMAL); - Assertions.assertThat(currentMatch.getMatch().size()).isEqualTo(0); - System.out.println("allMatchStatus = " + allMatchStatus); - } - - } -} diff --git a/src/test/java/com/gg/server/domain/match/service/MatchTournamentTest.java b/src/test/java/com/gg/server/domain/match/service/MatchTournamentTest.java deleted file mode 100644 index bdb7b9c79..000000000 --- a/src/test/java/com/gg/server/domain/match/service/MatchTournamentTest.java +++ /dev/null @@ -1,316 +0,0 @@ -package com.gg.server.domain.match.service; - -import com.gg.server.admin.noti.dto.SendNotiAdminRequestDto; -import com.gg.server.admin.noti.service.NotiAdminService; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.exception.EnrolledSlotException; -import com.gg.server.domain.match.exception.SlotNotFoundException; -import com.gg.server.domain.match.exception.WinningTeamNotFoundException; -import com.gg.server.domain.match.type.TournamentMatchStatus; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.utils.MatchTestUtils; -import com.gg.server.utils.TestDataUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -@IntegrationTest -@SpringBootTest -@Transactional -public class MatchTournamentTest { - @Autowired - TestDataUtils testDataUtils; - @Autowired - SlotManagementRepository slotManagementRepository; - @Autowired - GameRepository gameRepository; - @Autowired - MatchTournamentService matchTournamentService; - @Autowired - MatchTestUtils matchTestUtils; - @MockBean - NotiAdminService notiAdminService; - - Tournament tournament; - List allTournamentGames; - - @BeforeEach - public void beforeEach() { - testDataUtils.createSeason(); - testDataUtils.createSlotManagement(15); - tournament = testDataUtils.createTournamentWithUser(Tournament.ALLOWED_JOINED_NUMBER, 4, "test"); - allTournamentGames = testDataUtils.createTournamentGameList(tournament, 7); - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๋ผ์šด๋“œ๋ณ„ ๊ฒฝ๊ธฐ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ") - class MatchTournament { - @Test - @DisplayName("8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ ์„ฑ๊ณต") - public void quarterTest() { - // when - matchTournamentService.matchGames(tournament, TournamentRound.QUARTER_FINAL_1); - - // then - List quarterRounds = TournamentRound.getSameRounds(TournamentRound.QUARTER_FINAL_1); - List quarterRoundGames = allTournamentGames.stream() - .filter(o -> quarterRounds.contains(o.getTournamentRound())) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - LocalDateTime startTime = tournament.getStartTime(); - int gameInterval = slotManagementRepository.findCurrent(startTime) - .orElseThrow(SlotNotFoundException::new) - .getGameInterval(); - - // 4๊ฐœ์˜ 8๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - assertThat(quarterRoundGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 2); - for (TournamentGame tournamentGame : quarterRoundGames) { - assertThat(tournamentGame.getGame()).isNotNull(); - assertThat(tournamentGame.getGame().getStatus()).isEqualTo(StatusType.BEFORE); - assertThat(tournamentGame.getGame().getStartTime()).isEqualTo(startTime); - assertThat(tournamentGame.getGame().getEndTime()).isEqualTo(startTime.plusMinutes(gameInterval)); - startTime = startTime.plusMinutes((long) gameInterval); - } - verify(notiAdminService, times(8)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - - @Test - @DisplayName("4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ ์„ฑ๊ณต") - public void semiTest() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ - List tournamentGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(tournamentGames, List.of(2, 0)); - - // when - matchTournamentService.matchGames(tournament, TournamentRound.SEMI_FINAL_1); - - // then - List semiRounds = TournamentRound.getSameRounds(TournamentRound.SEMI_FINAL_1); - List semiRoundGames = allTournamentGames.stream() - .filter(o -> semiRounds.contains(o.getTournamentRound())) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - // 2๊ฐœ์˜ 4๊ฐ• ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - assertThat(semiRoundGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 4); - for (TournamentGame tournamentGame : semiRoundGames) { - assertThat(tournamentGame.getGame()).isNotNull(); - assertThat(tournamentGame.getGame().getStatus()).isEqualTo(StatusType.BEFORE); - } - // 8๊ฐ•์—์„œ ์ด๊ธด ์œ ์ €๋ผ๋ฆฌ 4๊ฐ•์— ๋งค์นญ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - List quarterRounds = TournamentRound.getSameRounds(TournamentRound.QUARTER_FINAL_1); - List quarterRoundGames = allTournamentGames.stream() - .filter(o -> quarterRounds.contains(o.getTournamentRound())) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - List semiTeams = new ArrayList<>(); - List quarterWinningTeams = new ArrayList<>(); - for(TournamentGame semiRoundGame : semiRoundGames) { - semiTeams.add(semiRoundGame.getGame().getTeams().get(0).getTeamUsers().get(0).getUser()); - semiTeams.add(semiRoundGame.getGame().getTeams().get(1).getTeamUsers().get(0).getUser()); - } - for (TournamentGame quarterRoundGame : quarterRoundGames) { - Team winningTeam = matchTestUtils.getWinningTeam(quarterRoundGame.getGame()); - quarterWinningTeams.add(winningTeam.getTeamUsers().get(0).getUser()); - } - assertThat(semiTeams).contains(quarterWinningTeams.get(0)); - assertThat(semiTeams).contains(quarterWinningTeams.get(1)); - verify(notiAdminService, times(4)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - - @Test - @DisplayName("๊ฒฐ์Šน ๊ฒฝ๊ธฐ ๋งค์นญ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต") - public void finalTest() { - // given - // 8๊ฐ• & 4๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ ์ž…๋ ฅ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); - - // when - matchTournamentService.matchGames(tournament, TournamentRound.THE_FINAL); - - // then - // 1๊ฐœ์˜ ๊ฒฐ์Šน ๊ฒฝ๊ธฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - TournamentGame finalRoundGame = allTournamentGames.stream() - .filter(o -> TournamentRound.THE_FINAL.equals(o.getTournamentRound())).findAny().orElse(null); - assertThat(finalRoundGame.getGame()).isNotNull(); - verify(notiAdminService, times(2)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - - @Test - @DisplayName("์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ์‹คํŒจ") - public void failAlreadyMatched() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + 4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); - - // when, then - assertThatThrownBy(() -> matchTournamentService.matchGames(tournament, TournamentRound.SEMI_FINAL_1)) - .isInstanceOf(EnrolledSlotException.class); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ ํ™•์ธ ํ…Œ์ŠคํŠธ") - class CheckTournament { - @Test - @DisplayName("IMPOSSIBLE : ๊ฒฐ์Šน ๊ฒฝ๊ธฐ ์ ์ˆ˜ ์ž…๋ ฅ ํ›„ ํ† ๋„ˆ๋จผํŠธ END ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต & ์ข…๋ฃŒ ์‹œ๊ฐ„ ๊ฐฑ์‹ ") - public void finalEndTest() { - // given - // 8๊ฐ• & 4๊ฐ• & ๊ฒฐ์Šน ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ ์ž…๋ ฅ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); - Game finalGame = matchTestUtils.matchTournamentGames(tournament, TournamentRound.THE_FINAL).get(0).getGame(); - matchTestUtils.updateTournamentGameResult(finalGame, List.of(2, 0)); - - // when - TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(finalGame); - - // then - // ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ๊ฐ€ END๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ - // winner๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ - assertThat(TournamentMatchStatus.IMPOSSIBLE).isEqualTo(tournamentMatchStatus); - assertThat(tournament.getStatus()).isEqualTo(TournamentStatus.END); - assertThat(tournament.getWinner()).isNotNull(); - assertThat(tournament.getEndTime()).isEqualTo(finalGame.getEndTime()); - } - - @Test - @DisplayName("IMPOSSBLE : ์ง„ํ–‰์ค‘์ธ ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ๊ฒฝ๊ธฐ๊ฐ€ ์ ์ˆ˜์ž…๋ ฅ ์™„๋ฃŒ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ") - public void impossibleTest() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - - // when - matchTestUtils.updateTournamentGameResult(quarterGames.get(0).getGame(), List.of(2, 0)); - TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(quarterGames.get(0).getGame()); - - // then - assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.IMPOSSIBLE); - } - - @Test - @DisplayName("ALREADY_MATCHED : ์ด๋ฏธ ๋งค์นญ๋œ ๊ฒŒ์ž„์ด ์กด์žฌํ•  ๊ฒฝ์šฐ") - public void alreadyMatchedTest() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ + 4๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - matchTestUtils.updateTournamentGamesResult(semiGames, List.of(2, 0)); - - // when - TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(quarterGames.get(0).getGame()); - - // then - assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.ALREADY_MATCHED); - } - - @Test - @DisplayName("POSSIBLE : ํ† ๋„ˆ๋จผํŠธ ๋งค์นญ ๊ฐ€๋Šฅ ์ƒํƒœ") - public void possibleTest() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - - // when - TournamentMatchStatus tournamentMatchStatus = matchTournamentService.checkTournamentGame(quarterGames.get(0).getGame()); - - // then - assertThat(tournamentMatchStatus).isEqualTo(TournamentMatchStatus.POSSIBLE); - } - - } - - @Nested - @DisplayName("์œ„๋„ˆ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋‹ค์Œ ๊ฒฝ๊ธฐ ํŒ€ ๋ณ€๊ฒฝ ํ…Œ์ŠคํŠธ") - class ChangeTeam { - @Test - @DisplayName("8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ 4๊ฐ• ๊ฒฝ๊ธฐ๋กœ ํŒ€ ๋ณ€๊ฒฝ ์„ฑ๊ณต") - public void quarterToSemiTest() { - // given - // 8๊ฐ• ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ + 4๊ฐ• ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - matchTestUtils.updateTournamentGamesResult(quarterGames, List.of(2, 0)); - List semiGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.SEMI_FINAL_1); - - Game game = quarterGames.get(0).getGame(); // QAUARTER_FINAL_1l Game - TournamentRound nextRound = quarterGames.get(0).getTournamentRound().getNextRound(); // SEMI_FINAL_1 - Game nextMatchedGame = semiGames.stream() // SEMI_FINAL_1 Game - .filter(o -> nextRound.equals(o.getTournamentRound())) - .findAny() - .orElseThrow(() -> new IllegalArgumentException("๋‹ค์Œ ๊ฒฝ๊ธฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")).getGame(); - - // when - // ๊ธฐ์กด 8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ ์ง„ ํŒ€์ด ์ ์ˆ˜ ์ˆ˜์ •์œผ๋กœ ์ด๊ธด ํŒ€์œผ๋กœ ๋ณ€๊ฒฝ - Team losingTeam = game.getTeams().stream().filter(Team::getWin).findAny().orElseThrow(() -> new IllegalArgumentException("์Šน๋ฆฌํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); - Team winningTeam = game.getTeams().stream().filter(o -> !o.getWin()).findAny().orElseThrow(() -> new IllegalArgumentException("ํŒจ๋ฐฐํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); - losingTeam.updateScore(0, false); - winningTeam.updateScore(2, true); - matchTournamentService.updateMatchedGameUser(game, nextMatchedGame); - - // then - // ์ ์ˆ˜ ์ˆ˜์ •์œผ๋กœ 8๊ฐ• ๊ฒฝ๊ธฐ์—์„œ ์ด๊ธด ํŒ€์ด ๋‹ค์Œ ๊ฒฝ๊ธฐ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - List nextGameUsers = new ArrayList<>(); - nextGameUsers.add(nextMatchedGame.getTeams().get(0).getTeamUsers().get(0).getUser()); - nextGameUsers.add(nextMatchedGame.getTeams().get(1).getTeamUsers().get(0).getUser()); - - assertThat(nextGameUsers.contains(winningTeam.getTeamUsers().get(0).getUser())).isTrue(); - assertThat(nextGameUsers.contains(losingTeam.getTeamUsers().get(0).getUser())).isFalse(); - verify(notiAdminService, times(2)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - - @Test - @DisplayName("์šฐ์ŠนํŒ€์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์‹คํŒจ") - public void failUpdateWinner() { - // given - // 8๊ฐ• ๋งค์นญ - List quarterGames = matchTestUtils.matchTournamentGames(tournament, TournamentRound.QUARTER_FINAL_1); - TournamentGame targetTournamentGame = quarterGames.get(0); - TournamentRound nextRound = targetTournamentGame.getTournamentRound().getNextRound(); - Game nextMatchedGame = allTournamentGames.stream() - .filter(o -> nextRound.equals(o.getTournamentRound())) - .findAny() - .orElseThrow(() -> new IllegalArgumentException("๋‹ค์Œ ๊ฒฝ๊ธฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")).getGame(); - - // when, then - assertThatThrownBy(() -> matchTournamentService.updateMatchedGameUser(targetTournamentGame.getGame(), nextMatchedGame)) - .isInstanceOf(WinningTeamNotFoundException.class); - } - } -} diff --git a/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java b/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java deleted file mode 100644 index 47aecc9db..000000000 --- a/src/test/java/com/gg/server/domain/megaphone/controller/MegaphoneControllerTest.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.gg.server.domain.megaphone.controller; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.type.ItemType; -import com.gg.server.domain.megaphone.data.Megaphone; -import com.gg.server.domain.megaphone.data.MegaphoneRepository; -import com.gg.server.domain.megaphone.dto.MegaphoneUseRequestDto; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.data.ReceiptRepository; -import com.gg.server.domain.receipt.type.ItemStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.ItemTestUtils; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalTime; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.AssertionsForClassTypes; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -class MegaphoneControllerTest { - @Autowired - TestDataUtils testDataUtils; - - @Autowired - private MockMvc mockMvc; - - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - MegaphoneRepository megaphoneRepository; - - @Autowired - ReceiptRepository receiptRepository; - - @Autowired - ItemTestUtils itemTestUtils; - - @Test - @Transactional - @DisplayName("[Post] /pingpong/megaphones") - void useMegaphoneTest() throws Exception { - // ํ•ด๋‹น ํ…Œ์ŠคํŠธ๋Š” ์‹œ์Šคํ…œ์ƒ 23:55 ~ 00:05 ์‚ฌ์ด์— ํ…Œ์ŠคํŠธ ๋ถˆ๊ฐ€๋Šฅ - if (LocalTime.now().isAfter(LocalTime.of(23, 54)) - || LocalTime.now().isBefore(LocalTime.of(0, 6))) { - return; - } - String intraId = "intra"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String accessToken = tokenProvider.createToken(newUser.getId()); - // db์— ์ €์žฅํ•ด๋‘๊ณ  ํ…Œ์ŠคํŠธ - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", - "default", 40, 50, ItemType.MEGAPHONE); - Item item = itemTestUtils.createItem(newUser, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); - MegaphoneUseRequestDto megaphoneUseRequestDto = new MegaphoneUseRequestDto(receipt.getId(), "test"); - String content = objectMapper.writeValueAsString(megaphoneUseRequestDto); - String url = "/pingpong/megaphones"; - - mockMvc.perform(post(url) - .content(content) - .contentType(MediaType.APPLICATION_JSON) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - Megaphone result = megaphoneRepository.findFirstByOrderByIdDesc(); - assertThat(result.getContent()).isEqualTo(megaphoneUseRequestDto.getContent()); - } - - @Test - @Transactional - @DisplayName("DELETE /pingpong/megaphones/{megaphoneId}") - public void deleteMegaphoneTest() throws Exception { - //given - String intraId = "intra2"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String accessToken = tokenProvider.createToken(newUser.getId()); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", - "default", 40, 50, ItemType.MEGAPHONE); - Item item = itemTestUtils.createItem(newUser, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); - Receipt receipt2 = itemTestUtils.purchaseItem(newUser, newUser, item); - Megaphone megaphone = itemTestUtils.createMegaPhone(newUser, receipt, "test"); - Megaphone megaphone2 = itemTestUtils.createMegaPhone(newUser, receipt2, "test"); - String url = "/pingpong/megaphones/" + megaphone2.getId(); - - //when - mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse(); - - //then - AssertionsForClassTypes.assertThat(receipt2.getStatus()).isEqualTo(ItemStatus.DELETED); - } - - @Test - @Transactional - @DisplayName("[GET] /pingpong/megaphones/receipt/{receiptId}") - void getMegaphoneDetailTest() throws Exception { - String intraId = "intra"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, - SnsType.BOTH, RoleType.ADMIN); - String accessToken = tokenProvider.createToken(newUser.getId()); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("ํ™•์„ฑ๊ธฐ", "default", - "default", 40, 50, ItemType.MEGAPHONE); - Item item = itemTestUtils.createItem(newUser, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); - Megaphone megaphone = itemTestUtils.createMegaPhone(newUser, receipt, "test"); - String url = "/pingpong/megaphones/receipt/" + receipt.getId(); - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - System.out.println(contentAsString); - } - - @Test - @Transactional - @DisplayName("[GET] /pingpong/megaphones") - void getMegaphoneTodayListTest() throws Exception { - String accessToken = testDataUtils.getLoginAccessToken(); - String url = "/pingpong/megaphones"; - mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java b/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java deleted file mode 100644 index e7c77ba95..000000000 --- a/src/test/java/com/gg/server/domain/noti/controller/NotiControllerTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.gg.server.domain.noti.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.dto.NotiListResponseDto; -import com.gg.server.domain.noti.service.NotiService; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; - -import javax.transaction.Transactional; - -import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -class NotiControllerTest { - - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - UserRepository userRepository; - @Autowired - NotiRepository notiRepository; - @Autowired - private NotiService notiService; - @Autowired - private MockMvc mockMvc; - @Autowired - private ObjectMapper objectMapper; - - @Test - @DisplayName("GET /pingpong/notifications") - @Transactional - public void NotiFindByUserTest() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications"; - - UserDto userDto = UserDto.from(userRepository.getById(userId)); - NotiListResponseDto expectedResponse = new NotiListResponseDto(notiService.findNotiByUser(userDto)); - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - NotiListResponseDto actureResponse= objectMapper.readValue(contentAsString, NotiListResponseDto.class); - - //then - assertThat(actureResponse).isEqualTo(expectedResponse); - } - - @Test - @DisplayName("PUT /pingpong/notifications/check") - @Transactional - public void checkNotiByUserTest() throws Exception{ - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications/check"; - User user = userRepository.findById(userId).get(); - - notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); - notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); - notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); - //when - String contentAsString = mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - List notiList = notiRepository.findByUser(user); - for (Noti noti : notiList) { - assertThat(noti.getIsChecked()).isTrue(); - } - } - - @Test - @DisplayName("DELETE /notifications") - @Transactional - public void notiRemoveAll() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/notifications"; - User user = userRepository.findById(userId).get(); - - notiRepository.save(new Noti(user, NotiType.ANNOUNCE, "announce", false)); - notiRepository.save(new Noti(user, NotiType.MATCHED, "matched", false)); - notiRepository.save(new Noti(user, NotiType.IMMINENT, "imminent", true)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYMAN, "canceledbyman", false)); - notiRepository.save(new Noti(user, NotiType.CANCELEDBYTIME, "canceledbytime", false)); - - //when - String contentAsString = mockMvc.perform(delete(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - List notiList = notiRepository.findByUser(user); - assertThat(notiList.size()).isEqualTo(0); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java b/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java deleted file mode 100644 index a4fe14141..000000000 --- a/src/test/java/com/gg/server/domain/noti/service/NotiServiceTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.gg.server.domain.noti.service; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.transaction.Transactional; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; - -@RequiredArgsConstructor -@IntegrationTest -@Slf4j -class NotiServiceTest { - - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - NotiService notiService; - @Autowired - NotiRepository notiRepository; - @Autowired - UserRepository userRepository; - - @Test - @DisplayName("NotiService ์œ ์ €๋งค์นญ์•Œ๋ฆผ ์ „์†ก ํ…Œ์ŠคํŠธ") - @Transactional - public void ์œ ์ €๋งค์นญ์•Œ๋ฆผ์ „์†กํ…Œ์ŠคํŠธ() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - UserDto userDto = UserDto.from(user); - LocalDateTime now = LocalDateTime.now(); - String expectedMatchedNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์„ฑ์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; - String expectedMatchCancelNotiMessage = now.format(DateTimeFormatter.ofPattern("HH:mm")) + "์— ์‹ ์ฒญํ•œ ๋งค์นญ์ด ์ƒ๋Œ€์— ์˜ํ•ด ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."; - - //when - notiService.createMatched(user, now); - notiService.createMatchCancel(user, now); - List actureNotiList = notiRepository.findAllByUser(user); - - //then - Assertions.assertThat(actureNotiList.size()).isEqualTo(2); - for (Noti noti: actureNotiList) { - if (noti.getType() == NotiType.MATCHED) { - Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchedNotiMessage); - log.info("Matched Message : " + noti.getMessage()); - } - else if (noti.getType() == NotiType.CANCELEDBYMAN) { - Assertions.assertThat(noti.getMessage()).isEqualTo(expectedMatchCancelNotiMessage); - log.info("MatchCancel Message : " + noti.getMessage()); - } - Assertions.assertThat(noti.getIsChecked()).isFalse(); - } - } -} diff --git a/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java b/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java deleted file mode 100644 index 82bb54931..000000000 --- a/src/test/java/com/gg/server/domain/rank/controller/RankControllerTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.gg.server.domain.rank.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.service.RedisUploadService; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import org.apache.http.HttpHeaders; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Comparator; -import java.util.List; - - -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - - -@IntegrationTest -@Transactional -@AutoConfigureMockMvc -class RankControllerTest { - - @Autowired - TestDataUtils testDataUtils; - - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - - @Autowired - AuthTokenProvider tokenProvider; - - @Autowired - SeasonRepository seasonRepository; - - @Autowired - RankRedisRepository redisRepository; - - @Autowired - RedisUploadService redisUploadService; - - @BeforeEach - public void flushRedis(){ - redisRepository.deleteAll(); - testDataUtils.createTierSystem("pingpong"); - } - - @AfterEach - public void flushRedisAfter(){ - redisRepository.deleteAll(); - } - - @Test - @DisplayName("/exp") - void getExpRankPage() throws Exception { - - // given - Season season = testDataUtils.createSeason(); - int myTotalExp = 1000; - User myUser = testDataUtils.createNewUser(myTotalExp); - testDataUtils.createUserRank(myUser, "1", season); - - int otherTotalExp = 2000; - User user1 = testDataUtils.createNewUser(otherTotalExp); - testDataUtils.createUserRank(user1, "2", season); - int otherTotalExp2 = 3000; - User user2 = testDataUtils.createNewUser(otherTotalExp2); - testDataUtils.createUserRank(user2, "3", season); - int otherTotalExp3 = 4000; - User user3 = testDataUtils.createNewUser(otherTotalExp3); - testDataUtils.createUserRank(user3, "4", season); - - int page = 1; - int size = 3; - String url = "/pingpong/exp?page=" + page + "&size=" + size; - String accessToken = tokenProvider.createToken(myUser.getId()); - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - ExpRankPageResponseDto response = objectMapper.readValue(contentAsString, ExpRankPageResponseDto.class); - - //then - Assertions.assertThat(response.getMyRank()).isEqualTo(4); - Assertions.assertThat(response.getCurrentPage()).isEqualTo(page); - Assertions.assertThat(response.getTotalPage()).isEqualTo(2); - Assertions.assertThat(response.getRankList().size()).isEqualTo(3); - } - - @Test - @DisplayName("/pingpong/ranks/{gameType}") - public void getRankPage () throws Exception - { - //given - Season season = testDataUtils.createSeason(); - User myUser = testDataUtils.createNewUser(); - testDataUtils.createUserRank(myUser, "1", season, 1000); - - User user2 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user2, "2", season, 1500); - - User user3 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user3, "3", season, 2000); - - User user4 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user4, "4", season, 2500); - - User user5 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user5, "5", season, 3000); - - User user6 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user6, "6", season, 3500); - - User user7 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user7, "7", season, 4000); - - User user8 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user8, "8", season, 4500); - - User user9 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user9, "9", season, 5000); - - User user10 = testDataUtils.createNewUser(); - testDataUtils.createUserRank(user10, "10", season, 5500); - - String accessToken = tokenProvider.createToken(myUser.getId()); - - int page = 4; - int size = 3; - String url = "/pingpong/ranks/single?page=" + page + "&size=" + size; - - //when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - RankPageResponseDto resp = objectMapper.readValue(contentAsString, RankPageResponseDto.class); - - //then - List rankList = resp.getRankList(); - Assertions.assertThat(resp.getCurrentPage()).isEqualTo(4); - Assertions.assertThat(resp.getTotalPage()).isEqualTo(4); - Assertions.assertThat(resp.getMyRank()).isEqualTo(10); - Assertions.assertThat(rankList.size()).isEqualTo(1); - Assertions.assertThat(rankList).isSortedAccordingTo(Comparator.comparing(RankDto::getPpp).reversed()); - } - - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/rank/controller/RankV2ControllerTest.java b/src/test/java/com/gg/server/domain/rank/controller/RankV2ControllerTest.java deleted file mode 100644 index d961dfa1e..000000000 --- a/src/test/java/com/gg/server/domain/rank/controller/RankV2ControllerTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.gg.server.domain.rank.controller; - -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.service.RankService; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.global.config.WebConfig; -import com.gg.server.global.security.config.SecurityConfig; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.global.security.jwt.utils.TokenAuthenticationFilter; -import com.gg.server.global.utils.querytracker.LoggingInterceptor; -import java.util.ArrayList; -import java.util.Optional; -import org.junit.jupiter.api.Test; -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.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; -import org.springframework.data.domain.PageRequest; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import static org.mockito.BDDMockito.*; - -@WebMvcTest(value = RankV2Controller.class, - excludeFilters = { - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = WebConfig.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TokenAuthenticationFilter.class), - @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = LoggingInterceptor.class) - } -) -@ExtendWith(MockitoExtension.class) -class RankV2ControllerTest { - - @Autowired - private MockMvc mockMvc; - @MockBean - private RankService rankService; - @MockBean - private UserRepository userRepository; - @MockBean - private AuthTokenProvider authTokenProvider; - - @Test - @WithMockUser(username = "TestUser") - void getExpRankPage() throws Exception { - given(userRepository.findById(0L)) - .willReturn(Optional.of(User.builder().intraId("TestUser").build())); - given(rankService.getExpRankPage(PageRequest.of(1, 10), - UserDto - .builder() - .intraId("TestUser") - .id(1L) - .build()) - ).willReturn(new ExpRankPageResponseDto( - -1, - 1, - 1, - new ArrayList<>() - )); - mockMvc.perform(get("/pingpong/v2/exp") - .queryParam("size", "10") - .queryParam("page", "1")) - .andExpect(status().isOk()); - } - - @Test - @WithMockUser(username = "TestUser") - void getRankPage() throws Exception{ - given(userRepository.findById(0L)) - .willReturn(Optional.of(User.builder().intraId("TestUser").build())); - given(rankService.getRankPageV2(PageRequest.of(1, 10), - UserDto - .builder() - .intraId("TestUser") - .id(1L) - .build(), 1L) - ).willReturn(new RankPageResponseDto(-1, 1, 1, new ArrayList<>())); - mockMvc.perform(get("/pingpong/v2/ranks/single") - .queryParam("size", "10") - .queryParam("page", "1") - .queryParam("season", "1")) - .andExpect(status().isOk()); - - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java b/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java deleted file mode 100644 index e360f693c..000000000 --- a/src/test/java/com/gg/server/domain/rank/redis/RankRedisRepositoryTest.java +++ /dev/null @@ -1,275 +0,0 @@ -package com.gg.server.domain.rank.redis; - -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.rank.exception.RedisDataNotFoundException; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.List; - -@IntegrationTest -class RankRedisRepositoryTest { - - - @Autowired - RankRedisRepository redisRepository; - - static String zSetKey = "test:ZSet"; - static String hashKey = "test:hash"; - - @AfterEach - void deleteAll(){ - redisRepository.deleteZSetKey(zSetKey); - redisRepository.deleteHashKey(hashKey); - } - - @Test - void addToZSet() { - //given - Long userId = 1L; - int ppp = 100; - - //when - redisRepository.addToZSet(zSetKey, userId, ppp); - - //then - Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); - Assertions.assertThat(scoreInZSet).isEqualTo(ppp); - } - - @Test - void incrementScoreInZSet() { - //given - Long userId = 1L; - int ppp = 100; - int incrementPpp = 50; - redisRepository.addToZSet(zSetKey, userId, ppp); - - //when - redisRepository.incrementScoreInZSet(zSetKey, userId, incrementPpp); - - //then - Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); - Assertions.assertThat(scoreInZSet).isEqualTo(ppp + incrementPpp); - } - - @Test - void decrementScoreInZSet() { - //given - Long userId = 1L; - int ppp = 100; - int decrementPpp = 50; - redisRepository.addToZSet(zSetKey, userId, ppp); - - //when - redisRepository.decrementScoreInZSet(zSetKey, userId, decrementPpp); - - //then - Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); - Assertions.assertThat(scoreInZSet).isEqualTo(ppp - decrementPpp); - } - - - @Test - void add(){ - Long userId = 1L; - Long userId2 = 2L; - Long userId3 = 3L; - int ppp = 100; - int ppp2 = 200; - int ppp3 = 300; - redisRepository.addToZSet(zSetKey, userId, ppp); - redisRepository.addToZSet(zSetKey, userId2, ppp2); - redisRepository.addToZSet(zSetKey, userId3, ppp3); - } - - @Test - void getRankInZSet() { -// given - Long userId = 1L; - Long userId2 = 2L; - Long userId3 = 3L; - int ppp = 100; - int ppp2 = 200; - int ppp3 = 300; - redisRepository.addToZSet(zSetKey, userId, ppp); - redisRepository.addToZSet(zSetKey, userId2, ppp2); - redisRepository.addToZSet(zSetKey, userId3, ppp3); - - //when - Long rankInZSet = redisRepository.getRankInZSet(zSetKey, userId); - - //then - Assertions.assertThat(rankInZSet).isEqualTo(2); - } - - @Test - void getScoreInZSet() { - //given - Long userId = 1L; - int ppp = 100; - redisRepository.addToZSet(zSetKey, userId, ppp); - - //when - Long scoreInZSet = redisRepository.getScoreInZSet(zSetKey, userId); - - //then - Assertions.assertThat(scoreInZSet).isEqualTo(ppp); - } - - @Test - public void getUserIdsByRange () throws Exception { - //given - Long userId = 1L; - Long userId2 = 2L; - Long userId3 = 3L; - int ppp = 100; - int ppp2 = 200; - int ppp3 = 300; - redisRepository.addToZSet(zSetKey, userId, ppp); - redisRepository.addToZSet(zSetKey, userId2, ppp2); - redisRepository.addToZSet(zSetKey, userId3, ppp3); - - //when - List userIdsSorted = redisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 1); - - //then - Assertions.assertThat(userIdsSorted).containsExactly(userId3, userId2); - Assertions.assertThat(userIdsSorted.get(0)).isEqualTo(userId3); - Assertions.assertThat(userIdsSorted.get(1)).isEqualTo(userId2); - } - - @Test - @DisplayName("ZSet์—์„œ ์œ ์ € ์‚ญ์ œ") - public void deleteZSetTest () throws Exception - { - //given - Long userId = 1L; - int ppp = 100; - redisRepository.addToZSet(zSetKey, userId, ppp); - - //when - redisRepository.deleteFromZSet(zSetKey, userId); - - //then - Assertions.assertThatThrownBy(()->{ - redisRepository.getRankInZSet(zSetKey, userId); - }).isInstanceOf(RedisDataNotFoundException.class); - } - - - @Test - @DisplayName("Redis์— ๋žญํ‚น ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€, ๊ฒ€์ƒ‰ํ•œ๋‹ค.") - public void rankCreateSearch () throws Exception - { - //given - Long userId = 1L; - int ppp = 100; - int win = 3; - int lose = 4; - String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-test-image.s3.ap-northeast-2.amazonaws.com/tier/hand.svg", "#000000"); - - //when - redisRepository.addRankData(hashKey, userId, ranking); - RankRedis findRanking = redisRepository.findRankByUserId(hashKey, userId); - - //then - Assertions.assertThat(findRanking.getUserId()).isEqualTo(userId); - Assertions.assertThat(findRanking.getPpp()).isEqualTo(ppp); - Assertions.assertThat(findRanking.getWins()).isEqualTo(win); - Assertions.assertThat(findRanking.getLosses()).isEqualTo(lose); - Assertions.assertThat(findRanking.getStatusMessage()).isEqualTo(statusMessage); - } - - @Test - @DisplayName("user rank์ •๋ณด ์—…๋ฐ์ดํŠธ") - public void updateRank () throws Exception - { - //given - Long userId = 1L; - int ppp = 100; - int win = 3; - int lose = 4; - String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - redisRepository.addRankData(hashKey, userId, ranking); - - //when - int newPpp = 200; - int newWin = 4; - int newLose = 5; - String newStatusMessage = "newStatusMessage"; - RankRedis newRanking = new RankRedis(userId, "aa", newPpp, newWin, newLose, newStatusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - - redisRepository.updateRankData(hashKey, userId, newRanking); - //then - RankRedis findRanking = redisRepository.findRankByUserId(hashKey, userId); - Assertions.assertThat(findRanking.getUserId()).isEqualTo(userId); - Assertions.assertThat(findRanking.getPpp()).isEqualTo(newPpp); - Assertions.assertThat(findRanking.getWins()).isEqualTo(newWin); - Assertions.assertThat(findRanking.getLosses()).isEqualTo(newLose); - Assertions.assertThat(findRanking.getStatusMessage()).isEqualTo(newStatusMessage); - } - - @Test - @DisplayName("์œ ์ € ๋žญํฌ๋ฅผ ์‚ญ์ œํ•œ๋‹ค") - public void deleteUserRank () throws Exception - { - //given - Long userId = 3L; - int ppp = 100; - int win = 3; - int lose = 4; - String statusMessage = "statusMessage"; - RankRedis ranking = new RankRedis(userId, "aa", ppp, win, lose, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - redisRepository.addRankData(hashKey, userId, ranking); - - //when - redisRepository.deleteRankData(hashKey, userId); - - //then - Assertions.assertThatThrownBy(() -> { - redisRepository.findRankByUserId(hashKey, userId); - }).isInstanceOf(RedisDataNotFoundException.class); - } - - @Test - void findRanksByUserIds() { - //given - Long userId = 1L; - Long userId2 = 2L; - Long userId3 = 3L; - Long userId4 = 4L; - int ppp = 100; - int ppp2 = 200; - int ppp3 = 300; - int ppp4 = 400; - - RankRedis rank1 = new RankRedis(userId, "aa", ppp, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - RankRedis rank2 = new RankRedis(userId2,"aa", ppp2, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - RankRedis rank3 = new RankRedis(userId3, "aa", ppp3, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - RankRedis rank4 = new RankRedis(userId4, "aa", ppp4, 0, 0, "statusMessage", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - redisRepository.addRankData(hashKey, userId, rank1); - redisRepository.addRankData(hashKey, userId2, rank2); - redisRepository.addRankData(hashKey, userId3, rank3); - redisRepository.addRankData(hashKey, userId4, rank4); - redisRepository.addToZSet(zSetKey, userId, ppp); - redisRepository.addToZSet(zSetKey, userId2, ppp2); - redisRepository.addToZSet(zSetKey, userId3, ppp3); - redisRepository.addToZSet(zSetKey, userId4, ppp4); - - //when - List sortedUserIds = redisRepository.getUserIdsByRangeFromZSet(zSetKey, 0, 3); - List ranks = redisRepository.findRanksByUserIds(hashKey, sortedUserIds); - - //then -> ๋žญํฌ ์ˆœ์„œ๋„ ์•Œ๋งž๊ฒŒ ๋ฐ˜ํ™˜๋˜๋Š”์ง€ ํ™•์ธ - Assertions.assertThat(ranks) - .usingElementComparatorIgnoringFields("userId") - .containsExactly(rank4, rank3, rank2, rank1); - } - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/rank/redis/RedisTestService.java b/src/test/java/com/gg/server/domain/rank/redis/RedisTestService.java deleted file mode 100644 index c767b9e43..000000000 --- a/src/test/java/com/gg/server/domain/rank/redis/RedisTestService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.gg.server.domain.rank.redis; - -import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@Transactional -@RequiredArgsConstructor -public class RedisTestService { - private final RedisTemplate redisTemplate; - - - public void addStringWithError(String key, Object value) { - redisTemplate.opsForValue().set(key, value); - throw new RuntimeException(); - } - - public void addString(String key, Object value) { - redisTemplate.opsForValue().set(key, value); - } - - public Object getFromString(String key) { - return redisTemplate.opsForValue().get(key); - } -} diff --git a/src/test/java/com/gg/server/domain/rank/redis/RedisTransactionTest.java b/src/test/java/com/gg/server/domain/rank/redis/RedisTransactionTest.java deleted file mode 100644 index 0dee1cbfc..000000000 --- a/src/test/java/com/gg/server/domain/rank/redis/RedisTransactionTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gg.server.domain.rank.redis; - - -import com.gg.server.utils.annotation.IntegrationTestWithRedisTransaction; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.transaction.annotation.Transactional; - -@IntegrationTestWithRedisTransaction -public class RedisTransactionTest { - - @Autowired - RedisTestService redisTestService; - - @Autowired - RedisTemplate redisTemplate; - - @Test - @DisplayName("transaction์•ˆ์—์„œ exception์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ํ•ด๋‹น transaction์ด discord๋˜๋Š”์ง€ ํ™•์ธ") - public void rollbackTest () throws Exception - { - String key = "hello"; - - Assertions.assertThatThrownBy(() ->{ - redisTestService.addStringWithError(key, "aaa"); - }).isInstanceOf(RuntimeException.class); - - Object result = redisTemplate.opsForValue().get(key); - Assertions.assertThat(result).isNull(); - } - - @Test - @DisplayName("transaction์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ exec๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š”์ง€ ํ…Œ์ŠคํŠธ") - public void commitTest () throws Exception - { - String key = "hello1"; - String value = "aaa"; - - redisTestService.addString(key, value); - - Object result = redisTemplate.opsForValue().get(key); - Assertions.assertThat(result).isNotNull(); - Assertions.assertThat(result.toString()).isEqualTo(value); - } - - @Test - @DisplayName("transaction์•ˆ์—์„œ ์ƒˆ๋กœ ์ง‘์–ด๋„ฃ์€ key์— ๋Œ€ํ•ด์„œ ์กฐํšŒ์‹œ null์กฐํšŒ test") - @Transactional - public void nullTest () throws Exception - { - String key = "test"; - String value = "value"; - - redisTestService.addString(key, value); - - Object result = redisTestService.getFromString(key); - Assertions.assertThat(result).isNull(); - } - - @Test - @DisplayName("transaction์•ˆ์—์„œ ๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ key์— ๋Œ€ํ•ด์„œ ์กฐํšŒ์‹œ not null test") - public void nonNullTest () throws Exception - { - String key = "test"; - String value = "value"; - - redisTestService.addString(key, value); - - Object result = redisTestService.getFromString(key); - Assertions.assertThat(result).isNotNull(); - Assertions.assertThat(result.toString()).isEqualTo(value); - } - -} - diff --git a/src/test/java/com/gg/server/domain/rank/service/RankServiceTest.java b/src/test/java/com/gg/server/domain/rank/service/RankServiceTest.java deleted file mode 100644 index 400bc8e2a..000000000 --- a/src/test/java/com/gg/server/domain/rank/service/RankServiceTest.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.gg.server.domain.rank.service; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; - -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.dto.ExpRankPageResponseDto; -import com.gg.server.domain.rank.dto.ExpRankV2Dto; -import com.gg.server.domain.rank.dto.RankPageResponseDto; -import com.gg.server.domain.rank.dto.RankV2Dto; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.service.SeasonFindService; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import static org.mockito.BDDMockito.*; - -@ExtendWith(MockitoExtension.class) -class RankServiceTest { - @Mock - private UserRepository userRepository; - @Mock - private RankRedisRepository redisRepository; - @Mock - private SeasonFindService seasonFindService; - @Mock - private RankRepository rankRepository; - @InjectMocks - private RankService rankService; - @BeforeEach - void setUp() { - // ํ˜„์žฌ ์‹œ์ฆŒ ๊ฐ€์ ธ์˜ค๊ธฐ - given(seasonFindService.findCurrentSeason(any())) - .willReturn(Season.builder() - .seasonName("Test Season") - .build()); - } - - @AfterEach - void tearDown() { - } - - @Test - void getExpRankPage() { - PageRequest pageRequest = PageRequest.of(0, 10); - // exp ranking user list, total page size ์กฐํšŒ - given(userRepository.findAllByTotalExpGreaterThan(pageRequest, 0)) - .willReturn(new PageImpl<>(new ArrayList(), pageRequest, 1)); - - // exp ranking list ์กฐํšŒ - List expRankV2DtoList = expRankingSampleData(); - given(userRepository.findExpRank(pageRequest.getPageNumber(), pageRequest.getPageSize(), - null)) - .willReturn(expRankV2DtoList); - ExpRankPageResponseDto testRes = rankService.getExpRankPage(pageRequest, UserDto - .builder() - .intraId("TestUser") - .id(1L) - .totalExp(0) - .build()); - assertThat(testRes.getMyRank()).isEqualTo(-1); - assertThat(testRes.getRankList().get(0).getIntraId()).isEqualTo("Test User"); - } - - private static List expRankingSampleData() { - List expRankV2Dtos = new ArrayList<>(); - expRankV2Dtos.add(new ExpRankV2Dto() { - @Override - public String getIntraId() { - return "Test User"; - } - - @Override - public String getStatusMessage() { - return "status message"; - } - - @Override - public Integer getTotalExp() { - return 0; - } - - @Override - public String getImageUri() { - return "null"; - } - - @Override - public String getTextColor() { - return null; - } - - @Override - public Integer getRanking() { - return 1; - } - }); - return expRankV2Dtos; - } - - @Test - void getRankPageV2() { - PageRequest pageRequest = PageRequest.of(0, 10); - // ํ˜„์žฌ ์‹œ์ฆŒ id ์— ํ•ด๋‹นํ•˜๋Š” ๋žญํฌ ์œ ์ € ๋ฆฌ์ŠคํŠธ์˜ ํŽ˜์ด์ง€ ์ˆ˜ - given(rankRepository.countRankUserBySeasonId(any())) - .willReturn(1); - // ํ˜„์žฌ ์œ ์ € ranking - given(rankRepository.findRankByUserIdAndSeasonId(any(), any())) - .willReturn(Optional.of(1)); - // sample data - List rankV2DtoList = pppRankingSampleData(); - given(rankRepository.findPppRankBySeasonId(anyInt(), anyInt(), any())) - .willReturn(rankV2DtoList); - RankPageResponseDto result = rankService.getRankPageV2(pageRequest, - UserDto - .builder() - .intraId("TestUser") - .id(1L) - .totalExp(0) - .build(), - any()); - assertThat(result.getCurrentPage()).isEqualTo(pageRequest.getPageNumber() + 1); - assertThat(result.getRankList().size()).isEqualTo(rankV2DtoList.size()); - } - - private static List pppRankingSampleData() { - List rankV2DtoList = new ArrayList<>(); - rankV2DtoList.add(new RankV2Dto() { - @Override - public String getIntraId() { - return "TestUser"; - } - - @Override - public String getStatusMessage() { - return "status message"; - } - - @Override - public Integer getPpp() { - return 1150; - } - - @Override - public String getTierImageUri() { - return "null"; - } - - @Override - public String getTextColor() { - return null; - } - - @Override - public Integer getRanking() { - return 1; - } - }); - return rankV2DtoList; - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/season/SeasonTestController.java b/src/test/java/com/gg/server/domain/season/SeasonTestController.java deleted file mode 100644 index 23bfe8635..000000000 --- a/src/test/java/com/gg/server/domain/season/SeasonTestController.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.gg.server.domain.season; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.season.dto.SeasonListResDto; -import com.gg.server.domain.season.dto.SeasonResDto; -import com.gg.server.domain.season.service.SeasonService; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import com.gg.server.utils.annotation.IntegrationTest; -import java.time.LocalDateTime; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -public class SeasonTestController { - - @Autowired - MockMvc mvc; - @Autowired - private SeasonService seasonService; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - ObjectMapper objectMapper; - - @Autowired - private SeasonRepository seasonRepository; - - - @BeforeEach - @Transactional - public void init() { - System.out.println("before each"); - Season s1 = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100); - seasonRepository.save(s1); - seasonRepository.save(new Season("test2 season", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100)); - seasonRepository.flush(); - System.out.println(seasonRepository.findAll()); - } - - @Test - @DisplayName("์‹œ์ฆŒ ์กฐํšŒ Test") - @Transactional - void season_list_test() throws Exception { - //given - String accessToken = testDataUtils.getLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - String url = "/pingpong/seasons"; - List list = seasonService.seasonList(); - //when - String contentAsString = mvc.perform(RestDocumentationRequestBuilders.get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - //then - SeasonListResDto result = objectMapper.readValue(contentAsString, SeasonListResDto.class); - assertThat(list.size()).isEqualTo(result.getSeasonList().size()); - } -} diff --git a/src/test/java/com/gg/server/domain/season/SeasonTriggerTest.java b/src/test/java/com/gg/server/domain/season/SeasonTriggerTest.java deleted file mode 100644 index d4c65cb49..000000000 --- a/src/test/java/com/gg/server/domain/season/SeasonTriggerTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.gg.server.domain.season; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import javax.persistence.EntityManager; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.cglib.proxy.UndeclaredThrowableException; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -@RequiredArgsConstructor -@IntegrationTest -@AutoConfigureMockMvc -@Slf4j -public class SeasonTriggerTest { - - @Autowired - MockMvc mvc; - @Autowired - TestDataUtils testDataUtils; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - ObjectMapper objectMapper; - @Autowired - EntityManager em; - - @Autowired - private SeasonRepository seasonRepository; - - - @BeforeEach - @Transactional - public void init() { - System.out.println("before each"); - Season s1 = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100); - seasonRepository.save(s1); - seasonRepository.save(new Season("test2 season", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100)); - seasonRepository.flush(); - System.out.println(seasonRepository.findAll()); - } - - @Test - @DisplayName("์‹œ์ฆŒ ์‚ญ์ œ ๋ฐฉ์ง€ Test") - @Transactional - public void ์‹œ์ฆŒ์‚ญ์ œ๋ฐฉ์ง€Test() { - Season season = new Season("test1 ์‹œ์ฆŒ", LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), 1000, 100); - seasonRepository.save(season); - Long id = season.getId(); - testDataUtils.createMockMatch(testDataUtils.createNewUser(), season, - LocalDateTime.now().minusMinutes(20), LocalDateTime.now().minusMinutes(5), Mode.RANK); - log.info("ID : " + id); - Throwable thrownException = Assertions.assertThrows(UndeclaredThrowableException.class, () -> { - seasonRepository.deleteById(id); - em.flush(); - }); - - log.info("์—๋Ÿฌ ๋ฉ”์‹œ์ง€: " + thrownException.getMessage()); - } -} diff --git a/src/test/java/com/gg/server/domain/team/data/TeamUnitTest.java b/src/test/java/com/gg/server/domain/team/data/TeamUnitTest.java deleted file mode 100644 index a5da26df2..000000000 --- a/src/test/java/com/gg/server/domain/team/data/TeamUnitTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.gg.server.domain.team.data; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import com.gg.server.utils.annotation.UnitTest; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@UnitTest -@DisplayName("TeamUnitTest") -class TeamUnitTest { - - List mockTeamUsers; - List teams; - - @BeforeEach - void setUp() { - mockTeamUsers = IntStream.range(0, 10) - .mapToObj(i -> mock(TeamUser.class)) - .collect(Collectors.toCollection(ArrayList::new)); - teams = IntStream.range(0, 10) - .mapToObj(i -> new Team()) - .collect(Collectors.toCollection(ArrayList::new)); - } - - @Nested - @DisplayName("AddTeamUser") - class AddTeam { - - @Test - @DisplayName("๋‹จ์ผ TeamUser ์ถ”๊ฐ€ ์„ฑ๊ณต") - public void addSingleTeamSuccess() { - //given - Team team = teams.get(0); - TeamUser mockTeamUser = mockTeamUsers.get(0); - - //when - team.addTeamUser(mockTeamUser); - - //then - assertEquals(1, team.getTeamUsers().size()); - assertEquals(mockTeamUser, team.getTeamUsers().get(0)); - } - - @Test - @DisplayName("๋‘๊ฐœ TeamUser ์ถ”๊ฐ€ ์„ฑ๊ณต") - void addMultiTeamSuccess() { - //given - Team team = teams.get(0); - - //when - team.addTeamUser(mockTeamUsers.get(0)); - team.addTeamUser(mockTeamUsers.get(1)); - - //then - assertEquals(2, team.getTeamUsers().size()); - assertEquals(mockTeamUsers.get(0), team.getTeamUsers().get(0)); - assertEquals(mockTeamUsers.get(1), team.getTeamUsers().get(1)); - } - - @Test - @DisplayName("๋‘๊ฐœ ์ด์ƒ์˜ TeamUser ์ถ”๊ฐ€ ์‹คํŒจ") - void addExceedTeamFailed() { - //given - Team team = teams.get(0); - - //when - team.addTeamUser(mockTeamUsers.get(0)); - team.addTeamUser(mockTeamUsers.get(1)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> team.addTeamUser(mockTeamUsers.get(2))); - assertEquals(ErrorCode.TEAM_USER_EXCEED, businessException.getErrorCode()); - assertEquals(ErrorCode.TEAM_USER_EXCEED.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("๋™์ผํ•œ TeamUser ์ถ”๊ฐ€ ์‹คํŒจ") - void duplicatedTeamAddFailed() { - //given - Team team = teams.get(0); - - //when - team.addTeamUser(mockTeamUsers.get(0)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> team.addTeamUser(mockTeamUsers.get(0))); - assertEquals(ErrorCode.TEAM_USER_ALREADY_EXIST, businessException.getErrorCode()); - assertEquals(ErrorCode.TEAM_USER_ALREADY_EXIST.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Team team = teams.get(0); - - //when - TeamUser teamUser = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> team.addTeamUser(teamUser)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - } -} diff --git a/src/test/java/com/gg/server/domain/tournament/controller/TournamentFindControllerTest.java b/src/test/java/com/gg/server/domain/tournament/controller/TournamentFindControllerTest.java deleted file mode 100644 index a8fabcfd7..000000000 --- a/src/test/java/com/gg/server/domain/tournament/controller/TournamentFindControllerTest.java +++ /dev/null @@ -1,529 +0,0 @@ -package com.gg.server.domain.tournament.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.gg.server.utils.annotation.IntegrationTest; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.data.TournamentUserRepository; -import com.gg.server.domain.tournament.dto.TournamentListResponseDto; -import com.gg.server.domain.tournament.dto.TournamentResponseDto; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.CustomRuntimeException; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import com.gg.server.utils.TestDataUtils; -import java.time.LocalDateTime; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@IntegrationTest -@AutoConfigureMockMvc -@Transactional -@RequiredArgsConstructor -@Slf4j -public class TournamentFindControllerTest { - - @Autowired - MockMvc mockMvc; - @Autowired - TestDataUtils testDataUtils; - @Autowired - ObjectMapper objectMapper; - @Autowired - AuthTokenProvider tokenProvider; - @Autowired - TournamentUserRepository tournamentUserRepository; - - List tournamentList; - String accessToken; - - User tester; - - - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_๋ฆฌ์ŠคํŠธ_์กฐํšŒ") - class findTournamentListTest { - @BeforeEach - void beforeEach() { - tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, SnsType.SLACK, RoleType.ADMIN); - accessToken = tokenProvider.createToken(tester.getId()); - tournamentList = testDataUtils.makeTournamentList(); - } - @Test - @DisplayName("์ „์ฒด_์กฐํšŒ") - public void getTournamentList() throws Exception { - // given - int page = 1; - int size = 20; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); - - // then - List tournamentInfoList = resp.getTournaments(); - for (int i = 0; i < tournamentInfoList.size(); i++) { - Long tournamentId = tournamentInfoList.get(i).getTournamentId(); - TournamentResponseDto tournamentResponseDto = tournamentList.stream().filter(t -> t.getTournamentId().equals(tournamentId)).findFirst().orElse(null); - if (tournamentResponseDto != null) { - assertThat(tournamentInfoList.get(i).getTitle()).isEqualTo(tournamentResponseDto.getTitle()); - assertThat(tournamentInfoList.get(i).getContents()).isEqualTo(tournamentResponseDto.getContents()); - assertThat(tournamentInfoList.get(i).getType()).isEqualTo(tournamentResponseDto.getType()); - assertThat(tournamentInfoList.get(i).getStatus()).isEqualTo(tournamentResponseDto.getStatus()); - assertThat(tournamentInfoList.get(i).getWinnerIntraId()).isEqualTo(tournamentResponseDto.getWinnerIntraId()); - assertThat(tournamentInfoList.get(i).getWinnerImageUrl()).isEqualTo(tournamentResponseDto.getWinnerImageUrl()); - assertThat(tournamentInfoList.get(i).getPlayerCnt()).isEqualTo(tournamentResponseDto.getPlayerCnt()); - } - if (i > 0) - assertThat(tournamentInfoList.get(i).getStartTime()).isAfter(tournamentInfoList.get(i - 1).getEndTime()); - } - } - - @Test - @DisplayName("status๋ณ„_์กฐํšŒ") - public void getTournamentListByStatus() throws Exception { - - // given - int page = 1; - int size = 10; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&status=" + TournamentStatus.BEFORE; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); - - // then - List tournamentInfoList = resp.getTournaments(); - for (TournamentResponseDto responseDto : tournamentInfoList) { - assertThat(responseDto.getStatus()).isEqualTo(TournamentStatus.BEFORE); - } - } - - @Test - @DisplayName("type๋ณ„_์กฐํšŒ") - public void getTournamentListByType() throws Exception { - - // given - int page = 1; - int size = 10; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); - - // then - List tournamentInfoList = resp.getTournaments(); - for (TournamentResponseDto responseDto : tournamentInfoList) { - assertThat(responseDto.getType()).isEqualTo(TournamentType.ROOKIE); - } - } - - @Test - @DisplayName("type๊ณผ status ๋ณ„ ์กฐํšŒ") - public void getTournamentListByTypeAndStatus() throws Exception { - // given - int page = 1; - int size = 10; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE + "&status=" + TournamentStatus.BEFORE; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - TournamentListResponseDto resp = objectMapper.readValue(contentAsString, TournamentListResponseDto.class); - - // then - List tournamentInfoList = resp.getTournaments(); - for (TournamentResponseDto responseDto : tournamentInfoList) { - assertThat(responseDto.getType()).isEqualTo(TournamentType.ROOKIE); - assertThat(responseDto.getStatus()).isEqualTo(TournamentStatus.BEFORE); - } - } - - @Test - @DisplayName("์ž˜๋ชป๋œ type") - public void wrongType() throws Exception { - // given - int page = 1; - int size = 10; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + "rookie123" + "&status=" + TournamentStatus.BEFORE.getCode(); - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - - // then - log.info(contentAsString); - } - - @Test - @DisplayName("์ž˜๋ชป๋œ status") - public void wrongStatus() throws Exception { - // given - int page = 1; - int size = 10; - String url = "/pingpong/tournaments/?page=" + page + "&size=" + size + "&type=" + TournamentType.ROOKIE.getCode() + "&status=" + "wrongStatus"; - - // when - String contentAsString = mockMvc.perform(get(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse().getContentAsString(); - - // then - log.info(contentAsString); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‹ ์ฒญ_์ทจ์†Œ_ํ…Œ์ŠคํŠธ") - class cancelTournamentUserRegistrationTest { - @BeforeEach - void beforeEach() { - tester = testDataUtils.createNewUser("findControllerTester", "findControllerTester", RacketType.DUAL, SnsType.SLACK, RoleType.ADMIN); - accessToken = tokenProvider.createToken(tester.getId()); - } - @Test - @DisplayName("์œ ์ €_์‹ ์ฒญ_์ทจ์†Œ_์„ฑ๊ณต") - void success() throws Exception { - // given - int maxTournamentUser = 8; - Tournament tournament = testDataUtils.createTournament(LocalDateTime.now(), LocalDateTime.now(), TournamentStatus.BEFORE); - for (int i=0; i{throw new CustomRuntimeException("", ErrorCode.BAD_REQUEST);}); - List tournamentUserList = tournament.getTournamentUsers(); - for (int i=0; i tournamentGameList = testDataUtils.createTournamentGameList(tournament, 7); - SlotManagement slotManagement = SlotManagement.builder() - .pastSlotTime(0) - .futureSlotTime(0) - .openMinute(0) - .gameInterval(15) - .startTime(LocalDateTime.now().minusHours(1)) - .build(); - slotManagementRepository.save(slotManagement); - - // when - tournamentService.startTournament(); - - // then - // ํ† ๋„ˆ๋จผํŠธ์˜ ์ƒํƒœ๊ฐ€ LIVE๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - assertThat(tournament.getStatus()) - .isEqualTo(TournamentStatus.LIVE); - - // game์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - List tournamentGames = tournamentGameRepository.findAllByTournamentId(tournament.getId()).stream() - .filter(o -> o.getGame() != null) - .collect(Collectors.toList()); - assertThat(tournamentGames.size()).isEqualTo(Tournament.ALLOWED_JOINED_NUMBER / 2); - for (TournamentGame tournamentGame : tournamentGames) { - assertThat(tournamentGame.getGame()).isNotNull(); - } - //์ฐธ๊ฐ€์ž์—๊ฒŒ ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ๋ฐ ๋งค์นญ ์•Œ๋ฆผ์ด ์ „์†ก๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - verify(notiAdminService, times(Tournament.ALLOWED_JOINED_NUMBER)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์ทจ์†Œ ์„ฑ๊ณต") - public void cancelTournamentTest() { - // given - testDataUtils.createSeason(); - // BEFORE๋กœ ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ - Tournament tournament = testDataUtils.createTournamentWithUser(7, 0, "test"); - SlotManagement slotManagement = SlotManagement.builder() - .pastSlotTime(0) - .futureSlotTime(0) - .openMinute(0) - .gameInterval(15) - .startTime(LocalDateTime.now().minusHours(1)) - .build(); - slotManagementRepository.save(slotManagement); - - // when - tournamentService.startTournament(); - - // then - //์ฐธ๊ฐ€์ž์—๊ฒŒ ์ทจ์†Œ ์•Œ๋ฆผ์ด ์ „์†ก๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - verify(notiAdminService, times(7)).sendAnnounceNotiToUser(Mockito.any(SendNotiAdminRequestDto.class)); - } - } - -} diff --git a/src/test/java/com/gg/server/domain/tournament/data/TournamentGameUnitTest.java b/src/test/java/com/gg/server/domain/tournament/data/TournamentGameUnitTest.java deleted file mode 100644 index bd2cdd397..000000000 --- a/src/test/java/com/gg/server/domain/tournament/data/TournamentGameUnitTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.utils.annotation.UnitTest; -import org.junit.jupiter.api.*; -import org.mockito.Mockito; - -@UnitTest -@DisplayName("TournamentGameUnitTest") -public class TournamentGameUnitTest { - - TournamentGame tournamentGame; - - @Nested - @DisplayName("UpdateGame") - class UpdateGame { - @Test - @DisplayName("TournamentGame์˜ ๊ฒŒ์ž„ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") - void updateSuccess() { - //given - tournamentGame = new TournamentGame(); - Game game = Mockito.mock(Game.class); - - //when - tournamentGame.updateGame(game); - - //then - Assertions.assertEquals(game, tournamentGame.getGame()); - } - } -} diff --git a/src/test/java/com/gg/server/domain/tournament/data/TournamentUnitTest.java b/src/test/java/com/gg/server/domain/tournament/data/TournamentUnitTest.java deleted file mode 100644 index c7de7468c..000000000 --- a/src/test/java/com/gg/server/domain/tournament/data/TournamentUnitTest.java +++ /dev/null @@ -1,353 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; - -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.user.data.User; -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import com.gg.server.utils.annotation.UnitTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - - -@UnitTest -@DisplayName("TournamentUnitTest") -class TournamentUnitTest { - - List mockTournamentGames; - List mockTournamentUsers; - List tournaments; - - @BeforeEach - void setUp() { - mockTournamentGames = IntStream.range(0, 10) - .mapToObj(i -> mock(TournamentGame.class)) - .collect(Collectors.toCollection(ArrayList::new)); - - mockTournamentUsers = IntStream.range(0, 10) - .mapToObj(i -> mock(TournamentUser.class)) - .collect(Collectors.toCollection(ArrayList::new)); - - tournaments = IntStream.range(0, 10) - .mapToObj(i -> new Tournament()) - .collect(Collectors.toCollection(ArrayList::new)); - } - - @Nested - @DisplayName("AddTournamentGame") - class AddTournamentGame { - - @Test - @DisplayName("๋‹จ์ผ TournamentGame ์ถ”๊ฐ€ ์„ฑ๊ณต") - public void addSingleTournamentGameSuccess() { - //given - Tournament tournament = tournaments.get(0); - TournamentGame mockTournamentGame = mockTournamentGames.get(0); - - //when - tournament.addTournamentGame(mockTournamentGame); - - //then - assertEquals(1, tournament.getTournamentGames().size()); - assertEquals(mockTournamentGame, tournament.getTournamentGames().get(0)); - } - - @Test - @DisplayName("์ตœ๋Œ€ TournamentGame ์ถ”๊ฐ€ ์„ฑ๊ณต") - void addMultiTournamentGameSuccess() { - //given - Tournament tournament = tournaments.get(0); - - //when - IntStream.range(0, 7).forEach(i -> tournament.addTournamentGame(mockTournamentGames.get(i))); - - //then - assertEquals(7, tournament.getTournamentGames().size()); - IntStream.range(0, 7).forEach(i -> - assertEquals(mockTournamentGames.get(i), tournament.getTournamentGames().get(i))); - } - - @Test - @DisplayName("์ตœ๋Œ€ ์ด์ƒ์˜ TournamentGame ์ถ”๊ฐ€ ์‹คํŒจ") - void addExceedTournamentGameFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - IntStream.range(0, 7).forEach(i -> tournament.addTournamentGame(mockTournamentGames.get(i))); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.addTournamentGame(mockTournamentGames.get(7))); - assertEquals(ErrorCode.TOURNAMENT_GAME_EXCEED, businessException.getErrorCode()); - assertEquals(ErrorCode.TOURNAMENT_GAME_EXCEED.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("๋™์ผํ•œ TournamentGame ์ถ”๊ฐ€ ์‹คํŒจ") - void duplicatedTournamentGameAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - tournament.addTournamentGame(mockTournamentGames.get(0)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.addTournamentGame(mockTournamentGames.get(0))); - assertEquals(ErrorCode.TOURNAMENT_GAME_DUPLICATION, businessException.getErrorCode()); - assertEquals(ErrorCode.TOURNAMENT_GAME_DUPLICATION.getMessage(), - businessException.getMessage()); - } - - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - TournamentGame tournamentGame = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.addTournamentGame(tournamentGame)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - } - - @Nested - @DisplayName("AddTournamentUser") - class AddTournamentUser { - - @Test - @DisplayName("๋‹จ์ผ TournamentUser ์ถ”๊ฐ€ ์„ฑ๊ณต") - public void addSingleTournamentGameSuccess() { - //given - Tournament tournament = tournaments.get(0); - TournamentUser mockTournamentUser = mockTournamentUsers.get(0); - - //when - tournament.addTournamentUser(mockTournamentUser); - - //then - assertEquals(1, tournament.getTournamentUsers().size()); - assertEquals(mockTournamentUser, tournament.getTournamentUsers().get(0)); - } - - @Test - @DisplayName("์—ฌ๋Ÿฌ TournamentUser ์ถ”๊ฐ€ ์„ฑ๊ณต") - void addMultiTournamentGameSuccess() { - //given - Tournament tournament = tournaments.get(0); - - //when - IntStream.range(0, mockTournamentUsers.size()).forEach(i -> - tournament.addTournamentUser(mockTournamentUsers.get(i))); - - //then - assertEquals(mockTournamentUsers.size(), tournament.getTournamentUsers().size()); - IntStream.range(0, mockTournamentUsers.size()).forEach(i -> - assertEquals(mockTournamentUsers.get(i), tournament.getTournamentUsers().get(i))); - } - - @Test - @DisplayName("๋™์ผํ•œ TournamentUser ์ถ”๊ฐ€ ์‹คํŒจ") - void duplicatedTournamentGameAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - tournament.addTournamentUser(mockTournamentUsers.get(0)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.addTournamentUser(mockTournamentUsers.get(0))); - assertEquals(ErrorCode.TOURNAMENT_USER_DUPLICATION, businessException.getErrorCode()); - assertEquals(ErrorCode.TOURNAMENT_USER_DUPLICATION.getMessage(), - businessException.getMessage()); - } - - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - TournamentUser tournamentUser = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.addTournamentUser(tournamentUser)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - } - - @Nested - @DisplayName("DeleteTournamentUser") - class DeleteTournamentUser { - - @Test - @DisplayName("TournamentUser ์‚ญ์ œ ์„ฑ๊ณต") - public void addSingleTournamentGameSuccess() { - //given - Tournament tournament = tournaments.get(0); - TournamentUser mockTournamentUser = mockTournamentUsers.get(0); - tournament.addTournamentUser(mockTournamentUser); - - //when - tournament.deleteTournamentUser(mockTournamentUser); - - //then - assertEquals(0, tournament.getTournamentUsers().size()); - } - - @Test - @DisplayName("์กด์žฌํ•˜์ง€ ์•Š๋Š” TournamentUser ์‚ญ์ œ ์‹คํŒจ") - void duplicatedTournamentGameAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - tournament.addTournamentUser(mockTournamentUsers.get(0)); - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.deleteTournamentUser(mockTournamentUsers.get(1))); - assertEquals(ErrorCode.TOURNAMENT_USER_NOT_FOUND, businessException.getErrorCode()); - assertEquals(ErrorCode.TOURNAMENT_USER_NOT_FOUND.getMessage(), - businessException.getMessage()); - } - - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - TournamentUser tournamentUser = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.deleteTournamentUser(tournamentUser)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - } - - @Nested - @DisplayName("UpdateWinner") - class UpdateWinner { - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - User user = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.updateWinner(user)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("์Šน์ž ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") - void updateSuccess() { - //given - Tournament tournament = tournaments.get(0); - User user = mock(User.class); - - //when - tournament.updateWinner(user); - - //then - assertEquals(user, tournament.getWinner()); - } - } - - @Nested - @DisplayName("UpdateStatus") - class UpdateStatus { - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - TournamentStatus status = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.updateStatus(status)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("์ƒํƒœ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") - void updateSuccess() { - //given - Tournament tournament = tournaments.get(0); - TournamentStatus status = TournamentStatus.LIVE; - - //when - tournament.updateStatus(status); - - //then - assertEquals(status, tournament.getStatus()); - } - } - - @Nested - @DisplayName("UpdateStatus") - class UpdateEndTime { - @Test - @DisplayName("null ํฌ์ธํ„ฐ ์ „๋‹ฌ ์‹œ ์‹คํŒจ") - void nullAddFailed() { - //given - Tournament tournament = tournaments.get(0); - - //when - LocalDateTime endTime = null; - - //then - BusinessException businessException = assertThrows(BusinessException.class, - () -> tournament.updateEndTime(endTime)); - assertEquals(ErrorCode.NULL_POINT, businessException.getErrorCode()); - assertEquals(ErrorCode.NULL_POINT.getMessage(), businessException.getMessage()); - } - - @Test - @DisplayName("endTime ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") - void updateEndTimeSuccess() { - //given - Tournament tournament = tournaments.get(0); - LocalDateTime endTime = LocalDateTime.now().withMinute(0).withNano(0); - - //when - tournament.updateEndTime(endTime); - - //then - assertEquals(endTime, tournament.getEndTime()); - } - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/domain/tournament/data/TournamentUserUnitTest.java b/src/test/java/com/gg/server/domain/tournament/data/TournamentUserUnitTest.java deleted file mode 100644 index 6026f73d9..000000000 --- a/src/test/java/com/gg/server/domain/tournament/data/TournamentUserUnitTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.gg.server.domain.tournament.data; - -import com.gg.server.domain.user.data.User; -import com.gg.server.utils.annotation.UnitTest; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import java.time.LocalDateTime; - -@UnitTest -@DisplayName("TournamentUserUnitTest") -public class TournamentUserUnitTest { - Tournament tournament; - TournamentUser tournamentUser; - User user; - - @Nested - @DisplayName("DeleteTournament") - class DeleteTournament { - @Test - @DisplayName("ํ† ๋„ˆ๋จผํŠธ ์‚ญ์ œ ์„ฑ๊ณต") - void deleteSuccess() { - //given - user = Mockito.mock(User.class); - tournament = new Tournament(); - tournamentUser = new TournamentUser(user, tournament, false, LocalDateTime.now()); - - //when - tournamentUser.deleteTournament(); - - //then - Assertions.assertNull(tournamentUser.getTournament()); - } - } - - @Nested - @DisplayName("UpdateIsJoined") - class UpdateIsJoined { - @Test - @DisplayName("์ฐธ๊ฐ€ ์ •๋ณด ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต") - void updateSuccess() { - //given - tournamentUser = new TournamentUser(); - boolean isjoined = true; - - //when - tournamentUser.updateIsJoined(isjoined); - - //then - Assertions.assertEquals(isjoined, tournamentUser.getIsJoined()); - } - } -} diff --git a/src/test/java/com/gg/server/domain/tournament/service/TournamentServiceTest.java b/src/test/java/com/gg/server/domain/tournament/service/TournamentServiceTest.java deleted file mode 100644 index f0e384d9d..000000000 --- a/src/test/java/com/gg/server/domain/tournament/service/TournamentServiceTest.java +++ /dev/null @@ -1,287 +0,0 @@ -package com.gg.server.domain.tournament.service; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; - -import com.gg.server.admin.tournament.dto.TournamentAdminCreateRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminUpdateRequestDto; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.data.TournamentGameRepository; -import com.gg.server.domain.tournament.data.TournamentRepository; -import com.gg.server.domain.tournament.data.TournamentUser; -import com.gg.server.domain.tournament.data.TournamentUserRepository; -import com.gg.server.domain.tournament.dto.TournamentUserRegistrationResponseDto; -import com.gg.server.domain.tournament.exception.TournamentConflictException; -import com.gg.server.domain.tournament.exception.TournamentNotFoundException; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserDto; -import com.gg.server.domain.user.exception.UserNotFoundException; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.utils.ReflectionUtilsForUnitTest; -import com.gg.server.utils.annotation.UnitTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@UnitTest -@ExtendWith(MockitoExtension.class) -class TournamentServiceTest { - @Mock - TournamentRepository tournamentRepository; - @Mock - TournamentGameRepository tournamentGameRepository; - @Mock - TournamentUserRepository tournamentUserRepository; - @Mock - UserRepository userRepository; - @InjectMocks - TournamentService tournamentService; - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ƒํƒœ_ํ…Œ์ŠคํŠธ") - class UserStatusInTournamentTest { - @Test - @DisplayName("์œ ์ €_์ƒํƒœ_๋ฐ˜ํ™˜_์„ฑ๊ณต") - void success() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - LocalDateTime.now(), LocalDateTime.now().plusHours(2)); - User user = createUser("testUser"); - TournamentUser tournamentUser = new TournamentUser(user, tournament, true, LocalDateTime.now()); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - given(tournamentUserRepository.findByTournamentIdAndUserId(tournament.getId(), user.getId())) - .willReturn(Optional.of(tournamentUser)); - - // when, then - TournamentUserRegistrationResponseDto responseDto = - tournamentService.getUserStatusInTournament(tournament.getId(), UserDto.from(user)); - } - - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") - void tournamentNotFound() { - // given - Long tournamentId = 1L; - User user = createUser("testUser"); - given(tournamentRepository.findById(tournamentId)).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(() -> tournamentService.getUserStatusInTournament(tournamentId, UserDto.from(user))) - .isInstanceOf(TournamentNotFoundException.class); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์‹ ์ฒญ_ํ…Œ์ŠคํŠธ") - class RegisterTournamentUserTest { - @Test - @DisplayName("์œ ์ €_์ƒํƒœ_์ถ”๊ฐ€_์„ฑ๊ณต") - void success() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - LocalDateTime.now(), LocalDateTime.now().plusHours(2)); - User user = createUser("testUser"); - List tournamentUserList = new ArrayList<>(); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); - given(tournamentUserRepository.findAllByUser(any(User.class))).willReturn(tournamentUserList); - - // when, then - TournamentUserRegistrationResponseDto responseDto = - tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user)); - } - - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") - void tournamentNotFound() { - // given - User user = createUser("testUser"); - given(tournamentRepository.findById(any(Long.class))).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(()->tournamentService.registerTournamentUser(1L, UserDto.from(user))) - .isInstanceOf(TournamentNotFoundException.class); - } - - @Test - @DisplayName("db์—_์—†๋Š”_์œ ์ €") - void userNotFound() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - LocalDateTime.now(), LocalDateTime.now().plusHours(2)); - User user = createUser("testUser"); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - given(userRepository.findById(null)).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(()->tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user))) - .isInstanceOf(UserNotFoundException.class); - } - - @Test - @DisplayName("์ด๋ฏธ_์‹ ์ฒญํ•œ_ํ† ๋„ˆ๋จผํŠธ_์กด์žฌ") - void conflictedRegistration() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - LocalDateTime.now(), LocalDateTime.now().plusHours(2)); - User user = createUser("testUser"); - List tournamentUserList = new ArrayList<>(); - tournamentUserList.add(new TournamentUser(user, tournament, true, LocalDateTime.now())); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); - given(tournamentUserRepository.findAllByUser(any(User.class))).willReturn(tournamentUserList); - - // when, then - assertThatThrownBy(()->tournamentService.registerTournamentUser(tournament.getId(), UserDto.from(user))) - .isInstanceOf(TournamentConflictException.class); - } - } - - @Nested - @DisplayName("ํ† ๋„ˆ๋จผํŠธ_์œ ์ €_์ฐธ๊ฐ€_์ทจ์†Œ_ํ…Œ์ŠคํŠธ") - class cancelTournamentUserRegistration { - @Test - @DisplayName("์œ ์ €_์ฐธ๊ฐ€_์ทจ์†Œ_์„ฑ๊ณต") - void success() { - // given - Tournament tournament = createTournament(1L, TournamentStatus.BEFORE, - LocalDateTime.now(), LocalDateTime.now().plusHours(2)); - User user = createUser("testUser"); - ReflectionUtilsForUnitTest.setFieldWithReflection(user, "id", 1L); - TournamentUser tournamentUser = new TournamentUser(user, tournament, true, LocalDateTime.now()); - given(tournamentRepository.findById(tournament.getId())).willReturn(Optional.of(tournament)); - - // when, then - tournamentService.cancelTournamentUserRegistration(tournament.getId(), UserDto.from(user)); - } - - @Test - @DisplayName("์ฐพ์„_์ˆ˜_์—†๋Š”_ํ† ๋„ˆ๋จผํŠธ") - void tournamentNotFound() { - // given - Long tournamentId = 1L; - User user = createUser("testUser"); - given(tournamentRepository.findById(tournamentId)).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(()->tournamentService.cancelTournamentUserRegistration(tournamentId, UserDto.from(user))) - .isInstanceOf(TournamentNotFoundException.class); - } - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ requestDto - * @param startTime ํ† ๋„ˆ๋จผํŠธ ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @return - */ - private TournamentAdminCreateRequestDto createTournamentCreateRequestDto(String title, LocalDateTime startTime, LocalDateTime endTime) { - return new TournamentAdminCreateRequestDto( - title, - "์ œ 1ํšŒ ๋ฃจํ‚ค์ „ ๋งŽ๊ด€๋ถ€!!", - startTime, - endTime, - TournamentType.ROOKIE - ); - } - - /** - * ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” ์ƒ์„ฑ - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ๋ช‡ ๋ฒˆ์งธ ๊ฒŒ์ž„์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด - * @return ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - */ - private TournamentGame createTournamentGame(Tournament tournament, TournamentRound round) { - TournamentGame tournamentGame = new TournamentGame(null, tournament, round); - return tournamentGameRepository.save(tournamentGame); - } - - /** - * ํ˜„์žฌ ์‹œ๊ฐ„์—์„œ days hours, ๋งŒํผ ์ฐจ์ด๋‚˜๋Š” ์‹œ๊ฐ„์„ ๊ตฌํ•œ๋‹ค. - * @param days - * @param hours - * @return - */ - private LocalDateTime getTargetTime(long days, long hours) { - return LocalDateTime.now().plusDays(days).plusHours(hours); - } - - private Tournament createTournament(Long id, TournamentStatus status, LocalDateTime startTime, LocalDateTime endTime) { - Tournament tournament = Tournament.builder() - .title(id + "st tournament") - .contents("") - .startTime(startTime) - .endTime(endTime) - .type(TournamentType.ROOKIE) - .status(status) - .build(); - ReflectionUtilsForUnitTest.setFieldWithReflection(tournament, "id", id); - return tournament; - } - - /** - *
id ๋ถ€ํ„ฐ cnt๊ฐœ ๋งŒํผ์˜ ํ† ๋„ˆ๋จผํŠธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.
- * ๊ฐ ํ† ๋„ˆ๋จผํŠธ๋Š” 1์‹œ๊ฐ„ ๊ธธ์ด์ด๋ฉฐ, ํ† ๋„ˆ๋จผํŠธ๊ฐ„ 1์‹œ๊ฐ„์˜ ๊ฐ„๊ฒฉ์ด ์žˆ๋‹ค. - * @param id - * @param cnt - * @param startTime - * @return - */ - private List createTournaments(Long id, long cnt, LocalDateTime startTime) { - List tournamentList = new ArrayList<>(); - for (long i=0; i historics = responseDto.getHistorics(); -// findPChangesHistory ์—๋Š” ์ •๋ ฌํ•œ๋‹ค๋Š” ๋‚ด์šฉ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™์•„ ๋ณด๋ฅ˜ -// Assertions.assertThat(historics) -// .isSortedAccordingTo(Comparator.comparing(UserHistoryData::getDate)); - } - - @Test - @DisplayName("[put] {intraId}") - public void updateUser() throws Exception { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - String imageUrl = "imageUrl"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); - String statusMessage = "statusMessage"; - testDataUtils.createUserRank(newUser, statusMessage, season); - String accessToken = tokenProvider.createToken(newUser.getId()); - String url = "/pingpong/users/" + newUser.getIntraId(); - - String newStatusMessage = "newStatusMessage"; - RacketType newRacketType = RacketType.SHAKEHAND; - SnsType newSnsType = SnsType.SLACK; - - //when - mockMvc.perform(put(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new UserModifyRequestDto(newRacketType, newStatusMessage, newSnsType)))) - .andExpect(status().isNoContent()); - //then - String hashKey = RedisKeyManager.getHashKey(season.getId()); - RankRedis rank = redisRepository.findRankByUserId(hashKey, newUser.getId()); - rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).ifPresentOrElse(rank1 -> { - Assertions.assertThat(rank1.getStatusMessage()).isEqualTo(newStatusMessage); - }, () -> { - Assertions.fail("๋žญํฌ ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); - }); - userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { - Assertions.assertThat(user.getRacketType()).isEqualTo((newRacketType)); - Assertions.assertThat(user.getSnsNotiOpt()).isEqualTo(newSnsType); - Assertions.assertThat(rank.getStatusMessage()).isEqualTo(newStatusMessage); - }, () -> { - Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); - }); - } - - @Test - @DisplayName("[post] /attendance") - public void attendUserTest() throws Exception { - //given - testDataUtils.createCoinPolicy(admin, 1, 0, 0, 0); - String accessToken = testDataUtils.getLoginAccessToken(); - String url = "/pingpong/users/attendance"; - - //when - String contentAsString = mockMvc.perform(post(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - UserAttendanceResponseDto result = objectMapper.readValue(contentAsString, UserAttendanceResponseDto.class); - - //then - System.out.println(result.getAfterCoin()); - Assertions.assertThat(result.getAfterCoin() - result.getBeforeCoin()).isEqualTo(result.getCoinIncrement()); - } - - @Test - @DisplayName("[patch] text-color") - public void updateTextColorTest() throws Exception { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); - String statusMessage = "statusMessage"; - testDataUtils.createUserRank(newUser, statusMessage, season); - String accessToken = tokenProvider.createToken(newUser.getId()); - String url = "/pingpong/users/text-color"; - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", - "subContent", 100, 50, ItemType.TEXT_COLOR); - Item item = itemTestUtils.createItem(admin, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); -// Receipt receipt = receiptRepository.findById(4L).get(); - String newTextColor = "#FFFFFF"; - - //when - mockMvc.perform(patch(url).header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(new UserTextColorDto(receipt.getId(), newTextColor)))) - .andExpect(status().is2xxSuccessful()); - //then - userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { - Assertions.assertThat(user.getTextColor()).isEqualTo(newTextColor); - }, () -> { - Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); - }); - AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); - } - - @Test - @DisplayName("[patch] edge") - public void updateEdgeTest() throws Exception { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); - String statusMessage = "statusMessage"; - testDataUtils.createUserRank(newUser, statusMessage, season); - String accessToken = tokenProvider.createToken(newUser.getId()); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", - "subContent", 100, 50, ItemType.EDGE); - Item item = itemTestUtils.createItem(admin, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); -// Receipt receipt = receiptRepository.findById(3L).get(); - String url = "/pingpong/users/edge"; - - //when - mockMvc.perform(patch(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .content(objectMapper.writeValueAsString(receipt.getId())) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - log.info("user.getEdge() : {}", newUser.getEdge()); - userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { - Assertions.assertThat(Arrays.stream(EdgeType.values()).anyMatch(v -> v.equals(user.getEdge()))).isEqualTo(true); - }, () -> { - Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); - }); - AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); - } - - @Test - @DisplayName("[get]/pingpong/users/coin") - public void getUserCoin() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - - String url = "/pingpong/users/coin"; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - UserCoinResponseDto result = objectMapper.readValue(contentAsString, UserCoinResponseDto.class); - int userCoin = userRepository.findById(userId).orElseThrow(() -> new UserNotFoundException()).getGgCoin(); - assertThat(result.getCoin()).isEqualTo(userCoin); - System.out.println(userCoin); - } - - @Test - @DisplayName("[patch] background") - public void updateBackgroundTest() throws Exception { - //given - Season season = testDataUtils.createSeason(); - String intraId = "intraId"; - String email = "email"; - User newUser = testDataUtils.createNewUser(intraId, email, RacketType.PENHOLDER, SnsType.BOTH, RoleType.USER); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", - "subContent", 100, 50, ItemType.BACKGROUND); - Item item = itemTestUtils.createItem(admin, dto); - Receipt receipt = itemTestUtils.purchaseItem(newUser, newUser, item); - String statusMessage = "statusMessage"; - testDataUtils.createUserRank(newUser, statusMessage, season); - String accessToken = tokenProvider.createToken(newUser.getId()); - -// Receipt receipt = receiptRepository.findById(2L).get(); - String uri = "/pingpong/users/background"; - - //when - mockMvc.perform(patch(uri) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) - .content(objectMapper.writeValueAsString(receipt.getId())) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is2xxSuccessful()) - .andReturn().getResponse().getContentAsString(); - - //then - log.info("user.getBackground() : {}", newUser.getBackground()); - userRepository.findById(newUser.getId()).ifPresentOrElse(user -> { - Assertions.assertThat(Arrays.stream(BackgroundType.values()).anyMatch(v -> v.equals(user.getBackground()))).isEqualTo(true); - }, () -> { - Assertions.fail("์œ ์ € ์—…๋ฐ์ดํŠธ ์‹คํŒจ"); - }); - AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); - } - - @Test - @DisplayName("[get]/pingpong/users/coinhistory") - public void getUserCoinHistory() throws Exception { - String accessToken = testDataUtils.getAdminLoginAccessToken(); - Long userId = tokenProvider.getUserIdFromAccessToken(accessToken); - User user = userRepository.getById(userId); - testDataUtils.createCoinPolicy(admin, 0, 1, 3, 2); - - coinHistoryService.addNormalCoin(user); - coinHistoryService.addRankWinCoin(user); - coinHistoryService.addNormalCoin(user); - String url = "/pingpong/users/coinhistory?page=1&size=5"; - - String contentAsString = mockMvc.perform(get(url) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(); - - UserCoinHistoryListResponseDto result = objectMapper.readValue(contentAsString, UserCoinHistoryListResponseDto.class); - - System.out.println(result.getTotalPage()); - for(CoinHistoryResponseDto temp : result.getUseCoinList()){ - System.out.println(temp.getHistory() + " " + temp.getAmount() + " " + temp.getCreatedAt()); - } - } - - @Test - @DisplayName("[post]/pingpong/users/profile-image") - public void getUserImage() throws Exception { - String mockS3Path = "mockS3Path"; - Mockito.when(userImageHandler - .uploadToS3(Mockito.any(MultipartFile.class), Mockito.any(String.class))) - .thenReturn(mockS3Path); -// String accessToken = testDataUtils.getLoginAccessToken(); - ItemUpdateRequestDto dto = new ItemUpdateRequestDto("name", "mainContent", - "subContent", 100, 50, ItemType.PROFILE_IMAGE); - Item item = itemTestUtils.createItem(admin, dto); - User user = testDataUtils.createNewUser(); - testDataUtils.createUserImage(user); - String accessToken = testDataUtils.getLoginAccessTokenFromUser(user); - Receipt receipt = itemTestUtils.purchaseItem(user, user, item); -// Receipt receipt = receiptRepository.findById(7L).orElseThrow(ReceiptNotFoundException::new); - MockMultipartFile image = new MockMultipartFile("profileImage", "imagefile.jpeg", "image/jpeg", "<>".getBytes()); - MockMultipartFile jsonFile = new MockMultipartFile("userProfileImageRequestDto", "", "application/json", ("{\"receiptId\": " + receipt.getId() + "}").getBytes()); - - String contentAsString = mockMvc.perform(multipart("/pingpong/users/profile-image") - .file(image) - .file(jsonFile) - .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)) - .andExpect(status().isNoContent()) - .andReturn().getResponse().getContentAsString(); - AssertionsForClassTypes.assertThat(receipt.getStatus()).isEqualTo(ItemStatus.USED); - } -} diff --git a/src/test/java/com/gg/server/domain/user/controller/dto/GameInfoDto.java b/src/test/java/com/gg/server/domain/user/controller/dto/GameInfoDto.java deleted file mode 100644 index 1fef1036e..000000000 --- a/src/test/java/com/gg/server/domain/user/controller/dto/GameInfoDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gg.server.domain.user.controller.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class GameInfoDto { - private Long gameId; - private Long myTeamId; - private Long myUserId; - private Long enemyTeamId; - private Long enemyUserId; -} diff --git a/src/test/java/com/gg/server/utils/ItemTestUtils.java b/src/test/java/com/gg/server/utils/ItemTestUtils.java deleted file mode 100644 index 02b013c3d..000000000 --- a/src/test/java/com/gg/server/utils/ItemTestUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.gg.server.utils; - -import com.gg.server.admin.item.dto.ItemUpdateRequestDto; -import com.gg.server.domain.item.data.Item; -import com.gg.server.domain.item.data.ItemRepository; -import com.gg.server.domain.megaphone.data.Megaphone; -import com.gg.server.domain.megaphone.data.MegaphoneRepository; -import com.gg.server.domain.receipt.data.Receipt; -import com.gg.server.domain.receipt.data.ReceiptRepository; -import com.gg.server.domain.receipt.type.ItemStatus; -import com.gg.server.domain.user.data.User; -import java.time.LocalDate; -import java.time.LocalDateTime; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; - -/** - * ItemTestUtils. - * - *

- * - *

- * - * @author : middlefitting - * @since : 2023/12/08 - */ -@Component -@AllArgsConstructor -public class ItemTestUtils { - - ItemRepository itemRepository; - - ReceiptRepository receiptRepository; - - MegaphoneRepository megaphoneRepository; - - /** - * ์•„์ดํ…œ์„ ๊ตฌ๋งคํ•œ๋‹ค.(์˜์ˆ˜์ฆ ์ƒ์„ฑ) - */ - public Receipt purchaseItem(User purchaser, User owner, Item item) { - Receipt receipt = new Receipt(item, purchaser.getIntraId(), owner.getIntraId(), - ItemStatus.BEFORE, LocalDateTime.now()); - return receiptRepository.save(receipt); - } - - /** - * ์•„์ดํ…œ์„ ์ƒ์„ฑํ•œ๋‹ค. - */ - public Item createItem(User creator, ItemUpdateRequestDto updateRequestDto) { - Item item = Item.builder() - .creatorIntraId(creator.getIntraId()) - .itemImageUri("42gg-s3") - .updateRequestDto(updateRequestDto) - .build(); - itemRepository.save(item); - return item; - } - - /** - * ๋ฉ”๊ฐ€ํฐ์„ ์ƒ์„ฑํ•œ๋‹ค. - * ํ˜„์žฌ ์„œ๋น„์Šค์— ๋งž๊ฒŒ WAITING ์ƒํƒœ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค. - */ - public Megaphone createMegaPhone(User user, Receipt receipt, String content) { - Megaphone mega = new Megaphone(user, receipt, content, LocalDate.now().plusDays(1)); - receipt.updateStatus(ItemStatus.WAITING); - receiptRepository.save(receipt); - megaphoneRepository.save(mega); - return mega; - } -} diff --git a/src/test/java/com/gg/server/utils/MatchTestUtils.java b/src/test/java/com/gg/server/utils/MatchTestUtils.java deleted file mode 100644 index 480c50706..000000000 --- a/src/test/java/com/gg/server/utils/MatchTestUtils.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.gg.server.utils; - -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.match.exception.WinningTeamNotFoundException; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.exception.TeamNotFoundException; -import com.gg.server.domain.tournament.data.Tournament; -import com.gg.server.domain.tournament.data.TournamentGame; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class MatchTestUtils { - private final UserRepository userRepository; - private final SeasonRepository seasonRepository; - private final RankRedisRepository rankRedisRepository; - private final SlotManagementRepository slotManagementRepository; - private final GameRepository gameRepository; - - public User createUser() { - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createGuestUser() { - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.GUEST) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public RankRedis addUsertoRankRedis(Long userId, Integer ppp, Long seasonId) { - String randomId = UUID.randomUUID().toString(); - RankRedis rankRedis = new RankRedis(userId, randomId, ppp, 0, 0,"test", "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000"); - rankRedisRepository.addRankData(RedisKeyManager.getHashKey(seasonId), userId, rankRedis); - rankRedisRepository.addToZSet(RedisKeyManager.getZSetKey(seasonId), userId, ppp); - return rankRedis; - } - - public List getTestSlotTimes(Integer interval) { - LocalDateTime now = LocalDateTime.now(); - LocalDateTime standard = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth() - , now.getHour(), 0); - List sampleSlots = new ArrayList(); - for (int i = 0; i < 15; i++) { - if (standard.plusMinutes(interval * i).isAfter(now)) { - sampleSlots.add(standard.plusMinutes(interval * i)); - } - } - return sampleSlots; - } - public Season makeTestSeason(Integer pppGap) { - Optional currentSeason = seasonRepository.findCurrentSeason(LocalDateTime.now()); - if (currentSeason.isPresent()) { - return currentSeason.get(); - } - Season season = new Season( - "test", - LocalDateTime.now().minusDays(1), - LocalDateTime.of(9999, 12, 31, 23, 59, 59), - 1000, - pppGap - ); - seasonRepository.save(season); - return season; - } - - public SlotManagement makeTestSlotManagement(Integer interval) { - SlotManagement slotManagement = SlotManagement.builder() - .futureSlotTime(10) - .pastSlotTime(0) - .gameInterval(interval) - .openMinute(5) - .startTime(LocalDateTime.now().minusHours(2)) - .build(); - slotManagementRepository.save(slotManagement); - return slotManagement; - } - - /** - * ํ† ๋„ˆ๋จผํŠธ์—์„œ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๊ฒฝ๊ธฐ๋“ค์„ ๋งค์นญ (์ƒ์„ฑ) - * @param tournament ํ† ๋„ˆ๋จผํŠธ - * @param round ํ•ด๋‹น ๋ผ์šด๋“œ์™€ ๋™์ผํ•œ ๋ผ์šด๋“œ์˜ ๋ชจ๋“  ๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ - * ex ) 8๊ฐ•์˜ ๊ฒฝ์šฐ 8๊ฐ•์˜ 4๊ฒฝ๊ธฐ๋ฅผ ๋งค์นญ - * @return ๋งค์นญ๋œ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ - */ - public List matchTournamentGames(Tournament tournament, TournamentRound round) { - Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()) - .orElseThrow(() -> new IllegalArgumentException("ํ˜„์žฌ ์‹œ์ฆŒ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.")); - List sameRounds = TournamentRound.getSameRounds(round); - List sameRoundGames = tournament.getTournamentGames().stream() - .filter(o -> sameRounds.contains(o.getTournamentRound())) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - List previousRoundTournamentGames = findSameRoundGames(tournament.getTournamentGames(), TournamentRound.getPreviousRoundNumber(round)); - - for (int i = 0; i < round.getRoundNumber() / 2; ++i) { - Game game = new Game(season, StatusType.BEFORE, Mode.TOURNAMENT, LocalDateTime.now(), LocalDateTime.now()); - Team team1 = new Team(game, -1, false); - Team team2 = new Team(game, -1, false); - User user1 = findMatchUser(previousRoundTournamentGames, i * 2, tournament); - User user2 = findMatchUser(previousRoundTournamentGames, i * 2 + 1, tournament); - new TeamUser(team1, user1); - new TeamUser(team2, user2); - gameRepository.save(game); - sameRoundGames.get(i).updateGame(game); - } - return sameRoundGames; - } - - /** - * ์—ฌ๋Ÿฌ ๊ฒฝ๊ธฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์ˆ˜์ • - * @param tournamentGames - * @param scores - */ - public void updateTournamentGamesResult(List tournamentGames, List scores) { - int sum = scores.stream().mapToInt(Integer::intValue).sum(); - if (sum > 3 || sum < 0) { - throw new IllegalArgumentException("๊ฒŒ์ž„ ์ ์ˆ˜๋Š” 0 ~ 3 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); - } - List games = tournamentGames.stream().map(TournamentGame::getGame).collect(Collectors.toList()); - for (Game game : games) { - updateTournamentGameResult(game, scores); - } - } - - /** - * ํ•˜๋‚˜์˜ ๊ฒฝ๊ธฐ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ ์—…๋ฐ์ดํŠธ - * @param game - * @param scores - */ - public void updateTournamentGameResult(Game game, List scores) { - int sum = scores.stream().mapToInt(Integer::intValue).sum(); - if (sum > 3 || sum < 0) { - throw new IllegalArgumentException("๊ฒŒ์ž„ ์ ์ˆ˜๋Š” 0 ~ 3 ์‚ฌ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."); - } - List teams = game.getTeams(); - teams.get(0).updateScore(scores.get(0), scores.get(0) > scores.get(1)); - teams.get(1).updateScore(scores.get(1), scores.get(0) < scores.get(1)); - // BEFORE -> LIVE -> WAIT -> END - game.updateStatus(); - game.updateStatus(); - game.updateStatus(); - - } - - public Team getWinningTeam(Game game) { - return game.getTeams().stream() - .filter(team -> Boolean.TRUE.equals(team.getWin())) - .findAny() - .orElseThrow(WinningTeamNotFoundException::new); - } - - private User findMatchUser(List previousTournamentGames, int index, Tournament tournament) { - if (previousTournamentGames.isEmpty()) { - return tournament.getTournamentUsers().get(index).getUser(); - } - Game game = previousTournamentGames.get(index).getGame(); - return getWinningTeam(game) - .getTeamUsers().get(0).getUser(); - } - - private List findSameRoundGames(List tournamentGames, int roundNum) { - return tournamentGames.stream() - .filter(tournamentGame -> roundNum == tournamentGame.getTournamentRound().getRoundNumber()) - .sorted(Comparator.comparing(TournamentGame::getTournamentRound)) - .collect(Collectors.toList()); - } -} diff --git a/src/test/java/com/gg/server/utils/ReflectionUtilsForUnitTest.java b/src/test/java/com/gg/server/utils/ReflectionUtilsForUnitTest.java deleted file mode 100644 index 80ecbcc5f..000000000 --- a/src/test/java/com/gg/server/utils/ReflectionUtilsForUnitTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.gg.server.utils; - -import com.gg.server.global.exception.ErrorCode; -import com.gg.server.global.exception.custom.BusinessException; -import java.lang.reflect.Field; - -/** - * ReflectionUtilsForUnitTest. - * - *

- * ์œ ๋‹› ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋ฆฌํ”Œ๋ ‰์…˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ - *

- * - */ -public class ReflectionUtilsForUnitTest { - - /** - * ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด์„œ ํ•„๋“œ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค. - */ - static public void setFieldWithReflection(Object object, String fieldName, Object value) { - try { - Field field = object.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(object, value); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new BusinessException(ErrorCode.BAD_REQUEST); - } - } -} diff --git a/src/test/java/com/gg/server/utils/TestDataUtils.java b/src/test/java/com/gg/server/utils/TestDataUtils.java deleted file mode 100644 index 564d111b7..000000000 --- a/src/test/java/com/gg/server/utils/TestDataUtils.java +++ /dev/null @@ -1,727 +0,0 @@ -package com.gg.server.utils; - -import com.gg.server.admin.tournament.dto.TournamentAdminCreateRequestDto; -import com.gg.server.admin.tournament.dto.TournamentAdminUpdateRequestDto; -import com.gg.server.domain.announcement.data.Announcement; -import com.gg.server.domain.announcement.data.AnnouncementRepository; -import com.gg.server.domain.coin.data.CoinPolicy; -import com.gg.server.domain.coin.data.CoinPolicyRepository; -import com.gg.server.domain.game.data.Game; -import com.gg.server.domain.game.data.GameRepository; -import com.gg.server.domain.game.exception.GameNotExistException; -import com.gg.server.domain.game.type.Mode; -import com.gg.server.domain.game.type.StatusType; -import com.gg.server.domain.noti.data.Noti; -import com.gg.server.domain.noti.data.NotiRepository; -import com.gg.server.domain.noti.type.NotiType; -import com.gg.server.domain.pchange.data.PChange; -import com.gg.server.domain.pchange.data.PChangeRepository; -import com.gg.server.domain.rank.data.Rank; -import com.gg.server.domain.rank.data.RankRepository; -import com.gg.server.domain.rank.redis.RankRedis; -import com.gg.server.domain.rank.redis.RankRedisRepository; -import com.gg.server.domain.rank.redis.RedisKeyManager; -import com.gg.server.domain.season.data.Season; -import com.gg.server.domain.season.data.SeasonRepository; -import com.gg.server.domain.slotmanagement.SlotManagement; -import com.gg.server.domain.slotmanagement.data.SlotManagementRepository; -import com.gg.server.domain.team.data.Team; -import com.gg.server.domain.team.data.TeamRepository; -import com.gg.server.domain.team.data.TeamUser; -import com.gg.server.domain.team.data.TeamUserRepository; -import com.gg.server.domain.tier.data.Tier; -import com.gg.server.domain.tier.data.TierRepository; -import com.gg.server.domain.tournament.data.*; -import com.gg.server.domain.tournament.dto.TournamentResponseDto; -import com.gg.server.domain.tournament.type.TournamentRound; -import com.gg.server.domain.tournament.type.TournamentStatus; -import com.gg.server.domain.tournament.type.TournamentType; -import com.gg.server.domain.user.controller.dto.GameInfoDto; -import com.gg.server.domain.user.data.User; -import com.gg.server.domain.user.data.UserImage; -import com.gg.server.domain.user.data.UserImageRepository; -import com.gg.server.domain.user.data.UserRepository; -import com.gg.server.domain.user.dto.UserImageDto; -import com.gg.server.domain.user.type.RacketType; -import com.gg.server.domain.user.type.RoleType; -import com.gg.server.domain.user.type.SnsType; -import com.gg.server.global.security.jwt.utils.AuthTokenProvider; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -@Component -@RequiredArgsConstructor -public class TestDataUtils { - private final UserRepository userRepository; - private final AuthTokenProvider tokenProvider; - private final NotiRepository notiRepository; - private final SeasonRepository seasonRepository; - private final GameRepository gameRepository; - private final TeamUserRepository teamUserRepository; - private final TeamRepository teamRepository; - private final RankRedisRepository redisRepository; - private final PChangeRepository pChangeRepository; - private final RankRepository rankRepository; - private final TierRepository tierRepository; - private final TournamentRepository tournamentRepository; - private final TournamentGameRepository tournamentGameRepository; - private final TournamentUserRepository tournamentUserRepository; - private final AnnouncementRepository announcementRepository; - private final CoinPolicyRepository coinPolicyRepository; - private final UserImageRepository userImageRepository; - private final SlotManagementRepository slotManagementRepository; - - public String getLoginAccessToken() { - User user = User.builder() - .eMail("email") - .intraId("intraId") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return tokenProvider.createToken(user.getId()); - } - - public String getLoginAccessTokenFromUser(User user) { - return tokenProvider.createToken(user.getId()); - } - - - public String getAdminLoginAccessToken() { - User user = User.builder() - .eMail("email") - .intraId("intraId") - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.ADMIN) - .totalExp(1000) - .build(); - userRepository.save(user); - return tokenProvider.createToken(user.getId()); - } - - public User createAdminUser(){ - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.ADMIN) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - /** - * Item ์—๋Š” ์ธํŠธ๋ผ ID๊ฐ€ ํ˜„์žฌ 10์ž๋กœ ์ œํ•œ๋˜์–ด ์žˆ์Œ - */ - public User createAdminUserForItem(){ - String randomId = UUID.randomUUID().toString().substring(0, 10); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.ADMIN) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(){ - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(String intraId){ - User user = User.builder() - .eMail("email") - .intraId(intraId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(1000) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(String intraId, String email, RacketType racketType, - SnsType snsType, RoleType roleType){ - User user = User.builder() - .eMail(email) - .intraId(intraId) - .racketType(racketType) - .snsNotiOpt(snsType) - .roleType(roleType) - .totalExp(0) - .build(); - userRepository.save(user); - return user; - } - - public User createNewUser(int totalExp){ - String randomId = UUID.randomUUID().toString().substring(0, 30); - User user = User.builder() - .eMail("email") - .intraId(randomId) - .racketType(RacketType.PENHOLDER) - .snsNotiOpt(SnsType.NONE) - .roleType(RoleType.USER) - .totalExp(totalExp) - .build(); - userRepository.save(user); - return user; - } - - public GameInfoDto addMockDataUserLiveApi(String event, int notiCnt, String currentMatchMode, Long userId) { - User curUser = userRepository.findById(userId).get(); - for (int i = 0; i < notiCnt; i++) { - Noti noti = new Noti(curUser, NotiType.ANNOUNCE, String.valueOf(i), false); - notiRepository.save(noti); - } - LocalDateTime startTime, endTime; - Season season = createSeason(); - createUserRank(curUser, "testUserMessage", season); - Mode mode = (currentMatchMode.equals(Mode.RANK.getCode()))? Mode.RANK : Mode.NORMAL; - createGame(curUser, LocalDateTime.now().minusMinutes(100), LocalDateTime.now().minusMinutes(85), season, mode); - createGame(curUser, LocalDateTime.now().minusMinutes(50), LocalDateTime.now().minusMinutes(35), season, mode); - LocalDateTime now = LocalDateTime.now(); - if (event.equals("match")){ - startTime = now.plusMinutes(10); - endTime = startTime.plusMinutes(15); - return createGame(curUser, startTime, endTime, season, mode); - }else if (event.equals("game")){ - startTime = now.minusMinutes(5); - endTime = startTime.plusMinutes(15); - return createGame(curUser, startTime, endTime, season, mode); - } - return null; - } - - public GameInfoDto createGame(User curUser, LocalDateTime startTime, LocalDateTime endTime, Season season, Mode mode) { - LocalDateTime now = LocalDateTime.now(); - Game game; - if (now.isBefore(startTime)) - game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); - else if (now.isAfter(startTime) && now.isBefore(endTime)) - game = new Game(season, StatusType.LIVE, mode, startTime, endTime); - else - game = new Game(season, StatusType.END, mode, startTime, endTime); - Team myTeam = new Team(game, -1, false); - TeamUser teamUser = new TeamUser(myTeam, curUser); - User enemyUser = createNewUser(); - Team enemyTeam = new Team(game, -1, false); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - createUserRank(curUser, "statusMessage", season); - createUserRank(enemyUser, "enemyUserMeassage", season); - gameRepository.save(game); - return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), enemyUser.getId()); - } - - - public Season createSeason(){ - LocalDateTime startTime = LocalDateTime.now().minusMinutes(5); - LocalDateTime endTime = startTime.plusMonths(1); - Season season = seasonRepository.findCurrentSeason(LocalDateTime.now()).orElse(null); - if (season == null) - season = new Season("name", startTime.minusMinutes(1), endTime, 1000, 300); - seasonRepository.save(season); - return season; - } - - public void createUserRank(User newUser, String statusMessage, Season season) { - if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) - return ; - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - redisRepository.addRankData(hashKey, newUser.getId(), - new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); - Rank userRank = Rank.builder() - .user(newUser) - .season(season) - .ppp(season.getStartPpp()) - .wins(0) - .losses(0) - .statusMessage(statusMessage) - .build(); - rankRepository.save(userRank); - } - - public void createUserRank(User newUser, String statusMessage, Season season, Tier tier) { - if (rankRepository.findByUserIdAndSeasonId(newUser.getId(), season.getId()).isPresent()) - return ; - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - redisRepository.addRankData(hashKey, newUser.getId(), - new RankRedis(newUser.getId(), "aa", season.getStartPpp(), 0, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); - Rank userRank = Rank.builder() - .user(newUser) - .season(season) - .ppp(season.getStartPpp()) - .wins(0) - .losses(0) - .statusMessage(statusMessage) - .tier(tier) - .build(); - rankRepository.save(userRank); - } - - public void createUserRank(User newUser, String statusMessage, Season season, int ppp) { - String zSetKey = RedisKeyManager.getZSetKey(season.getId()); - String hashKey = RedisKeyManager.getHashKey(season.getId()); - Tier tier = tierRepository.findStartTier().get(); - redisRepository.addToZSet(zSetKey, newUser.getId(), ppp); - redisRepository.addRankData(hashKey, newUser.getId(), - new RankRedis(newUser.getId(), "aa", ppp, 1, 0, statusMessage, "https://42gg-public-image.s3.ap-northeast-2.amazonaws.com/images/nheo.jpeg", "#000000")); - Rank userRank = Rank.builder() - .user(newUser) - .season(season) - .ppp(ppp) - .wins(1) - .losses(0) - .statusMessage(statusMessage) - .tier(tier) - .build(); - rankRepository.save(userRank); - } - - public void createMockMatchWithMockRank(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime) { - Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, 0, false); - TeamUser teamUser = new TeamUser(myTeam, newUser); - Team enemyTeam = new Team(game, 0, false); - User enemyUser = createNewUser(); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - createUserRank(enemyUser, "status message", season); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - PChange pChange1 = new PChange(game, newUser, 1100, true); - PChange pChange2 = new PChange(game, enemyUser, 900, true); - pChangeRepository.save(pChange1); - pChangeRepository.save(pChange2); - } - - public void createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime) { - Game game = new Game(season, StatusType.END, Mode.RANK, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, 0, false); - TeamUser teamUser = new TeamUser(myTeam, newUser); - Team enemyTeam = new Team(game, 0, false); - User enemyUser = createNewUser(); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - PChange pChange1 = new PChange(game, newUser, 1100, true); - PChange pChange2 = new PChange(game, enemyUser, 900, true); - - pChangeRepository.save(pChange1); - pChangeRepository.save(pChange2); - } - - public Game createMockMatch(User newUser, Season season, LocalDateTime startTime, LocalDateTime endTime, Mode mode) { - Game game = new Game(season, StatusType.END, mode, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, 0, false); - TeamUser teamUser = new TeamUser(myTeam, newUser); - Team enemyTeam = new Team(game, 0, false); - User enemyUser = createNewUser(); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - PChange pChange1 = new PChange(game, newUser, 1100, true); - PChange pChange2 = new PChange(game, enemyUser, 900, true); - - pChangeRepository.save(pChange1); - pChangeRepository.save(pChange2); - return game; - } - - public Game createMockMatch(User newUser, Season season, LocalDateTime startTime, - LocalDateTime endTime, Mode mode, int myScore, int enemyScore) { - Game game = new Game(season, StatusType.END, mode, startTime, endTime); - gameRepository.save(game); - Team myTeam = new Team(game, myScore, myScore > enemyScore); - TeamUser teamUser = new TeamUser(myTeam, newUser); - Team enemyTeam = new Team(game, enemyScore, enemyScore > myScore); - User enemyUser = createNewUser(); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - PChange pChange1 = new PChange(game, newUser, 1100, true); - PChange pChange2 = new PChange(game, enemyUser, 900, true); - - pChangeRepository.save(pChange1); - pChangeRepository.save(pChange2); - return game; - } - - /** - *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

- * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @param status ํ† ๋„ˆ๋จผํŠธ ์ƒํƒœ - * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ - */ - public Tournament createTournament(LocalDateTime startTime, LocalDateTime endTime, TournamentStatus status) { - Tournament tournament = Tournament.builder() - .title("title") - .contents("contents") - .startTime(startTime) - .endTime(endTime) - .type(TournamentType.ROOKIE) - .status(status).build(); - return tournamentRepository.save(tournament); - } - - /** - * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. - * @param title ์ œ๋ชฉ - * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @param status ์ƒํƒœ - * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ - */ - public Tournament createTournament(String title, LocalDateTime startTime, LocalDateTime endTime, TournamentStatus status) { - Tournament tournament = Tournament.builder() - .title(title) - .contents("contents") - .startTime(startTime) - .endTime(endTime) - .type(TournamentType.ROOKIE) - .status(status).build(); - return tournamentRepository.save(tournament); - } - - /** - * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. - * @param title ์ œ๋ชฉ - * @param contents ๋‚ด์šฉ - * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @param type ํƒ€์ž… - * @param status ์ƒํƒœ - * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ - */ - public Tournament createTournament(String title, String contents, LocalDateTime startTime, LocalDateTime endTime, TournamentType type, TournamentStatus status) { - Tournament tournament = Tournament.builder() - .title(title) - .contents(contents) - .startTime(startTime) - .endTime(endTime) - .type(type) - .status(status).build(); - return tournamentRepository.save(tournament); - } - - /** - * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ์ƒ์„ฑ RequestDto ๋ฐ˜ํ™˜. - * @param startTime - * @param endTime - * @param type - * @return - */ - public TournamentAdminCreateRequestDto createRequestDto(LocalDateTime startTime, LocalDateTime endTime, TournamentType type) { - return new TournamentAdminCreateRequestDto( - "1st rookie tournament", - "welcome !", - startTime, - endTime, - type); - } - - /** - *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

- * @param tournamentType - * @param tournamentStatus - * @return - */ - public Tournament createTournamentByEnum(TournamentType tournamentType, TournamentStatus tournamentStatus, LocalDateTime startTime) { - Tournament tournament = Tournament.builder() - .title("testTournament") - .contents("contents") - .startTime(startTime) - .endTime(startTime.plusDays(1)) - .type(tournamentType) - .status(tournamentStatus).build(); - return tournamentRepository.save(tournament); - } - - /** - * ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ RequestDto ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™” - * @param startTime ์‹œ์ž‘ ์‹œ๊ฐ„ - * @param endTime ์ข…๋ฃŒ ์‹œ๊ฐ„ - * @param type ํ† ๋„ˆ๋จผํŠธ ์ข…๋ฅ˜ - * @return ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ RequestDto - */ - public TournamentAdminUpdateRequestDto createUpdateRequestDto(LocalDateTime startTime, LocalDateTime endTime, TournamentType type) { - return new TournamentAdminUpdateRequestDto( - "title", - "contents", - startTime, - endTime, - type); - } - - /** - *

ํ…Œ์ŠคํŠธ์šฉ ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜. ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’๋“ค๋งŒ ์ดˆ๊ธฐํ™”

- * @param tournament ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„์— ๋„ฃ์–ด ์ค„ ํ† ๋„ˆ๋จผํŠธ - * @param cnt ๋ฐ˜ํ™˜ ๋ฆฌ์ŠคํŠธ ํฌ๊ธฐ, 8๊ฐ•๊ธฐ์ค€ 7๊ฐœ - * @return ํ† ๋„ˆ๋จผํŠธ ๊ฒŒ์ž„ ๋ฆฌ์ŠคํŠธ - */ - public List createTournamentGameList(Tournament tournament, int cnt) { - List tournamentGameList = new ArrayList<>(); - TournamentRound [] values = TournamentRound.values(); - - while (--cnt >= 0) { - tournamentGameList.add(new TournamentGame(null, tournament, values[cnt])); - } - return tournamentGameRepository.saveAll(tournamentGameList); - } - - /** - *

ํ† ๋„ˆ๋จผํŠธ ์œ ์ € ์ƒ์„ฑ ๋ฐ ์ €์žฅ

- * @param user ํ† ๋„ˆ๋จผํŠธ ์ฐธ๊ฐ€ ์‹ ์ฒญ ์œ ์ € - * @param tournament ํ•ด๋‹น ํ† ๋„ˆ๋จผํŠธ - * @param isJoined ์ฐธ๊ฐ€์ž 1, ๋Œ€๊ธฐ์ž 0 - * @return - */ - public TournamentUser createTournamentUser(User user, Tournament tournament, boolean isJoined) { - TournamentUser tournamentUser = new TournamentUser(user, tournament, isJoined, LocalDateTime.now()); - return tournamentUserRepository.save(tournamentUser); - } - - public List makeTournamentList() { - int joinUserCnt = 8; - int notJoinUserCnt = 4; - List tournamentResponseDtos = new ArrayList<>(); - - User winner = createNewUser("winner_sgo", "winner@gmail.com", RacketType.PENHOLDER, SnsType.NONE, RoleType.USER); - UserImageDto winnerImage = new UserImageDto(winner); - for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { - User newUser = createNewUser("42gg_tester" + i, "tester" + i + "@gmail.com", RacketType.PENHOLDER, SnsType.NONE, RoleType.USER); - userRepository.save(newUser); - } - int day = 100; - for (TournamentType type : TournamentType.values()) { - for (TournamentStatus status : TournamentStatus.values()) { - for (int i = 0; i < 5; i++) { - Tournament tournament = createTournamentByEnum(type, status, LocalDateTime.now().plusDays(day++)); - tournamentResponseDtos.add(new TournamentResponseDto(tournament, winnerImage, joinUserCnt)); - tournament.updateWinner(winner); - for (int j = 0; j < joinUserCnt; j++) { - TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId("42gg_tester" + j).get(), tournament, true, LocalDateTime.now()); - tournamentUserRepository.save(tournamentUser); - tournament.getTournamentUsers().add(tournamentUser); - } - for (int j = joinUserCnt; j < joinUserCnt + notJoinUserCnt; j++) { - TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId("42gg_tester" + j).get(), tournament, false, LocalDateTime.now()); - tournamentUserRepository.save(tournamentUser); - tournament.getTournamentUsers().add(tournamentUser); - } - tournamentRepository.save(tournament); - } - } - } - tournamentResponseDtos.sort((o1, o2) -> o2.getStartTime().compareTo(o1.getStartTime())); - return tournamentResponseDtos; - } - - public Tournament createTournamentWithUser(int joinUserCnt, int notJoinUserCnt, String testName) { - Tournament tournament = Tournament.builder() - .title("testTournament") - .contents("contents") - .startTime(LocalDateTime.now()) - .endTime(LocalDateTime.now().plusDays(1)) - .type(TournamentType.ROOKIE) - .status(TournamentStatus.BEFORE).build(); - for (int i = 0; i < joinUserCnt + notJoinUserCnt; i++) { - User newUser = createNewUser(testName + i, "tester" + i + "@gmail.com", RacketType.PENHOLDER, SnsType.NONE, RoleType.USER); - userRepository.save(newUser); - } - for (int j = 0; j < joinUserCnt; j++) { - TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId(testName + j).get(), tournament, true, LocalDateTime.now()); - } - for (int j = joinUserCnt; j < joinUserCnt + notJoinUserCnt; j++) { - TournamentUser tournamentUser = new TournamentUser(userRepository.findByIntraId(testName + j).get(), tournament, false, LocalDateTime.now()); - } - return tournamentRepository.save(tournament); - } - - public TournamentGame createTournamentGame(Tournament tournament, TournamentRound round, GameInfoDto gameInfoDto) { - TournamentGame tournamentGame = new TournamentGame(gameRepository.findById(gameInfoDto.getGameId()).orElseThrow(GameNotExistException::new), tournament, round); - tournamentGameRepository.save(tournamentGame); - return tournamentGame; - } - - /** - * ํ‹ฐ์–ด ์ƒ์„ฑ - */ - public Tier createTier(String url) { - Tier tier = new Tier(url); - tierRepository.save(tier); - return tier; - } - - /** - * ํ˜„์žฌ ์‹œ์Šคํ…œ์— ๋งž๋Š” ํ‹ฐ์–ด 7๊ฐœ๋ฅผ ์ƒ์„ฑ - */ - public ArrayList createTierSystem(String url) { - ArrayList tiers = new ArrayList<>(); - for (int i = 0; i < 7; i++) { - Tier tier = new Tier(url + i); - tierRepository.save(tier); - tiers.add(tier); - } - return tiers; - } - - public GameInfoDto createGameWithTierAndRank(User curUser, LocalDateTime startTime, LocalDateTime endTime, Season season, Mode mode, Tier tier) { - LocalDateTime now = LocalDateTime.now(); - Game game; - if (now.isBefore(startTime)) - game = new Game(season, StatusType.BEFORE, mode, startTime, endTime); - else if (now.isAfter(startTime) && now.isBefore(endTime)) - game = new Game(season, StatusType.LIVE, mode, startTime, endTime); - else - game = new Game(season, StatusType.END, mode, startTime, endTime); - gameRepository.save(game); - - User enemyUser = createNewUser(); - Team myTeam = new Team(game, -1, false); - Team enemyTeam = new Team(game, -1, false); - TeamUser teamUser = new TeamUser(myTeam, curUser); - TeamUser enemyTeamUser = new TeamUser(enemyTeam, enemyUser); - createUserRank(curUser, "statusMessage", season, tier); - createUserRank(enemyUser, "enemyUserMeassage", season, tier); - teamRepository.save(myTeam); - teamRepository.save(enemyTeam); - teamUserRepository.save(teamUser); - teamUserRepository.save(enemyTeamUser); - - return new GameInfoDto(game.getId(), myTeam.getId(), curUser.getId(), enemyTeam.getId(), - enemyUser.getId()); - } - - public CoinPolicy createCoinPolicy(User user, int attendance, int normal, int rankWin, int rankLose) { - CoinPolicy coinPolicy = CoinPolicy.builder() - .user(user) - .attendance(attendance) - .normal(normal) - .rankWin(rankWin) - .rankLose(rankLose) - .build(); - coinPolicyRepository.save(coinPolicy); - return coinPolicy; - } - - public Announcement createAnnouncement(User creator, String content) { - Announcement announcement = Announcement.builder() - .creatorIntraId(creator.getIntraId()) - .content(content) - .build(); - announcementRepository.save(announcement); - return announcement; - } - - /** - * ๊ณต์ง€์‚ฌํ•ญ ์—ฌ๋Ÿฌ๊ฐœ ์ƒ์„ฑ. - * ๊ฐ€์žฅ ์ตœ์‹  ์ด์™ธ๋Š” ๊ฐฑ์‹ ์ฒ˜๋ฆฌ. - * - * @param creator - * @param cnt - * @return ์ƒ์„ฑ๋œ ๊ณต์ง€์‚ฌํ•ญ ๋ฆฌ์ŠคํŠธ - */ - public ArrayList createAnnouncements(User creator, int cnt) { - return IntStream.range(0, cnt) - .mapToObj(i -> { - Announcement announcement = createAnnouncement(creator, "content" + i); - if (i != cnt - 1) announcement.update(creator.getIntraId(), LocalDateTime.now()); - return announcement; - }) - .collect(Collectors.toCollection(ArrayList::new)); - } - - public UserImage createUserImage(User user) { - UserImage userImage = new UserImage(user, "testUrl", - LocalDateTime.now(), null, true); - userImageRepository.save(userImage); - return userImage; - } - - public ArrayList createUserImages(User user, int cnt) { - return IntStream.range(0, cnt) - .mapToObj(i -> { - UserImage userImage = createUserImage(user); - if (i != cnt - 1) userImage.updateDeletedAt(LocalDateTime.now()); - return userImage; - }) - .collect(Collectors.toCollection(ArrayList::new)); - } - - public List createUsers(int cnt) { - List users = new ArrayList<>(); - for (int i = 0; i < cnt; i++) { - users.add(createNewUser("testUser" + i, "testUser" + i + "@gmail.com", RacketType.PENHOLDER, SnsType.NONE, RoleType.USER)); - } - userRepository.saveAll(users); - return users; - } - - public SlotManagement createSlotManagement(Integer interval) { - SlotManagement slotManagement = SlotManagement.builder() - .futureSlotTime(12) - .pastSlotTime(5) - .gameInterval(interval) - .openMinute(5) - .startTime(LocalDateTime.now().minusHours(2)) - .build(); - slotManagementRepository.save(slotManagement); - return slotManagement; - } - - public SlotManagement createSlot(int gameInterval) { - SlotManagement slotManagement = SlotManagement.builder() - .pastSlotTime(0) - .futureSlotTime(0) - .openMinute(0) - .gameInterval(gameInterval) - .startTime(LocalDateTime.now().minusHours(1)) - .build(); - return slotManagementRepository.save(slotManagement); - } -} diff --git a/src/test/java/com/gg/server/utils/annotation/IntegrationTestAspect.java b/src/test/java/com/gg/server/utils/annotation/IntegrationTestAspect.java deleted file mode 100644 index e3c467f6d..000000000 --- a/src/test/java/com/gg/server/utils/annotation/IntegrationTestAspect.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gg.server.utils.annotation; - -import com.gg.server.domain.rank.redis.RankRedisRepository; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.After; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Aspect -@Component -public class IntegrationTestAspect { - - @Autowired - private RankRedisRepository rankRedisRepository; - - /** - * ํ†ตํ•ฉํ…Œ์ŠคํŠธ ์ข…๋ฃŒ ํ›„ redis ๋ฐ์ดํ„ฐ ์‚ญ์ œ - */ - @After("execution(* *(..)) && @within(integrationTest)") - public void afterTest(JoinPoint joinPoint, IntegrationTest integrationTest) { - rankRedisRepository.deleteAll(); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/utils/annotation/TestTypeConstant.java b/src/test/java/com/gg/server/utils/annotation/TestTypeConstant.java deleted file mode 100644 index c0d89cc16..000000000 --- a/src/test/java/com/gg/server/utils/annotation/TestTypeConstant.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.utils.annotation; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * TestType. - * - *

- * Tag ์—์„œ ์‚ฌ์šฉํ•  ํ…Œ์ŠคํŠธ ํƒ€์ž…์„ ์ •์˜ - *

- * - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class TestTypeConstant { - public static final String UNIT_TEST = "UnitTest"; - public static final String INTEGRATION_TEST = "IntegrationTest"; -} diff --git a/src/test/java/com/gg/server/utils/annotation/UnitTest.java b/src/test/java/com/gg/server/utils/annotation/UnitTest.java deleted file mode 100644 index 9a2dd50df..000000000 --- a/src/test/java/com/gg/server/utils/annotation/UnitTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.gg.server.utils.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.junit.jupiter.api.Tag; - -/** - * Unit ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜ - * - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Tag(TestTypeConstant.UNIT_TEST) -public @interface UnitTest { - -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/utils/config/MySQLInitializer.java b/src/test/java/com/gg/server/utils/config/MySQLInitializer.java deleted file mode 100644 index 1f4fde72e..000000000 --- a/src/test/java/com/gg/server/utils/config/MySQLInitializer.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.gg.server.utils.config; - -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.testcontainers.containers.MySQLContainer; - -/** - * MysqlInitializer. - * - *

- * mysql testContainer ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ - *

- * - * @author : middlefitting - * @since : 2024/01/09 - */ -public class MySQLInitializer implements - ApplicationContextInitializer { - private static final String params = "?serverTimezone=Asia/Seoul&characterEncoding=UTF-8"; - private static final MySQLContainer MYSQL_CONTAINER = - new MySQLContainer<>("mysql:8.0") - .withDatabaseName("test") - .withUsername("root") - .withPassword("1234"); - - static { - MYSQL_CONTAINER.start(); - } - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - TestPropertyValues.of( - "spring.datasource.url=" + MYSQL_CONTAINER.getJdbcUrl() + params, - "spring.datasource.username=" + MYSQL_CONTAINER.getUsername(), - "spring.datasource.password=" + MYSQL_CONTAINER.getPassword() - ).applyTo(applicationContext.getEnvironment()); - } -} diff --git a/src/test/java/com/gg/server/utils/config/RedisInitializer.java b/src/test/java/com/gg/server/utils/config/RedisInitializer.java deleted file mode 100644 index 5ecd919e3..000000000 --- a/src/test/java/com/gg/server/utils/config/RedisInitializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gg.server.utils.config; - -import com.redis.testcontainers.RedisContainer; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.testcontainers.utility.DockerImageName; - -public class RedisInitializer implements - ApplicationContextInitializer { - private static final RedisContainer REDIS_CONTAINER = - new RedisContainer(DockerImageName.parse("redis:5.0.3-alpine")) - .withExposedPorts(6379); - - static { - REDIS_CONTAINER.start(); - } - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - TestPropertyValues.of( - "spring.redis.host=" + REDIS_CONTAINER.getHost(), - "spring.redis.port=" + REDIS_CONTAINER.getMappedPort(6379) - ).applyTo(applicationContext.getEnvironment()); - } -} \ No newline at end of file diff --git a/src/test/java/com/gg/server/utils/config/TestRedisConfig.java b/src/test/java/com/gg/server/utils/config/TestRedisConfig.java deleted file mode 100644 index 7e25e77c4..000000000 --- a/src/test/java/com/gg/server/utils/config/TestRedisConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gg.server.utils.config; - -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; - -/** - * TestRedisConfig. - * - *

- * ํ…Œ์ŠคํŠธ์—์„œ redis Transaction์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ ์„ค์ • - * ํ•ด๋‹น ๋นˆ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ฐ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค redis ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™” ํ•„์š” - *

- */ -@TestConfiguration -public class TestRedisConfig { - - @Primary - @Bean(name = "testRedisTemplate") - public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { - final RedisTemplate redisTemplate = new RedisTemplate<>(); - - redisTemplate.setConnectionFactory(redisConnectionFactory); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - - redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer()); - redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); - redisTemplate.setEnableTransactionSupport(false); - - return redisTemplate; - } -}