diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07a0459 --- /dev/null +++ b/.gitignore @@ -0,0 +1,118 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +## Config file +/src/main/resources/*.yaml +/src/main/resources/*.yml + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +log/ +src/main/resources/appender \ No newline at end of file diff --git a/README.md b/README.md index f0820ef..23b5043 100644 --- a/README.md +++ b/README.md @@ -1 +1,115 @@ -# HisPath-Server \ No newline at end of file +# HisPath : 학생 교육 역량 평가 및 마일스톤 서비스 + +## 🤟 HisPath란? + +학생의 활동들을 학교 관계자와 학생이 포트폴리오로 편리하게 관리할 수 있도록 도와주는 **매개체 역할**을 합니다. 학생은 본인의 포트폴리오를 편리하게 관리하고, 관리자는 학생들의 활동 이력으로 학생을 분석, 평가, 관리하는 웹 서비스입니다. + +[HisPath 1분소개 영상](https://youtu.be/gUDZRBHC4tw) + +## 📝 HisPath의 필요성 + +졸업을 압둔 학생들이 여태 취업 준비를 위해 이력서를 쓴다고 하면 제일 먼저 하는 고민이 내가 **"지금까지 어떠한 활동을 했는가"** 입니다. 이러한 고민은 결국 자신이 학교를 다니면서 한 활동들이 잊혀지거나 기록으로 남지 않아 자기소개서와 포트폴리오를 작성할 때 쓸 내용이 없어서 발생합니다. + +따라서 이러한 문제들을 해결하여 학생들에게 포트폴리오 관리 및 이력서 작성의 편의성을 제공하기 위해 디자인한 서비스 입니다. + +## 😄 기대 효과 + +1️⃣ 기존 학생의 활동 정보 및 장학금 수혜 **정보를 능동적으로 활용**하여 **학생들의 포트폴리오 관리에 편리함** 제공 + +2️⃣ **포트폴리오 관리 및 이력서 작성 기능** 한번에 제공 + +3️⃣ **다양한 차트**를 통해 학생, 학생 활동, 장학금 내역 등 **데이터 조회의 편의성 및 분석** 제공 + +4️⃣ 학생, 관리자, 전공, 학부, 학생 활동, 참여 여부 등 **다양한 정보 관리에 편의성** 제공 + +## 🧑‍🤝‍🧑 Member + +| ![](https://github.com/gomster96.png) | ![](https://github.com/davidpiao.png) | ![](https://github.com/lukehongg.png) | ![](https://github.com//shinel98.png) | ![](https://github.com/shine-jung.png) | ![](https://github.com/songdabin.png) | +| :-----------------------------------: | :-----------------------------------: | :-----------------------------------: | :-----------------------------------: | :------------------------------------: | :-----------------------------------: | +| **안병웅(팀장)** | **박성진** | **홍성헌** | **이인혁** | **정석민** | **송다빈** | +| **BackEnd** | **Full-Stack** | **Full-Stack** | **Full-Stack** | **FrontEnd** | **FrontEnd** | . | + +## 🔧 기술스택 + + + +## ⌨️ Code + +- 전체 서비스 Back End: https://github.com/HisPath/HisPath-Server +- 학생 서비스 Front End: https://github.com/HisPath/HisPath-Student +- 관리자 서비스 Front End : https://github.com/HisPath/HisPath-Manager + +## 💻 데모영상 +https://www.youtube.com/watch?v=3CG4rbCgE8s + +## 📐 구현 구조 + +image + +## ✌️ ERD + +image + +## 🖌️ Service Design + +image + +## 🎁 Service Introduction + +![안병웅박성진_캡스톤발표자료 (1)_006](https://user-images.githubusercontent.com/80206884/210240205-27e4d572-2913-481b-b6ee-eadf08af24d0.jpg) +![안병웅박성진_캡스톤발표자료 (1)_007](https://user-images.githubusercontent.com/80206884/210240213-19452899-666f-4e85-abe4-55b24488f748.jpg) +![안병웅박성진_캡스톤발표자료 (1)_008](https://user-images.githubusercontent.com/80206884/210240215-94bb0c16-1247-444f-b2bb-6ee8d6fb95f6.jpg) +![안병웅박성진_캡스톤발표자료 (1)_009](https://user-images.githubusercontent.com/80206884/210240220-a14b7a92-589f-48b2-a59d-dfa070ffeef1.jpg) +![안병웅박성진_캡스톤발표자료 (1)_010](https://user-images.githubusercontent.com/80206884/210240222-62f30b8a-a205-41b4-8623-d90b2f0dfdf7.jpg) +![안병웅박성진_캡스톤발표자료 (1)_011](https://user-images.githubusercontent.com/80206884/210240223-abeae6a6-567a-42ba-9717-1298242468a3.jpg) +![안병웅박성진_캡스톤발표자료 (1)_012](https://user-images.githubusercontent.com/80206884/210240225-d2a99f4c-191f-4fc7-9b09-ca21041dee6a.jpg) +![안병웅박성진_캡스톤발표자료 (1)_013](https://user-images.githubusercontent.com/80206884/210240229-0bd07665-dace-4638-96df-601f877b7c16.jpg) +![안병웅박성진_캡스톤발표자료 (1)_014](https://user-images.githubusercontent.com/80206884/210240230-bcb28ab5-6c89-4035-b443-3b2f71d12758.jpg) +![안병웅박성진_캡스톤발표자료 (1)_015](https://user-images.githubusercontent.com/80206884/210240232-d31f8ee4-f6f8-4a4c-96b4-9fa90f4ed748.jpg) +![안병웅박성진_캡스톤발표자료 (1)_016](https://user-images.githubusercontent.com/80206884/210240236-02ea269e-3294-4893-b1e2-adb836583d86.jpg) +![안병웅박성진_캡스톤발표자료 (1)_017](https://user-images.githubusercontent.com/80206884/210240239-fb3f6e68-8c65-41c1-aa8d-b1400824e603.jpg) +![안병웅박성진_캡스톤발표자료 (1)_018](https://user-images.githubusercontent.com/80206884/210240241-9ec178c6-39c7-4c94-b1c4-56c004e08ade.jpg) +![안병웅박성진_캡스톤발표자료 (1)_019](https://user-images.githubusercontent.com/80206884/210240242-819eb14c-2908-446b-8091-0e207726744c.jpg) +![안병웅박성진_캡스톤발표자료 (1)_020](https://user-images.githubusercontent.com/80206884/210240246-098300b5-144b-4587-8ab7-52a2d2d641d3.jpg) +![안병웅박성진_캡스톤발표자료 (1)_021](https://user-images.githubusercontent.com/80206884/210240250-04e08d04-5f02-4f65-9ff4-ee3dbf11f735.jpg) +![안병웅박성진_캡스톤발표자료 (1)_022](https://user-images.githubusercontent.com/80206884/210240254-42615b61-d951-4da6-868c-96a10145bcc7.jpg) +![안병웅박성진_캡스톤발표자료 (1)_023](https://user-images.githubusercontent.com/80206884/210240255-d7f85998-fe4c-48ce-8b32-0c6fd30cb293.jpg) +![안병웅박성진_캡스톤발표자료 (1)_024](https://user-images.githubusercontent.com/80206884/210240257-7b2453d2-bffa-4a19-817b-1bc7af19c77e.jpg) +![안병웅박성진_캡스톤발표자료 (1)_025](https://user-images.githubusercontent.com/80206884/210240259-94f78d65-791c-4599-bdee-db719ed314d5.jpg) +![안병웅박성진_캡스톤발표자료 (1)_026](https://user-images.githubusercontent.com/80206884/210240262-ba9b4855-fdbb-406b-9acb-869c4a86f77b.jpg) +![안병웅박성진_캡스톤발표자료 (1)_027](https://user-images.githubusercontent.com/80206884/210240263-4242df45-337d-4b79-a4e6-c8edc7341f22.jpg) +![안병웅박성진_캡스톤발표자료 (1)_028](https://user-images.githubusercontent.com/80206884/210240265-322f78a7-332b-425d-8f1e-f2b768aba566.jpg) +![안병웅박성진_캡스톤발표자료 (1)_029](https://user-images.githubusercontent.com/80206884/210240266-4d4bc509-31ea-4296-b1e9-7c5bd3ebb542.jpg) +![안병웅박성진_캡스톤발표자료 (1)_030](https://user-images.githubusercontent.com/80206884/210240268-5fcfd0ac-bdd5-4c54-af1d-e1de3539c226.jpg) +![안병웅박성진_캡스톤발표자료 (1)_031](https://user-images.githubusercontent.com/80206884/210240272-754601ce-16bd-468a-960d-95081f8c4690.jpg) +![안병웅박성진_캡스톤발표자료 (1)_032](https://user-images.githubusercontent.com/80206884/210240277-e6063842-7ff0-46c1-b326-ec0a4f14dea6.jpg) +![안병웅박성진_캡스톤발표자료 (1)_033](https://user-images.githubusercontent.com/80206884/210240279-6fe8ee61-0df6-4d34-841f-52612dc30134.jpg) +![안병웅박성진_캡스톤발표자료 (1)_034](https://user-images.githubusercontent.com/80206884/210240280-a81aca72-61c4-4c16-b6d2-6ee616fb502e.jpg) +![안병웅박성진_캡스톤발표자료 (1)_035](https://user-images.githubusercontent.com/80206884/210240281-d6c9aba7-77ef-4b58-99d6-21a6e1ae12ae.jpg) + + + + +## 🔎 기술 설명 + +![안병웅박성진_캡스톤발표자료 (1)_040](https://user-images.githubusercontent.com/80206884/210241017-34b06259-8cff-4f30-8e13-4dbf4b091b61.jpg) +![안병웅박성진_캡스톤발표자료 (1)_041](https://user-images.githubusercontent.com/80206884/210241024-d83efad1-ac9d-44fd-8dc4-b1ce20f68fdc.jpg) +![안병웅박성진_캡스톤발표자료 (1)_042](https://user-images.githubusercontent.com/80206884/210241026-ed4ea227-f3d9-43cd-aa7e-1a38969344ef.jpg) +![안병웅박성진_캡스톤발표자료 (1)_043](https://user-images.githubusercontent.com/80206884/210241029-5d8d28bb-0911-4b7d-9ba7-4f4a87ba64da.jpg) +![안병웅박성진_캡스톤발표자료 (1)_044](https://user-images.githubusercontent.com/80206884/210241031-498ad24a-cd33-4433-94ca-3cc58bed64e3.jpg) +![안병웅박성진_캡스톤발표자료 (1)_045](https://user-images.githubusercontent.com/80206884/210241033-41992c52-dd29-45fa-bfa0-b3b6e3f2ad81.jpg) +![안병웅박성진_캡스톤발표자료 (1)_046](https://user-images.githubusercontent.com/80206884/210241035-3524ea11-6b49-41f0-b0aa-ccc626971097.jpg) +![안병웅박성진_캡스톤발표자료 (1)_047](https://user-images.githubusercontent.com/80206884/210241037-f4805384-e4e6-46d9-aa93-032d272a0a55.jpg) +![안병웅박성진_캡스톤발표자료 (1)_048](https://user-images.githubusercontent.com/80206884/210241043-85f860b0-696d-42c4-a8c7-faf821d34f9f.jpg) +![안병웅박성진_캡스톤발표자료 (1)_049](https://user-images.githubusercontent.com/80206884/210241045-00b865eb-4454-41a6-82a2-1db98ecf9487.jpg) +![안병웅박성진_캡스톤발표자료 (1)_050](https://user-images.githubusercontent.com/80206884/210241047-1398a388-8888-498f-a540-5ad2dabd9b8f.jpg) +![안병웅박성진_캡스톤발표자료 (1)_051](https://user-images.githubusercontent.com/80206884/210241048-b95ae314-b83f-42a2-9e6f-46eb3b93dce7.jpg) + + +## 🙋‍♂️ 협업 + +![안병웅박성진_캡스톤발표자료 (1)_052](https://user-images.githubusercontent.com/80206884/210241246-007ad0fd-03ab-43e4-8a70-718eb0486aa0.jpg) +![안병웅박성진_캡스톤발표자료 (1)_053](https://user-images.githubusercontent.com/80206884/210241255-e059ce6f-946f-4a5c-a8f1-396d714693f0.jpg) +![안병웅박성진_캡스톤발표자료 (1)_054](https://user-images.githubusercontent.com/80206884/210241257-14509c51-6d95-49b9-ba23-b14646084d0d.jpg) +![안병웅박성진_캡스톤발표자료 (1)_055](https://user-images.githubusercontent.com/80206884/210241258-101387fa-9aba-44f0-9f71-a37eff46cd42.jpg) + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..15028db --- /dev/null +++ b/build.gradle @@ -0,0 +1,53 @@ +plugins { + id 'org.springframework.boot' version '2.5.3' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' +} + +group = 'com.server' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '11' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'io.springfox:springfox-boot-starter:3.0.0' + implementation 'ca.pjer:logback-awslogs-appender:1.6.0' + implementation group: 'org.apache.poi', name: 'poi', version: '4.1.2' + implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '4.1.2' + implementation group: 'commons-io', name: 'commons-io', version: '2.4' + implementation 'org.springframework.boot:spring-boot-configuration-processor' + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation("io.netty:netty-resolver-dns-native-macos:4.1.75.Final:osx-aarch_64") + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'mysql:mysql-connector-java' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + implementation 'com.querydsl:querydsl-jpa:5.0.0' + annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jpa" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + implementation "com.querydsl:querydsl-core:5.0.0" + clean { + delete file('src/main/generated') + } + implementation 'ca.pjer:logback-awslogs-appender:1.6.0' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..249e583 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..8049c68 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..a69d9cb --- /dev/null +++ b/gradlew @@ -0,0 +1,240 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..53a6b23 --- /dev/null +++ b/gradlew.bat @@ -0,0 +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 diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..8bebd46 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hispath' diff --git a/src/main/java/com/server/hispath/HispathApplication.java b/src/main/java/com/server/hispath/HispathApplication.java new file mode 100644 index 0000000..d1bf399 --- /dev/null +++ b/src/main/java/com/server/hispath/HispathApplication.java @@ -0,0 +1,14 @@ +package com.server.hispath; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@SpringBootApplication +@EnableJpaAuditing +public class HispathApplication { + + public static void main(String[] args) { + SpringApplication.run(HispathApplication.class, args); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/ActivityService.java b/src/main/java/com/server/hispath/activity/application/ActivityService.java new file mode 100644 index 0000000..e2f4b87 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/ActivityService.java @@ -0,0 +1,280 @@ +package com.server.hispath.activity.application; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.dto.*; +import com.server.hispath.activity.application.dto.chart.ChartCategoryDto; +import com.server.hispath.activity.application.dto.chart.ChartDataDto; +import com.server.hispath.activity.application.dto.chart.ChartSectionCntDto; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.activity.domain.repository.ActivityRepository; +import com.server.hispath.activity.domain.repository.ActivityRepositoryCustom; +import com.server.hispath.activity.presentation.response.chart.ChartSectionResponse; +import com.server.hispath.category.application.CategoryService; +import com.server.hispath.category.domain.Category; +import com.server.hispath.category.domain.repository.CategoryRepository; +import com.server.hispath.exception.activity.ActivityNotFoundException; +import com.server.hispath.exception.activity.ParticipantNotFoundException; +import com.server.hispath.exception.student.StudentNotFoundException; +import com.server.hispath.student.domain.Participant; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; +import com.server.hispath.student.domain.repository.StudentRepositoryCustom; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ActivityService { + + private final ActivityRepository activityRepository; + private final CategoryService categoryService; + private final CategoryRepository categoryRepository; + private final StudentRepository studentRepository; + private final StudentRepositoryCustom studentRepositoryCustom; + private final ActivityRepositoryCustom activityRepositoryCustom; + + @Transactional + public Long create(Long categoryId, ActivityContentDto dto) { + Category category = categoryService.findById(categoryId); + Activity activity = Activity.from(category, dto); + Activity savedActivity = activityRepository.save(activity); + return savedActivity.getId(); + } + + @Transactional(readOnly = true) + public ActivityDto find(Long id) { + Activity activity = this.findById(id); + return ActivityDto.from(activity); + } + + + @Transactional(readOnly = true) + public List findAll() { + List activities = activityRepository.findAll(); + return activities.stream() + .map(ActivityDto::from) + .collect(Collectors.toList()); + } + + @Transactional + public ActivityDto update(Long id, Long categoryId, ActivityContentDto dto) { + Activity activity = this.findById(id); + Category category = categoryService.findById(categoryId); + activity.update(category, dto); + + return ActivityDto.from(activity); + } + + @Transactional + public void delete(Long activityId) { + activityRepository.deleteById(activityId); + } + + @Transactional + public void deleteStudentActivity(Long studentId, Long activityId) { + Activity activity = activityRepository.findActivityWithStudents(activityId) + .orElseThrow(ActivityNotFoundException::new); + Student student = studentRepository.findById(studentId) + .orElseThrow(StudentNotFoundException::new); + if (activity.isPersonal()) { + activityRepository.deleteById(activityId); + return; + } + activity.getParticipants() + .stream() + .filter(participant -> participant.isSameStudent(student)) + .findFirst() + .orElseThrow(ParticipantNotFoundException::new) + .deleteContent(); + } + + @Transactional(readOnly = true) + public List bringSemester() { + List semesters = activityRepository.bringSemester(); + return semesters.stream() + .map(SemesterDto::from) + .collect(Collectors.toList()); + + } + + @Transactional + public Long createStudentActivity(Long studentId, + StudentActivityContentDto activityContentDto, + ParticipantContentDto participantContentDto) { + + Student student = studentRepository.findById(studentId).orElseThrow(StudentNotFoundException::new); + Category category = categoryRepository.findByName("기타"); + Activity activity = Activity.from(activityContentDto, category); + activity.addParticipant(student, participantContentDto); + return activityRepository.save(activity).getId(); + } + + @Transactional + public ActivityParticipantDto updateStudentActivity(Long activityId, Long studentId, + StudentActivityContentDto activityContentDto, + ParticipantContentDto participantContentDto) { + + Activity activity = this.findById(activityId); + activity.update(activityContentDto); + Student student = studentRepository.findById(studentId).orElseThrow(StudentNotFoundException::new); + Participant updatedParticipant = activity.getParticipants() + .stream() + .filter(participant -> participant.isSameStudent(student)) + .findFirst() + .orElseThrow(ParticipantNotFoundException::new); + updatedParticipant.update(participantContentDto); + return ActivityParticipantDto.of(updatedParticipant); + } + + @Transactional(readOnly = true) + public List findAllParticipantActivites(Long studentId, String semester, String section) { + Student student = studentRepository.findStudentWithActivities(studentId) + .orElseThrow(StudentNotFoundException::new); + return student.getParticipants() + .stream() + .filter(participant -> participant.isSameSemester(semester)) + .filter(participant -> participant.isSameSection(section)) + .map(ActivityParticipantDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List findRecentParticipantActivities(Long studentId) { + + Student student = studentRepository.findStudentWithActivities(studentId) + .orElseThrow(StudentNotFoundException::new); + List dtos = student.getParticipants() + .stream() + .sorted((p1, p2) -> p2.getUpdatedAt() + .compareTo(p1.getUpdatedAt())) + .map(ActivityParticipantDto::of) + .collect(Collectors.toList()); + if (dtos.size() > 6) { + return dtos.subList(0, 6); + } + return dtos; + } + + @Transactional(readOnly = true) + public List findAllPersonalParticipantActivites(Long id, String semester, String section) { + Student student = studentRepository.findStudentWithActivities(id).orElseThrow(StudentNotFoundException::new); + return student.getParticipants() + .stream() + .filter(participant -> participant.isSameSemester(semester)) + .filter(participant -> participant.isSameSection(section)) + .filter(Participant::isPersonal) + .map(ActivityParticipantDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public ActivityParticipantDto findParticipantActivityById(Long studentId, Long activityId) { + Activity activity = activityRepository.findActivityWithStudents(activityId) + .orElseThrow(ActivityNotFoundException::new); + Student student = studentRepository.findById(studentId) + .orElseThrow(StudentNotFoundException::new); + Participant participant = activity.getParticipants() + .stream() + .filter(p -> p.isSameStudent(student)) + .findFirst() + .orElseThrow(ParticipantNotFoundException::new); + return ActivityParticipantDto.of(participant); + + } + + @Transactional(readOnly = true) + public List findAllByStudentAndSemster(Long id, String semester) { + Student student = findStudentWholeByIdAndSemester(id, semester, false); + + return student.getParticipants() + .stream() + .map(participant -> ActivityDto.from(participant.getActivity())) + .collect(Collectors.toList()); + } + + @Transactional + public void apply(Long activityId) { + this.findById(activityId).apply(); + } + + @Transactional + public void approve(Long activityId, int weight) { + this.findById(activityId).approve(weight); + } + + @Transactional + public void reject(Long activityId) { + this.findById(activityId).reject(); + } + + + @Transactional(readOnly = true) + public List getChartDatasByCategory(Long studentId, ChartSearchRequestDto dto) { + Student student = studentRepository.findById(studentId).orElseThrow(StudentNotFoundException::new); + List studentCnts = activityRepositoryCustom.getStudentCategoryParticipateCnt(student, dto); + List totalCnts = activityRepositoryCustom.getTotalCategoryParticipateCnt(dto); + int totalStudentCnt = activityRepositoryCustom.getTotalStudentCntByChartSearchRequest(dto); + + return totalCnts.stream() + .map(totalCnt -> + studentCnts.stream() + .filter(studentCnt -> studentCnt.isSameCategory(totalCnt.getCategory())) + .findFirst() + .map(studentCnt -> new ChartDataDto(studentCnt, totalCnt.getCnt(), totalStudentCnt)) + .orElseGet(() -> new ChartDataDto(totalCnt.getCategory(), totalCnt.getCnt(), totalStudentCnt)) + ) + .collect(Collectors.toList()); + + } + + @Transactional(readOnly = true) + public List getChartTotalDatasByCategory(Long studentId, ChartSearchRequestDto dto) { + List chartDataDtos = this.getChartDatasByCategory(studentId, dto); + + List activityCntDtos = activityRepositoryCustom.getActivityCntByCategoryAndSemester(dto); + + return chartDataDtos.stream() + .map(chartDataDto -> + activityCntDtos.stream() + .filter(activityCntDto -> activityCntDto.isSameCategory(chartDataDto.getCategory())) + .findFirst() + .map(activityCntDto -> new ChartCategoryDto(chartDataDto, activityCntDto.getCnt())) + .orElseThrow(ActivityNotFoundException::new)) + .filter(ChartCategoryDto::isNotETC) + .collect(Collectors.toList()); + + } + + @Transactional(readOnly = true) + public List getChartTotalDatasBySections(Long studentId, String semester) { + ChartSearchRequestDto dto = ChartSearchRequestDto.builder().semester(semester).build(); + List studentCnts = activityRepositoryCustom.getPersonalChartSectionCnts(studentId, dto); + List totalCnts = activityRepositoryCustom.getTotalChartSectionCnts(dto); + int totalStudentCnt = activityRepositoryCustom.getTotalStudentCntByChartSearchRequest(dto); + + return totalCnts.stream() + .map(totalCnt -> { + return studentCnts.stream() + .filter(studentCnt -> studentCnt.isSameSection(totalCnt.getSection())) + .findFirst() + .map(studentCntDto -> new ChartSectionResponse(totalCnt.getSection(), studentCntDto.getCnt(), totalCnt.getCnt() / (double) totalStudentCnt)) + .orElseGet(() -> new ChartSectionResponse(totalCnt.getSection(), 0L, totalCnt.getCnt() / (double) totalStudentCnt)); + }) + .collect(Collectors.toList()); + + } + + private Student findStudentWholeByIdAndSemester(Long studentId, String semester, boolean isMileage) { + return studentRepositoryCustom.findStudentWithIdAndSemester(studentId, semester, isMileage) + .orElseThrow(StudentNotFoundException::new); + } + + public Activity findById(Long id) { + return activityRepository.findById(id).orElseThrow(ActivityNotFoundException::new); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/MActivityService.java b/src/main/java/com/server/hispath/activity/application/MActivityService.java new file mode 100644 index 0000000..cd222b2 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/MActivityService.java @@ -0,0 +1,156 @@ +package com.server.hispath.activity.application; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.dto.*; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.activity.domain.repository.ActivityRepository; +import com.server.hispath.category.application.CategoryService; +import com.server.hispath.category.domain.Category; +import com.server.hispath.common.BaseEntity; +import com.server.hispath.exception.activity.ActivityNotFoundException; +import com.server.hispath.exception.activity.ParticipantNotFoundException; +import com.server.hispath.exception.student.StudentNotFoundException; +import com.server.hispath.student.application.dto.StudentRefDetailDto; +//import com.server.hispath.student.domain.Inhyok; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MActivityService { + private final ActivityRepository activityRepository; + private final CategoryService categoryService; + private final ActivityService activityService; + private final StudentRepository studentRepository; + + @Transactional + public Long create(MActivityContentDto dto) { + Category category = categoryService.findById(dto.getCategoryId()); + Activity activity = Activity.from(category, dto); + Activity savedActivity = activityRepository.save(activity); + return savedActivity.getId(); + } + + @Transactional + public void createAll(List dtos) { + List activities = dtos.stream() + .map(dto -> { + Category category = categoryService.findById(dto.getCategoryId()); + return Activity.from(category, dto); + }).collect(Collectors.toList()); + activityRepository.saveAll(activities); + } + + @Transactional + public ActivityDto update(Long id, MActivityContentDto dto) { + Activity activity = activityService.findById(id); + Category category = categoryService.findById(dto.getCategoryId()); + activity.update(category, dto); + return ActivityDto.from(activity); + } + + @Transactional(readOnly = true) + public List findAllBySemester(String semester) { + List activities = activityRepository.findAllBySemesterAndRequestStatus(semester, 1); + return activities.stream() + .map(ActivityDto::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List findAll() { + List activities = activityRepository.findAllByRequestStatus(1); + return activities.stream() + .map(ActivityDto::from) + .collect(Collectors.toList()); + } + + @Transactional + public void deleteAllParticipant(Activity activity) { + activity.getParticipants().forEach(BaseEntity::deleteContent); + } + + @Transactional + public MActivityDetailDto findDetailActivityInfo(Long activityId) { + Activity activity = activityRepository.findActivityWithStudents(activityId) + .orElseThrow(ActivityNotFoundException::new); + List students = activity.getParticipants() + .stream() + .map(participant -> { + return StudentRefDetailDto.of(participant.getStudent()); + }) + .collect(Collectors.toList()); + return MActivityDetailDto.from(activity, students); + } + + @Transactional + public MStudentActivityDetailDto findActivitiesByStudent(Long studentId) { + Student student = studentRepository.findActivitiesByStudent(studentId) + .orElseThrow(StudentNotFoundException::new); + List activities = student.getParticipants() + .stream() + .map(participant -> { + return ActivityDto.from(participant.getActivity()); + }) + .collect(Collectors.toList()); + + return MStudentActivityDetailDto.from(student, activities); + } + + @Transactional + public void deleteParticipant(Long studentId, Long activityId) { + Student student = studentRepository.findById(studentId).orElseThrow(StudentNotFoundException::new); + Activity activity = activityService.findById(activityId); + activity.getParticipants() + .stream() + .filter(participant -> participant.isSameStudent(student)) + .findFirst() + .orElseThrow(ParticipantNotFoundException::new) + .deleteContent(); + } + + @Transactional + public List findSemestersById(Long studentId) { + Student student = studentRepository.findActivitiesByStudent(studentId).orElseThrow(StudentNotFoundException::new); + List semesters = student.getParticipants() + .stream().map(participant -> {return SemesterDto.from(participant.getActivity().getSemester());}).distinct().collect(Collectors.toList()); + return semesters; + } + + + + @Transactional(readOnly = true) + public ListfindAllParticipantActivities(Long id, String semester, String category) { + Student student = studentRepository.findStudentWithMActivities(id).orElseThrow(StudentNotFoundException::new); + return student.getParticipants() + .stream() + .filter(participant -> participant.isSameSemester(semester)) + .filter(participant -> participant.isSameCategory(category)) + .map(MActivityParticipantDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public ListfindParticipatedActivities(Long id, String semester, String category) { + List activities = activityRepository.findParticipatedActivity(); + Student student = studentRepository.findById(id).orElseThrow(StudentNotFoundException::new); + List collect = + activities.stream() + .filter(activity -> activity.isSameSemester(semester) && activity.isSameCategory(category)) + .map(activity -> { + return AllMActivityParticipantDto.of(activity, activity.isParticipate(student)); + }) + .collect(Collectors.toList()); + + return collect; + + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ActivityContentDto.java b/src/main/java/com/server/hispath/activity/application/dto/ActivityContentDto.java new file mode 100644 index 0000000..b8a4a73 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ActivityContentDto.java @@ -0,0 +1,29 @@ +package com.server.hispath.activity.application.dto; + +import java.time.LocalDateTime; + +import com.server.hispath.activity.presentation.request.ActivityCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityContentDto { + + private String semester; + private boolean personal; + private int requestStatus; + private String name; + private String remark; + private int weight; + + public static ActivityContentDto from(ActivityCURequest request) { + return new ActivityContentDto(request.getSemester(), request.isPersonal(), request.getRequestStatus(), + request.getName(), request.getRemark(), request.getWeight()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ActivityDto.java b/src/main/java/com/server/hispath/activity/application/dto/ActivityDto.java new file mode 100644 index 0000000..0df3724 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ActivityDto.java @@ -0,0 +1,33 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.category.application.dto.CategoryDto; +import com.server.hispath.student.domain.Participant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityDto { + private Long id; + private CategoryDto categoryDto; + private String semester; + private boolean personal; + private String name; + private String remark; + private int weight; + private boolean studentRegistered; + + public static ActivityDto from(Activity activity) { + return new ActivityDto(activity.getId(), CategoryDto.from(activity.getCategory()), activity.getSemester(), + activity.isPersonal(), activity.getName(), activity.getRemark(), activity.getWeight(), + activity.isStudentRegistered()); + } + + public static ActivityDto from(Participant participant){ + return ActivityDto.from(participant.getActivity()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ActivityParticipantDto.java b/src/main/java/com/server/hispath/activity/application/dto/ActivityParticipantDto.java new file mode 100644 index 0000000..0ccd974 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ActivityParticipantDto.java @@ -0,0 +1,26 @@ +package com.server.hispath.activity.application.dto; + + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.student.domain.Participant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityParticipantDto { + private Long id; + private String semester; + private String name; + private String remark; + private ParticipantContentDto participant; + private int requestStatus; + public static ActivityParticipantDto of(Participant participant) { + Activity activity = participant.getActivity(); + return new ActivityParticipantDto(activity.getId(), activity.getSemester(), activity.getName(), + activity.getRemark(), ParticipantContentDto.of(participant), activity.getRequestStatus()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/AllMActivityParticipantDto.java b/src/main/java/com/server/hispath/activity/application/dto/AllMActivityParticipantDto.java new file mode 100644 index 0000000..a1a6105 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/AllMActivityParticipantDto.java @@ -0,0 +1,26 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.category.application.dto.CategoryDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class AllMActivityParticipantDto { + private Long id; + private String semester; + private String name; + private String remark; + private CategoryDto category; + private boolean participated; + + public static AllMActivityParticipantDto of(Activity activity, boolean participated) { + return new AllMActivityParticipantDto(activity.getId(), activity.getSemester(), activity.getName(), activity.getRemark(), CategoryDto.from(activity.getCategory()), + participated); + } + +} + diff --git a/src/main/java/com/server/hispath/activity/application/dto/ChartCategoryCntDto.java b/src/main/java/com/server/hispath/activity/application/dto/ChartCategoryCntDto.java new file mode 100644 index 0000000..051fa5b --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ChartCategoryCntDto.java @@ -0,0 +1,39 @@ +package com.server.hispath.activity.application.dto; + +import java.util.Objects; + +import com.querydsl.core.annotations.QueryProjection; +import com.server.hispath.category.application.dto.CategoryDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartCategoryCntDto { + private CategoryDto category; + private Long cnt; + + @QueryProjection + public ChartCategoryCntDto(Long categoryId, String categoryName, Long cnt) { + this.category = new CategoryDto(categoryId, categoryName); + this.cnt = cnt; + } + + @QueryProjection + public ChartCategoryCntDto(Long categoryId, String categoryName, Integer cnt) { + this.category = new CategoryDto(categoryId, categoryName); + this.cnt = cnt.longValue(); + } + + public ChartCategoryCntDto(CategoryDto category) { + this.category = category; + this.cnt = 0L; + } + + public boolean isSameCategory(CategoryDto categoryDto){ + return Objects.equals(categoryDto.getId(), this.category.getId()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ChartDepartmentDataDto.java b/src/main/java/com/server/hispath/activity/application/dto/ChartDepartmentDataDto.java new file mode 100644 index 0000000..f5cd9eb --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ChartDepartmentDataDto.java @@ -0,0 +1,21 @@ +package com.server.hispath.activity.application.dto; + + +import com.querydsl.core.annotations.QueryProjection; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class ChartDepartmentDataDto { + + private String department; + private Long cnt; + + @QueryProjection + public ChartDepartmentDataDto(String department, Long cnt) { + this.department = department; + this.cnt = cnt; + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ChartGradeDataDto.java b/src/main/java/com/server/hispath/activity/application/dto/ChartGradeDataDto.java new file mode 100644 index 0000000..2450f2e --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ChartGradeDataDto.java @@ -0,0 +1,25 @@ +package com.server.hispath.activity.application.dto; + + +import com.querydsl.core.annotations.QueryProjection; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class ChartGradeDataDto { + + private int grade; + private Long cnt; + + @QueryProjection + public ChartGradeDataDto(int grade, Long cnt) { + this.grade = grade; + this.cnt = cnt; + } + + public void addCnt(Long cnt) { + this.cnt += cnt; + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ChartSearchRequestDto.java b/src/main/java/com/server/hispath/activity/application/dto/ChartSearchRequestDto.java new file mode 100644 index 0000000..73340d6 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ChartSearchRequestDto.java @@ -0,0 +1,17 @@ +package com.server.hispath.activity.application.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ChartSearchRequestDto { + private String semester; + private Integer grade; + private String department; +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ChartTimelineDto.java b/src/main/java/com/server/hispath/activity/application/dto/ChartTimelineDto.java new file mode 100644 index 0000000..15e72f3 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ChartTimelineDto.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.scholarship.domain.Scholarship; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartTimelineDto { + private String semester; + private int totalWeight; + + public static ChartTimelineDto of(Scholarship scholarship){ + return new ChartTimelineDto(scholarship.getSemester(), scholarship.getTotalMileage()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/MActivityContentDto.java b/src/main/java/com/server/hispath/activity/application/dto/MActivityContentDto.java new file mode 100644 index 0000000..7ebf9b0 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/MActivityContentDto.java @@ -0,0 +1,25 @@ +package com.server.hispath.activity.application.dto; + +import java.time.LocalDateTime; + +import com.server.hispath.activity.presentation.request.MActivityCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MActivityContentDto { + private Long categoryId; + private String semester; + private String name; + private String remark; + private int weight; + + public static MActivityContentDto of(MActivityCURequest request) { + return new MActivityContentDto(request.getCategoryId(), request.getSemester(), request.getName(), + request.getRemark(), request.getWeight()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/MActivityDetailDto.java b/src/main/java/com/server/hispath/activity/application/dto/MActivityDetailDto.java new file mode 100644 index 0000000..6d1cc24 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/MActivityDetailDto.java @@ -0,0 +1,35 @@ +package com.server.hispath.activity.application.dto; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.category.application.dto.CategoryDto; +import com.server.hispath.category.domain.Category; +import com.server.hispath.student.application.dto.StudentRefDetailDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MActivityDetailDto { + private Long id; + private String name; + private CategoryDto category; + private String semester; + private String remark; + private int weight; + private List students = new ArrayList<>(); + + + public static MActivityDetailDto from(Activity activity, List students) { + return new MActivityDetailDto(activity.getId(), activity.getName(), CategoryDto.from(activity.getCategory()), + activity.getSemester(), activity.getRemark(), activity.getWeight(), students); + + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/MActivityParticipantDto.java b/src/main/java/com/server/hispath/activity/application/dto/MActivityParticipantDto.java new file mode 100644 index 0000000..d883f12 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/MActivityParticipantDto.java @@ -0,0 +1,24 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.student.domain.Participant; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MActivityParticipantDto { + private Long id; + private String semester; + private String name; + private String remark; + private MParticipantContentDto participant; + + public static MActivityParticipantDto of(Participant participant) { + Activity activity = participant.getActivity(); + return new MActivityParticipantDto(activity.getId(), activity.getSemester(), activity.getName(), + activity.getRemark(), MParticipantContentDto.of(participant)); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/MParticipantContentDto.java b/src/main/java/com/server/hispath/activity/application/dto/MParticipantContentDto.java new file mode 100644 index 0000000..b980a24 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/MParticipantContentDto.java @@ -0,0 +1,26 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.presentation.request.MStudentActivityCURequest; +import com.server.hispath.activity.presentation.request.StudentActivityCURequest; +import com.server.hispath.category.domain.Category; +import com.server.hispath.student.domain.Participant; +import com.server.hispath.student.domain.Section; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MParticipantContentDto { + private Category category; + private String data; + + public static MParticipantContentDto of(MStudentActivityCURequest request) { + return new MParticipantContentDto(Category.fromString(request.getCategory()), request.getData()); + } + public static MParticipantContentDto of(Participant participant) { + return new MParticipantContentDto(participant.getActivity().getCategory(), participant.getData()); + } +} + diff --git a/src/main/java/com/server/hispath/activity/application/dto/MStudentActivityDetailDto.java b/src/main/java/com/server/hispath/activity/application/dto/MStudentActivityDetailDto.java new file mode 100644 index 0000000..ce78262 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/MStudentActivityDetailDto.java @@ -0,0 +1,46 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.category.application.dto.CategoryDto; +import com.server.hispath.student.application.dto.StudentRefDetailDto; +import com.server.hispath.student.domain.Student; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MStudentActivityDetailDto { +// private Long id; +// private String name; +// private CategoryDto category; +// private int studentNum; +// private String semester; +// private String remark; +// private LocalDateTime startDate; +// private LocalDateTime endDate; +// private int weight; + + + private Long id; + + private String name; + + private String studentNum; + + private int semester; + + + + private List activities = new ArrayList<>(); + + public static MStudentActivityDetailDto from(Student student, List activities) { + return new MStudentActivityDetailDto(student.getId(), student.getName(), student.getStudentNum(), student.getSemester() ,activities); + + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/ParticipantContentDto.java b/src/main/java/com/server/hispath/activity/application/dto/ParticipantContentDto.java new file mode 100644 index 0000000..ab9581c --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/ParticipantContentDto.java @@ -0,0 +1,24 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.presentation.request.StudentActivityCURequest; +import com.server.hispath.student.domain.Participant; +import com.server.hispath.student.domain.Section; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ParticipantContentDto { + private Section section; + private String data; + + public static ParticipantContentDto of(StudentActivityCURequest request) { + return new ParticipantContentDto(Section.find(request.getSection()), request.getData()); + } + public static ParticipantContentDto of(Participant participant) { + return new ParticipantContentDto(participant.getSection(), participant.getData()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/SemesterDto.java b/src/main/java/com/server/hispath/activity/application/dto/SemesterDto.java new file mode 100644 index 0000000..00cee8f --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/SemesterDto.java @@ -0,0 +1,41 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.student.domain.Student; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.Objects; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class SemesterDto { + private String semester; + + public static SemesterDto from(String semester) { + return new SemesterDto(semester); + } + + + @Override + public boolean equals(Object o) { + if(o instanceof SemesterDto){ + return semester.equals(((SemesterDto) o).semester); + } + return false; + } + + @Override + public int hashCode(){ + return semester.hashCode(); + } + + +} + + + diff --git a/src/main/java/com/server/hispath/activity/application/dto/StudentActivityContentDto.java b/src/main/java/com/server/hispath/activity/application/dto/StudentActivityContentDto.java new file mode 100644 index 0000000..8f48d7b --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/StudentActivityContentDto.java @@ -0,0 +1,20 @@ +package com.server.hispath.activity.application.dto; + +import com.server.hispath.activity.presentation.request.StudentActivityCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentActivityContentDto { + private String semester; + private String name; + private String remark; + + public static StudentActivityContentDto of(StudentActivityCURequest request){ + return new StudentActivityContentDto(request.getSemester(), request.getName(), request.getRemark()); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/chart/ChartCategoryDto.java b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartCategoryDto.java new file mode 100644 index 0000000..84ba70f --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartCategoryDto.java @@ -0,0 +1,32 @@ +package com.server.hispath.activity.application.dto.chart; + +import java.util.Objects; + +import com.server.hispath.activity.application.dto.chart.ChartDataDto; +import com.server.hispath.category.application.dto.CategoryDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartCategoryDto { + private CategoryDto category; + private Long myCnt; + private Double averageCnt; + private Long totalCnt; + + + public ChartCategoryDto(ChartDataDto dto, Long totalActivityCnt) { + this.category = dto.getCategory(); + this.myCnt = dto.getMyCnt(); + this.averageCnt = dto.getAverageCnt(); + this.totalCnt = totalActivityCnt; + } + + public boolean isNotETC(){ + return !Objects.equals(category.getName(), "기타"); + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/chart/ChartDataDto.java b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartDataDto.java new file mode 100644 index 0000000..ac7a091 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartDataDto.java @@ -0,0 +1,30 @@ +package com.server.hispath.activity.application.dto.chart; + +import com.server.hispath.activity.application.dto.ChartCategoryCntDto; +import com.server.hispath.category.application.dto.CategoryDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartDataDto { + + private CategoryDto category; + private Long myCnt; + private Double averageCnt; + + public ChartDataDto(ChartCategoryCntDto dto, Long totalCnt, int totalStudent) { + this.category = dto.getCategory(); + this.myCnt = dto.getCnt(); + this.averageCnt = totalCnt / (double) totalStudent; + } + + public ChartDataDto(CategoryDto dto, Long totalCnt, int totalStudent) { + this.category = dto; + this.myCnt = 0L; + this.averageCnt = totalCnt / (double) totalStudent; + } +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/chart/ChartRankDto.java b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartRankDto.java new file mode 100644 index 0000000..4d9ab42 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartRankDto.java @@ -0,0 +1,16 @@ +package com.server.hispath.activity.application.dto.chart; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartRankDto { + + private int myTotalWeight; + private double avgTotalWeight; + private int maxTotalWeight; + +} diff --git a/src/main/java/com/server/hispath/activity/application/dto/chart/ChartSectionCntDto.java b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartSectionCntDto.java new file mode 100644 index 0000000..8bfc68c --- /dev/null +++ b/src/main/java/com/server/hispath/activity/application/dto/chart/ChartSectionCntDto.java @@ -0,0 +1,28 @@ +package com.server.hispath.activity.application.dto.chart; + +import java.util.Objects; + +import com.querydsl.core.annotations.QueryProjection; +import com.server.hispath.student.domain.Section; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class ChartSectionCntDto { + + private String section; + private Long cnt; + + @QueryProjection + public ChartSectionCntDto(Section section, Long cnt) { + this.section = section.getName(); + this.cnt = cnt; + } + + public boolean isSameSection(String section){ + return Objects.equals(this.section, section); + } +} diff --git a/src/main/java/com/server/hispath/activity/domain/Activity.java b/src/main/java/com/server/hispath/activity/domain/Activity.java new file mode 100644 index 0000000..890b33d --- /dev/null +++ b/src/main/java/com/server/hispath/activity/domain/Activity.java @@ -0,0 +1,189 @@ +package com.server.hispath.activity.domain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import javax.persistence.*; + +import com.server.hispath.activity.application.dto.ActivityContentDto; +import com.server.hispath.activity.application.dto.MActivityContentDto; +import com.server.hispath.activity.application.dto.ParticipantContentDto; +import com.server.hispath.activity.application.dto.StudentActivityContentDto; +import com.server.hispath.category.domain.Category; +import com.server.hispath.common.BaseEntity; +import com.server.hispath.exception.activity.ActivityApplyException; +import com.server.hispath.exception.activity.ParticipantDuplicateException; +import com.server.hispath.student.domain.Participant; +import com.server.hispath.student.domain.Section; +import com.server.hispath.student.domain.Student; +import com.sun.istack.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE activity SET deleted = true Where id = ?") +public class Activity extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + private Category category; + + @NotNull + private String semester; + + private boolean personal; + + private String remark; + + // 1 일떄 마일리지 처리, 0이면 마일리지 아님 + private int requestStatus; + + private String name; + + private boolean studentRegistered = false; + + int weight; + + @Builder.Default + @OneToMany(mappedBy = "activity", cascade = CascadeType.PERSIST, orphanRemoval = true) + private List participants = new ArrayList<>(); + + public static Activity from(Category category, ActivityContentDto dto) { + return Activity.builder() + .category(category) + .semester(dto.getSemester()) + .personal(dto.isPersonal()) + .requestStatus(dto.getRequestStatus()) + .name(dto.getName()) + .remark(dto.getRemark()) + .weight(dto.getWeight()) + .build(); + } + + public static Activity from(Category category, MActivityContentDto dto) { + return Activity.builder() + .category(category) + .semester(dto.getSemester()) + .personal(false) + .requestStatus(1) + .name(dto.getName()) + .remark(dto.getRemark()) + .weight(dto.getWeight()) + .build(); + } + + public static Activity from(StudentActivityContentDto dto, Category category) { + return Activity.builder() + .category(category) + .semester(dto.getSemester()) + .remark(dto.getRemark()) + .personal(true) + .requestStatus(3) + .name(dto.getName()) + .weight(0) + .build(); + } + + public void update(Category category, ActivityContentDto dto) { + this.category = category; + this.semester = dto.getSemester(); + this.personal = dto.isPersonal(); + this.requestStatus = dto.getRequestStatus(); + this.name = dto.getName(); + this.remark = dto.getRemark(); + this.weight = dto.getWeight(); + } + + public void update(Category category, MActivityContentDto dto) { + this.category = category; + this.semester = dto.getSemester(); + this.name = dto.getName(); + this.remark = dto.getRemark(); + this.weight = dto.getWeight(); + } + + public void update(StudentActivityContentDto dto) { + this.semester = dto.getSemester(); + this.name = dto.getName(); + this.remark = dto.getRemark(); + } + + public void addParticipant(Student student, Section section) { + checkDuplicate(student); + Participant participant = new Participant(student, this, section); + this.connectParticipant(student, participant); + } + + public void checkDuplicate(Student student) { + Optional dupParticipant = this.getParticipants() + .stream() + .filter(participant -> participant.isSameStudent(student)) + .findFirst(); + if (dupParticipant.isPresent()) { + Student duplicatedStudent = dupParticipant.get().getStudent(); + throw new ParticipantDuplicateException(duplicatedStudent.getStudentNum(), duplicatedStudent.getName()); + } + } + + public void addParticipant(Student student, ParticipantContentDto participantContentDto) { + Participant participant = new Participant(student, this, participantContentDto); + this.connectParticipant(student, participant); + } + + private void connectParticipant(Student student, Participant participant) { + this.participants.add(participant); + student.addParticipant(participant); + } + + public void updateStudentRegister() { + studentRegistered = true; + } + + public boolean isSameSemester(String semester) { + if(Objects.equals(semester, "ALL")) + return true; + return Objects.equals(this.semester, semester); + } + + public boolean isSameCategory(String category) { + if(Objects.equals(category, "ALL")) + return true; + return Objects.equals(this.category.getName(), category); + } + + public void apply(){ + if(this.requestStatus != 3) + throw new ActivityApplyException(); + this.requestStatus = 0; + } + + public void approve(int weight){ + this.requestStatus = 1; + this.weight = weight; + } + + public void reject(){ + this.requestStatus = 2; + } + + public boolean isParticipate(Student student) { + return this.participants.stream() + .anyMatch(participant -> participant.isSameStudent(student)); + } + + +} diff --git a/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepository.java b/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepository.java new file mode 100644 index 0000000..5b2e6f6 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepository.java @@ -0,0 +1,51 @@ +package com.server.hispath.activity.domain.repository; + +import java.util.List; +import java.util.Optional; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.student.domain.Student; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface ActivityRepository extends JpaRepository { + List findAllBySemester(String semester); + + // commit 테스트용 + @Query("select a from Activity a " + + "left join fetch a.participants as p " + + "left join fetch p.student " + + "where a.id = :id ") + Optional findActivityWithStudents(Long id); + + @Query("select a from Activity a " + + "left join fetch a.participants as p " + + "left join fetch p.student " + + "where a.id = :id " + + "and a.personal = true ") + Optional findActivityWithStudentsAndPeronel(Long id); + + @Query("select a from Activity a " + + "left join fetch a.participants as p " + + "where p.student = :student " + + "and a.semester = :semester") + List findActivitiesByStudentAndSemester(Student student, String semester); + + @Query("select distinct semester from Activity") + List bringSemester(); + + List findAllBySemesterAndRequestStatus(String semester, int requestStatus); + + List findAllByRequestStatus(int requestStatus); + + @Query("select distinct a from Activity a " + + "left join fetch a.participants as p " + + "left join fetch p.student " + + "where a.requestStatus = 1") + List findParticipatedActivity(); + + @Query("select sum(a.weight) from Activity a " + + "where a.semester = :semester") + int sumActivityWeight(String semester); +} diff --git a/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepositoryCustom.java b/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepositoryCustom.java new file mode 100644 index 0000000..9c0c55e --- /dev/null +++ b/src/main/java/com/server/hispath/activity/domain/repository/ActivityRepositoryCustom.java @@ -0,0 +1,130 @@ +package com.server.hispath.activity.domain.repository; + +import java.util.List; +import java.util.Objects; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.server.hispath.activity.application.dto.ChartCategoryCntDto; +import com.server.hispath.activity.application.dto.ChartSearchRequestDto; +import com.server.hispath.activity.application.dto.QChartCategoryCntDto; +import com.server.hispath.activity.application.dto.chart.ChartSectionCntDto; +import com.server.hispath.activity.application.dto.chart.QChartSectionCntDto; +import com.server.hispath.student.domain.Student; + +import org.springframework.stereotype.Repository; + +import lombok.RequiredArgsConstructor; + +import static com.server.hispath.activity.domain.QActivity.activity; +import static com.server.hispath.category.domain.QCategory.category; +import static com.server.hispath.student.domain.QParticipant.participant; +import static com.server.hispath.student.domain.QStudent.student; + +@Repository +@RequiredArgsConstructor +public class ActivityRepositoryCustom { + private final JPAQueryFactory queryFactory; + + public List getStudentCategoryParticipateCnt(Student student, ChartSearchRequestDto dto) { + return queryFactory.select(new QChartCategoryCntDto(category.id, category.name, activity.count())) + .from(activity) + .leftJoin(activity.participants, participant) + .leftJoin(activity.category, category) + .where(studentChartCategoryCondition(student, dto)) + .groupBy(category) + .fetch(); + + } + + public List getTotalCategoryParticipateCnt(ChartSearchRequestDto dto) { + return queryFactory.select(new QChartCategoryCntDto(category.id, category.name, activity.participants.size() + .count())) + .from(activity) + .leftJoin(activity.participants, participant) + .leftJoin(participant.activity, activity) + .leftJoin(activity.category, category) + .where(totalChartCategoryCondition(dto)) + .groupBy(category) + .fetch(); + } + + public List getActivityCntByCategoryAndSemester(ChartSearchRequestDto dto) { + return queryFactory.select(new QChartCategoryCntDto(category.id, category.name, activity.count())) + .from(activity) + .leftJoin(activity.category, category) + .where(semesterCondition(new BooleanBuilder(), dto)) + .groupBy(category) + .fetch(); + } + + public List getPersonalChartSectionCnts(Long studentId, ChartSearchRequestDto dto) { + return queryFactory.select(new QChartSectionCntDto(participant.section, participant.count())) + .from(participant) + .where(participant.student.id.eq(studentId) + .and(participant.activity.semester.eq(dto.getSemester()))) + .groupBy(participant.section) + .fetch(); + } + + public List getTotalChartSectionCnts(ChartSearchRequestDto dto) { + return queryFactory.select(new QChartSectionCntDto(participant.section, participant.count())) + .from(participant) + .where(participant.activity.semester.eq(dto.getSemester())) + .groupBy(participant.section) + .fetch(); + } + + public int getTotalStudentCntByChartSearchRequest(ChartSearchRequestDto dto) { + return queryFactory.selectDistinct(participant.student.id) + .from(activity) + .leftJoin(activity.participants, participant) + .where(totalChartCategoryCondition(dto)) + .fetch().size(); + } + + public BooleanBuilder studentChartCategoryCondition(Student student, ChartSearchRequestDto dto) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + + booleanBuilder.and(participant.student.eq(student)); + booleanBuilder = semesterCondition(booleanBuilder, dto); + booleanBuilder = mileageActivityCondition(booleanBuilder); + return booleanBuilder; + } + + public BooleanBuilder totalChartCategoryCondition(ChartSearchRequestDto dto) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + booleanBuilder = semesterCondition(booleanBuilder, dto); + booleanBuilder = departmentCondition(booleanBuilder, dto); + booleanBuilder = mileageActivityCondition(booleanBuilder); + if (!Objects.isNull(dto.getGrade())) { + int grade = (dto.getGrade() + 1) / 2 * 2; + booleanBuilder.and(participant.student.semester.eq(grade - 1).or(participant.student.semester.eq(grade))); + } + return booleanBuilder; + } + + public BooleanBuilder semesterCondition(BooleanBuilder booleanBuilder, ChartSearchRequestDto dto) { + if (Objects.equals(dto.getSemester(), "ALL")) + return booleanBuilder; + if (!Objects.isNull(dto.getSemester())) { + booleanBuilder.and(activity.semester.eq(dto.getSemester())); + } + return booleanBuilder; + } + + public BooleanBuilder departmentCondition(BooleanBuilder booleanBuilder, ChartSearchRequestDto dto) { + + if (!Objects.isNull(dto.getDepartment())) { + booleanBuilder.and(participant.student.department.name.eq(dto.getDepartment())); + } + + return booleanBuilder; + } + + public BooleanBuilder mileageActivityCondition(BooleanBuilder booleanBuilder) { + booleanBuilder.and(activity.requestStatus.eq(1)); + return booleanBuilder; + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/ActivityController.java b/src/main/java/com/server/hispath/activity/presentation/ActivityController.java new file mode 100644 index 0000000..967511f --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/ActivityController.java @@ -0,0 +1,178 @@ +package com.server.hispath.activity.presentation; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.MActivityService; +import com.server.hispath.activity.application.dto.*; +import com.server.hispath.activity.presentation.request.ActivityApproveRequest; +import com.server.hispath.activity.presentation.request.ActivityCURequest; +import com.server.hispath.activity.presentation.request.StudentActivityCURequest; +import com.server.hispath.activity.presentation.response.ActivityParticipantResponse; +import com.server.hispath.activity.presentation.response.ActivityResponse; +import com.server.hispath.activity.presentation.response.SemesterResponse; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.student.domain.Section; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ActivityController { + private final ActivityService activityService; + private final MActivityService mActivityService; + + @PostMapping("/activity") + @ApiOperation(value = ApiDoc.ACTIVITY_CREATE) + public ResponseEntity create(@RequestBody ActivityCURequest request) { + Long id = activityService.create(request.getCategoryId(), ActivityContentDto.from(request)); + return ResponseEntity.ok(id); + } + + @GetMapping("/activity/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_READ) + public ResponseEntity find(@PathVariable Long id) { + + ActivityResponse response = ActivityResponse.from(activityService.find(id)); + return ResponseEntity.ok(response); + + } + + @GetMapping("/activities") + @ApiOperation(value = ApiDoc.ACTIVITY_READ_ALL) + public ResponseEntity> findAll() { + + List responses = activityService.findAll() + .stream() + .map(ActivityResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + + } + + @PutMapping("/activity/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_UPDATE) + public ResponseEntity update(@PathVariable Long id, @RequestBody ActivityCURequest request) { + ActivityDto dto = activityService.update(id, request.getCategoryId(), ActivityContentDto.from(request)); + ActivityResponse response = ActivityResponse.from(dto); + + return ResponseEntity.ok(response); + } + + @DeleteMapping("/activity/student/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_DELETE) + @RequiredLogin + public ResponseEntity delete(@PathVariable Long id, @StudentLogin LoginStudent loginStudent) { + activityService.deleteStudentActivity(loginStudent.getId(), id); + return ResponseEntity.ok(id); + } + + @GetMapping("/semester") + @ApiOperation(value = ApiDoc.ACTIVITY_READ_SEMESTER) + public ResponseEntity> findAllBySemester() { + List semesterDtos = activityService.bringSemester(); + List responses = semesterDtos.stream() + .map(SemesterResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/sections") + @ApiOperation(value = ApiDoc.SECTION_READ_ALL) + @RequiredLogin + public ResponseEntity> getSections() { + List sections = Arrays.stream(Section.values()) + .map(Section::getName) + .collect(Collectors.toList()); + return ResponseEntity.ok(sections); + } + + @PostMapping("/student-activity") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_CREATE) + @RequiredLogin + public ResponseEntity createStudentActivity(@StudentLogin LoginStudent loginStudent, @RequestBody StudentActivityCURequest request) { + Long response = activityService.createStudentActivity(loginStudent.getId(), StudentActivityContentDto.of(request), ParticipantContentDto.of(request)); + return ResponseEntity.ok(response); + } + + @PutMapping("/student-activity/{id}") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_UPDATE) + @RequiredLogin + public ResponseEntity updateStudentActivity(@PathVariable Long id + , @RequestBody StudentActivityCURequest request + , @StudentLogin LoginStudent loginStudent + ) { + ActivityParticipantDto activityParticipantDto = activityService.updateStudentActivity(id, loginStudent.getId(), StudentActivityContentDto.of(request), ParticipantContentDto.of(request)); + return ResponseEntity.ok(ActivityParticipantResponse.of(activityParticipantDto)); + } + + @GetMapping("/student-activities") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_READ_SEMESTER) + @RequiredLogin + public ResponseEntity> findParticipatedActivities( + @StudentLogin LoginStudent loginStudent, + @RequestParam String semester, + @RequestParam String section) { + List responses = activityService.findAllParticipantActivites(loginStudent.getId(), semester, section) + .stream() + .map(ActivityParticipantResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/studentactivity") + @ApiOperation(value = ApiDoc.STUDENT_MILEAGE_READ) + @RequiredLogin + public ResponseEntity findActivtyByStudentId(@StudentLogin LoginStudent loginStudent) { + return ResponseEntity.ok(mActivityService.findActivitiesByStudent(loginStudent.getId())); + } + + @PutMapping("/activity/apply/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_APPLY) + @RequiredLogin + public ResponseEntity applyActivity(@PathVariable Long id) { + activityService.apply(id); + return ResponseEntity.ok(null); + } + + @PutMapping("/activity/approve/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_APPROVE) + @RequiredManagerLogin + public ResponseEntity approveActivity(@PathVariable Long id, @RequestBody ActivityApproveRequest request) { + activityService.approve(id, request.getWeight()); + return ResponseEntity.ok(null); + } + + @PutMapping("/activity/reject/{id}") + @ApiOperation(value = ApiDoc.ACTIVITY_REJECT) + @RequiredManagerLogin + public ResponseEntity rejectActivity(@PathVariable Long id) { + activityService.reject(id); + return ResponseEntity.ok(null); + } + + + @GetMapping("/activity-detail/{activityId}") + @ApiOperation(value = ApiDoc.ACTIVITY_STUDENT_DETAIL) + @RequiredLogin + public ResponseEntity findParticipantActivityById( + @PathVariable Long activityId, + @StudentLogin LoginStudent loginStudent) { + + ActivityParticipantDto dto = activityService.findParticipantActivityById(loginStudent.getId(), activityId); + return ResponseEntity.ok(ActivityParticipantResponse.of(dto)); + + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/ActivityTestController.java b/src/main/java/com/server/hispath/activity/presentation/ActivityTestController.java new file mode 100644 index 0000000..161f0c8 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/ActivityTestController.java @@ -0,0 +1,39 @@ +package com.server.hispath.activity.presentation; + + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.activity.domain.repository.ActivityRepository; +import com.server.hispath.category.domain.Category; +import com.server.hispath.category.domain.repository.CategoryRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/activity") +public class ActivityTestController { + + private final ActivityRepository activityRepository; + private final CategoryRepository categoryRepository; + + @GetMapping("/init") + public ResponseEntity testInit() { + activityRepository.save(Activity.builder().semester("2021-2").personal(false).remark("Spring 이용").requestStatus(200).name("(캠프)웹서비스 프로젝트(spring)_장소연").weight(3).category(categoryRepository.findByName("비교과-행사참여")).build()); + activityRepository.save(Activity.builder().semester("2022-2").personal(false).remark("우수상 수상").requestStatus(200).name("비즈플로우").weight(2).category(categoryRepository.findByName("비교과-행사참여")).build()); + activityRepository.save(Activity.builder().semester("2020-2").personal(false).remark("").requestStatus(200).name("(캠프)미리미리C 캠프_김광").weight(5).category(categoryRepository.findByName("비교과-행사참여")).build()); + activityRepository.save(Activity.builder().semester("2020-1").personal(false).remark("").requestStatus(200).name("C 프로그래밍").weight(1).category(categoryRepository.findByName("전공마일리지")).build()); + activityRepository.save(Activity.builder().semester("2021-1").personal(false).remark("").requestStatus(200).name("AI프로젝트 입문").weight(2).category(categoryRepository.findByName("전공마일리지")).build()); + activityRepository.save(Activity.builder().semester("2019-2").personal(false).remark("").requestStatus(200).name("(캠프)Advanced Flutter Camp_조성배").weight(4).category(categoryRepository.findByName("비교과-행사참여")).build()); + activityRepository.save(Activity.builder().semester("2019-1").personal(true).remark("").requestStatus(200).name("정보처리기사 자격증").weight(2).category(categoryRepository.findByName("기타")).build()); + activityRepository.save(Activity.builder().semester("2022-1").personal(false).remark("").requestStatus(200).name("공학프로젝트기획").weight(6).category(categoryRepository.findByName("전공마일리지")).build()); + activityRepository.save(Activity.builder().semester("2020-2").personal(false).remark("").requestStatus(200).name("캡스톤").weight(1).category(categoryRepository.findByName("전공마일리지")).build()); + activityRepository.save(Activity.builder().semester("2021-2").personal(false).remark("").requestStatus(200).name("프로그래밍 집중훈련 캠프_김호준").weight(7).category(categoryRepository.findByName("비교과-행사참여")).build()); + + + + return ResponseEntity.ok(null); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/ChartController.java b/src/main/java/com/server/hispath/activity/presentation/ChartController.java new file mode 100644 index 0000000..afcf993 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/ChartController.java @@ -0,0 +1,136 @@ +package com.server.hispath.activity.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.dto.ChartGradeDataDto; +import com.server.hispath.activity.application.dto.ChartSearchRequestDto; +import com.server.hispath.activity.presentation.response.chart.*; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.scholarship.application.ScholarshipService; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ChartController { + + private final ActivityService activityService; + private final ScholarshipService scholarshipService; + + @GetMapping("/chart/mileage") + @ApiOperation(value = ApiDoc.CHART_MILEAGE_CATEGORY) + @RequiredLogin + public ResponseEntity> getChartMileageData( + String semester, + @RequestParam(required = false) Integer grade, + @RequestParam(required = false) String department, + @StudentLogin LoginStudent loginStudent + ) { + + ChartSearchRequestDto chartSearchRequestDto = new ChartSearchRequestDto(semester, grade, department); + List responses = activityService.getChartDatasByCategory(loginStudent.getId(), chartSearchRequestDto) + .stream() + .map(ChartDataResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/chart/popularity") + @ApiOperation(value = ApiDoc.CHART_MILEAGE_POPULARITY_CATEGORY) + @RequiredLogin + public ResponseEntity> getChartMileagePopularity( + String semester, + @RequestParam(required = false) Integer grade, + @RequestParam(required = false) String department, + @StudentLogin LoginStudent loginStudent + ) { + + ChartSearchRequestDto chartSearchRequestDto = new ChartSearchRequestDto(semester, grade, department); + List responses = activityService.getChartTotalDatasByCategory(loginStudent.getId(), chartSearchRequestDto) + .stream() + .map(ChartCategoryResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/chart/rank") + @ApiOperation(value = ApiDoc.CHART_MILEAGE_RANK) + @RequiredLogin + public ResponseEntity getChartMileageRank( + String semester, + @RequestParam(required = false) Integer grade, + @RequestParam(required = false) String department, + @StudentLogin LoginStudent loginStudent + ) { + + ChartSearchRequestDto chartSearchRequestDto = new ChartSearchRequestDto(semester, grade, department); + return ResponseEntity.ok(ChartRankResponse.of(scholarshipService.getRankChartData(loginStudent.getId(), chartSearchRequestDto))); + } + + @GetMapping("/chart/timeline") + @ApiOperation(value = ApiDoc.CHART_MILEAGE_TIMELINE) + @RequiredLogin + public ResponseEntity> getChartMileageTimeline(@StudentLogin LoginStudent loginStudent) { + + List responses = scholarshipService.getChartTimelines(loginStudent.getId()) + .stream() + .map(ChartTimelineResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/chart/weight") + @ApiOperation(value = ApiDoc.CHART_SCHOLARSHIP_WEIGHT) + @RequiredManagerLogin + public ResponseEntity> getChartWeightDistribution(@RequestParam String semester) { + + return ResponseEntity.ok(scholarshipService.getChartWeightDistribution(semester)); + } + + @GetMapping("/chart/grade") + @ApiOperation(value = ApiDoc.CHART_SCHOLARSHIP_GRADE) + @RequiredManagerLogin + public ResponseEntity> getChartGradeDistribution(@RequestParam String semester) { + + List responses = scholarshipService.getChartGradeDistribution(semester) + .stream() + .map(ChartGradeResponse::of) + .collect(Collectors.toList()); + + return ResponseEntity.ok(responses); + } + + @GetMapping("/chart/department") + @ApiOperation(value = ApiDoc.CHART_SCHOLARSHIP_DEPARTMENT) + @RequiredManagerLogin + public ResponseEntity> getChartDepartmentDistribution(@RequestParam String semester) { + + List responses = scholarshipService.getChartDepartmentDistribution(semester) + .stream() + .map(ChartDepartmentResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/chart/activities") + @ApiOperation(value = ApiDoc.CHART_STUDENT_ACTIVITY) + @RequiredLogin + public ResponseEntity> getActivityChartDatas(@StudentLogin LoginStudent loginStudent, @RequestParam String semester) { + return ResponseEntity.ok(activityService.getChartTotalDatasBySections(loginStudent.getId(), semester)); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/MActivityController.java b/src/main/java/com/server/hispath/activity/presentation/MActivityController.java new file mode 100644 index 0000000..bf7df9a --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/MActivityController.java @@ -0,0 +1,190 @@ +package com.server.hispath.activity.presentation; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.MActivityService; +import com.server.hispath.activity.application.dto.*; +import com.server.hispath.activity.presentation.request.MActivityCURequest; +import com.server.hispath.activity.presentation.request.MParticipantRequest; +import com.server.hispath.activity.presentation.request.MStudentRegisterRequest; +import com.server.hispath.activity.presentation.response.ActivityResponse; +import com.server.hispath.activity.presentation.response.AllMActivityParticipantResponse; +import com.server.hispath.activity.presentation.response.MActivityParticipantResponse; +import com.server.hispath.activity.presentation.response.SemesterResponse; +import com.server.hispath.auth.domain.*; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.application.dto.StudentSimpleRefDto; +import com.server.hispath.util.ExcelManager; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class MActivityController { + + private final MActivityService mActivityService; + private final ActivityService activityService; + private final StudentService studentService; + + @PostMapping("/mileage") + @ApiOperation(value = ApiDoc.MILEAGE_CREATE) + @RequiredSuperManagerLogin + public ResponseEntity create(@RequestBody MActivityCURequest request) { + Long id = mActivityService.create(MActivityContentDto.of(request)); + return ResponseEntity.ok(id); + } + + @PostMapping("/mileages") + @ApiOperation(value = ApiDoc.MILEAGES_CREATE) + @RequiredSuperManagerLogin + public ResponseEntity createMActivites(@RequestPart(value = "file") MultipartFile file) throws Exception { + mActivityService.createAll(ExcelManager.getMActivities(ExcelManager.extract(file))); + return ResponseEntity.ok(null); + } + + @PutMapping("/mileage/{id}") + @ApiOperation(value = ApiDoc.MILEAGE_UPDATE) + @RequiredSuperManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody MActivityCURequest request) { + ActivityDto dto = mActivityService.update(id, MActivityContentDto.of(request)); + ActivityResponse response = ActivityResponse.from(dto); + + return ResponseEntity.ok(response); + } + + @DeleteMapping("/mileage/{id}") + @ApiOperation(value = ApiDoc.MILEAGE_DELETE) + @RequiredSuperManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + activityService.delete(id); + return ResponseEntity.ok(id); + } + + @GetMapping("/mileage/semester") + @ApiOperation(value = ApiDoc.MILEAGE_READ_SEMESTER) + @RequiredManagerLogin + public ResponseEntity> findAllBySemester(@RequestParam String semester) { + List activityDtos = mActivityService.findAllBySemester(semester); + List responses = activityDtos.stream() + .map(ActivityResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/mileages") + @ApiOperation(value = ApiDoc.MILEAGE_READ_ALL) + @RequiredManagerLogin + public ResponseEntity> findAll() { + + List responses = mActivityService.findAll() + .stream() + .map(ActivityResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @PostMapping("/mileage/students") + @ApiOperation(value = ApiDoc.MILEAGE_REGISTER_STUDENTS) + @RequiredManagerLogin + public ResponseEntity registerStudents(@RequestPart(value = "file", required = false) MultipartFile file, + @RequestPart(value = "activityId") Long activityId) throws Exception { + + studentService.registerParticipants(activityId, ExcelManager.getStudentSimpleDatas(ExcelManager.extract(file))); + + return ResponseEntity.ok(null); + } + + @PostMapping("/mileage/student") + @ApiOperation(value = ApiDoc.MILEAGE_REGISTER_STUDENT) + @RequiredManagerLogin + public ResponseEntity registerStudent(@RequestBody MStudentRegisterRequest request) { + + studentService.registerParticipant(request.getActivityId(), StudentSimpleRefDto.of(request)); + return ResponseEntity.ok(null); + } + + @DeleteMapping("/mileage/student") + @ApiOperation(value = ApiDoc.ACTIVITY_STUDENT_DELETE) + @RequiredManagerLogin + public ResponseEntity deleteParticipant(@RequestBody MParticipantRequest request) { + mActivityService.deleteParticipant(request.getStudentId(), request.getActivityId()); + return ResponseEntity.ok(null); + } + + @GetMapping("/mileage/{id}") + @ApiOperation(value = ApiDoc.MILEAGE_READ) + public ResponseEntity findMileageActivityById(@PathVariable Long id) { + return ResponseEntity.ok(mActivityService.findDetailActivityInfo(id)); + } + + @GetMapping("/studentmileage") + @ApiOperation(value = ApiDoc.STUDENT_MILEAGE_READ) + @RequiredLogin + public ResponseEntity findActivtyByStudentId(@StudentLogin LoginStudent loginStudent) { + return ResponseEntity.ok(mActivityService.findActivitiesByStudent(loginStudent.getId())); + } + + @GetMapping("/student/semester") + @ApiOperation(value = ApiDoc.STUDENT_READ_SEMESTER) + @RequiredLogin + public ResponseEntity> findSemestersById(@StudentLogin LoginStudent loginStudent) { + List semesters = mActivityService.findSemestersById(loginStudent.getId()); + List responses = semesters.stream() + .map(SemesterResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + + @GetMapping("/student-mactivities") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_READ_SEMESTER) + @RequiredLogin + public ResponseEntity> findParticipatedActivities( + @StudentLogin LoginStudent loginStudent, + @RequestParam String semester, + @RequestParam String category) { + List responses = mActivityService.findAllParticipantActivities(loginStudent.getId(), semester, category) + .stream() + .map(MActivityParticipantResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + + + } + + @GetMapping("/student-allmactivities") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_READ_PARTICIPATE) + @RequiredLogin + public ResponseEntity> findAllParticipatedActivities( + @StudentLogin LoginStudent loginStudent, + @RequestParam String semester, + @RequestParam String category) { + + List responses; + if (Objects.equals(category, "참여여부")) { + responses = mActivityService.findParticipatedActivities(loginStudent.getId(), semester, "ALL") + .stream() + .filter(AllMActivityParticipantDto::isParticipated) + .map(AllMActivityParticipantResponse::of) + .collect(Collectors.toList()); + } else { + responses = mActivityService.findParticipatedActivities(loginStudent.getId(), semester, category) + .stream() + .map(AllMActivityParticipantResponse::of) + .collect(Collectors.toList()); + } + return ResponseEntity.ok(responses); + } + +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/activity/presentation/request/ActivityApproveRequest.java b/src/main/java/com/server/hispath/activity/presentation/request/ActivityApproveRequest.java new file mode 100644 index 0000000..a1a8462 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/ActivityApproveRequest.java @@ -0,0 +1,14 @@ +package com.server.hispath.activity.presentation.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityApproveRequest { + private int weight; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/ActivityCURequest.java b/src/main/java/com/server/hispath/activity/presentation/request/ActivityCURequest.java new file mode 100644 index 0000000..8ec02a3 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/ActivityCURequest.java @@ -0,0 +1,23 @@ +package com.server.hispath.activity.presentation.request; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ActivityCURequest { + private Long categoryId; + private String semester; + private boolean personal; + private int requestStatus; + private String name; + private String remark; + private int weight; + +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/MActivityCURequest.java b/src/main/java/com/server/hispath/activity/presentation/request/MActivityCURequest.java new file mode 100644 index 0000000..843db11 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/MActivityCURequest.java @@ -0,0 +1,21 @@ +package com.server.hispath.activity.presentation.request; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class MActivityCURequest { + private String semester; + private Long categoryId; + private String name; + private String remark; + private int weight; + +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/MParticipantRequest.java b/src/main/java/com/server/hispath/activity/presentation/request/MParticipantRequest.java new file mode 100644 index 0000000..1c0e0f9 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/MParticipantRequest.java @@ -0,0 +1,13 @@ +package com.server.hispath.activity.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class MParticipantRequest { + private Long activityId; + private Long studentId; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/MStudentActivityCURequest.java b/src/main/java/com/server/hispath/activity/presentation/request/MStudentActivityCURequest.java new file mode 100644 index 0000000..e12d94f --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/MStudentActivityCURequest.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.presentation.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class MStudentActivityCURequest { + + private String semester; + private String name; + private String remark; + private String category; + private String data; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/MStudentRegisterRequest.java b/src/main/java/com/server/hispath/activity/presentation/request/MStudentRegisterRequest.java new file mode 100644 index 0000000..c1d408e --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/MStudentRegisterRequest.java @@ -0,0 +1,16 @@ +package com.server.hispath.activity.presentation.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class MStudentRegisterRequest { + private Long activityId; + private String name; + private String studentNum; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/request/StudentActivityCURequest.java b/src/main/java/com/server/hispath/activity/presentation/request/StudentActivityCURequest.java new file mode 100644 index 0000000..3756e49 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/request/StudentActivityCURequest.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.presentation.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class StudentActivityCURequest { + + private String semester; + private String name; + private String remark; + private String section; + private String data; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantResponse.java new file mode 100644 index 0000000..986e9ba --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantResponse.java @@ -0,0 +1,26 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityParticipantDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityParticipantResponse { + private Long id; + private String semester; + private String name; + private String remark; + private String section; + private String data; + private boolean mileage; + + public static ActivityParticipantResponse of(ActivityParticipantDto dto) { + return new ActivityParticipantResponse(dto.getId(), dto.getSemester(), dto.getName(), dto.getRemark(), + dto.getParticipant().getSection().getName(), dto.getParticipant() + .getData(), dto.getRequestStatus() == 1); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantStatusResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantStatusResponse.java new file mode 100644 index 0000000..98f770f --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/ActivityParticipantStatusResponse.java @@ -0,0 +1,24 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityParticipantDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityParticipantStatusResponse { + private Long id; + private String semester; + private String name; + private String remark; + private String section; + private int requestStatus; + + public static ActivityParticipantStatusResponse of(ActivityParticipantDto dto) { + return new ActivityParticipantStatusResponse(dto.getId(), dto.getSemester(), dto.getName(), + dto.getRemark(), dto.getParticipant().getSection().getName(), dto.getRequestStatus()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/ActivityResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/ActivityResponse.java new file mode 100644 index 0000000..4bf503a --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/ActivityResponse.java @@ -0,0 +1,28 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivityResponse { + private Long id; + private Long categoryId; + private String categoryName; + private String semester; + private boolean personal; + private String name; + private String remark; + private int weight; + private boolean studentRegistered; + + public static ActivityResponse from(ActivityDto dto) { + return new ActivityResponse(dto.getId(), dto.getCategoryDto().getId(), dto.getCategoryDto().getName(), + dto.getSemester(), dto.isPersonal(), dto.getName(), dto.getRemark(), dto.getWeight(), + dto.isStudentRegistered()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/ActivitySimpleResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/ActivitySimpleResponse.java new file mode 100644 index 0000000..344125c --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/ActivitySimpleResponse.java @@ -0,0 +1,21 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityDto; +import com.server.hispath.activity.application.dto.ActivityParticipantDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ActivitySimpleResponse { + private Long id; + private String name; + private String semester; + + public static ActivitySimpleResponse of(ActivityParticipantDto activityDto){ + return new ActivitySimpleResponse(activityDto.getId(), activityDto.getName(), activityDto.getSemester()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/AllMActivityParticipantResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/AllMActivityParticipantResponse.java new file mode 100644 index 0000000..f638c7a --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/AllMActivityParticipantResponse.java @@ -0,0 +1,26 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.AllMActivityParticipantDto; +import com.server.hispath.activity.application.dto.MActivityParticipantDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class AllMActivityParticipantResponse { + private Long id; + private String semester; + private String name; + private String remark; + private String category; + + private boolean participated; + + public static AllMActivityParticipantResponse of(AllMActivityParticipantDto dto) { + return new AllMActivityParticipantResponse(dto.getId(), dto.getSemester(), dto.getName(), dto.getRemark(), + dto.getCategory().getName(), dto.isParticipated()); + + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/activity/presentation/response/MActivityParticipantResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/MActivityParticipantResponse.java new file mode 100644 index 0000000..477bca8 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/MActivityParticipantResponse.java @@ -0,0 +1,25 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityParticipantDto; +import com.server.hispath.activity.application.dto.MActivityParticipantDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MActivityParticipantResponse { + private Long id; + private String semester; + private String name; + private String remark; + private String category; + private String data; + + public static MActivityParticipantResponse of(MActivityParticipantDto dto) { + return new MActivityParticipantResponse(dto.getId(), dto.getSemester(), dto.getName(), dto.getRemark(), + + dto.getParticipant().getCategory().getName(), dto.getParticipant().getData()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/MileageChartResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/MileageChartResponse.java new file mode 100644 index 0000000..90a02e4 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/MileageChartResponse.java @@ -0,0 +1,18 @@ +package com.server.hispath.activity.presentation.response; + +import java.util.ArrayList; +import java.util.List; + +import com.server.hispath.activity.presentation.response.chart.ChartDataResponse; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MileageChartResponse { + + private List chartDatas = new ArrayList<>(); +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/SemesterResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/SemesterResponse.java new file mode 100644 index 0000000..a750f22 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/SemesterResponse.java @@ -0,0 +1,18 @@ +package com.server.hispath.activity.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityDto; +import com.server.hispath.activity.application.dto.SemesterDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SemesterResponse { + private String semester; + + public static SemesterResponse from(SemesterDto dto) { + return new SemesterResponse(dto.getSemester()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartCategoryResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartCategoryResponse.java new file mode 100644 index 0000000..47dde89 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartCategoryResponse.java @@ -0,0 +1,23 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.chart.ChartCategoryDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartCategoryResponse { + private Long categoryId; + private String categoryName; + private Long myCnt; + private Double averageCnt; + private Long totalCategoryCnt; + + public static ChartCategoryResponse of(ChartCategoryDto dto) { + return new ChartCategoryResponse(dto.getCategory().getId(), dto.getCategory().getName(), + dto.getMyCnt(), dto.getAverageCnt(), dto.getTotalCnt()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDataResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDataResponse.java new file mode 100644 index 0000000..a98b903 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDataResponse.java @@ -0,0 +1,23 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.chart.ChartDataDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartDataResponse { + + private Long categoryId; + private String categoryName; + private Long myCnt; + private Double averageCnt; + + public static ChartDataResponse of(ChartDataDto dto) { + return new ChartDataResponse(dto.getCategory().getId(), dto.getCategory().getName(), + dto.getMyCnt(), dto.getAverageCnt()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDepartmentResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDepartmentResponse.java new file mode 100644 index 0000000..d1eaa31 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartDepartmentResponse.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.ChartDepartmentDataDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartDepartmentResponse { + private String department; + private Long cnt; + + public static ChartDepartmentResponse of(ChartDepartmentDataDto dto) { + return new ChartDepartmentResponse(dto.getDepartment(), dto.getCnt()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartGradeResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartGradeResponse.java new file mode 100644 index 0000000..60da603 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartGradeResponse.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.ChartGradeDataDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartGradeResponse { + private int grade; + private Long cnt; + + public static ChartGradeResponse of(ChartGradeDataDto dto) { + return new ChartGradeResponse(dto.getGrade(), dto.getCnt()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartRankResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartRankResponse.java new file mode 100644 index 0000000..707d999 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartRankResponse.java @@ -0,0 +1,20 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.chart.ChartRankDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartRankResponse { + private int myTotalWeight; + private double avgTotalWeight; + private int maxTotalWeight; + + public static ChartRankResponse of(ChartRankDto dto){ + return new ChartRankResponse(dto.getMyTotalWeight(), dto.getAvgTotalWeight(), dto.getMaxTotalWeight()); + } +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartSectionResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartSectionResponse.java new file mode 100644 index 0000000..cc945e2 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartSectionResponse.java @@ -0,0 +1,15 @@ +package com.server.hispath.activity.presentation.response.chart; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartSectionResponse { + + private String section; + private Long myCnt; + private Double avgCnt; +} diff --git a/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartTimelineResponse.java b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartTimelineResponse.java new file mode 100644 index 0000000..8c97788 --- /dev/null +++ b/src/main/java/com/server/hispath/activity/presentation/response/chart/ChartTimelineResponse.java @@ -0,0 +1,19 @@ +package com.server.hispath.activity.presentation.response.chart; + +import com.server.hispath.activity.application.dto.ChartTimelineDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ChartTimelineResponse { + private String semester; + private int totalWeight; + + public static ChartTimelineResponse of(ChartTimelineDto dto) { + return new ChartTimelineResponse(dto.getSemester(), dto.getTotalWeight()); + } +} diff --git a/src/main/java/com/server/hispath/auth/application/AuthService.java b/src/main/java/com/server/hispath/auth/application/AuthService.java new file mode 100644 index 0000000..0ec61f3 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/application/AuthService.java @@ -0,0 +1,158 @@ +package com.server.hispath.auth.application; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Optional; + +import com.server.hispath.auth.application.dto.LoginRequestDto; +import com.server.hispath.auth.application.dto.LoginResponseDto; +import com.server.hispath.auth.domain.LoginManager; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.Member; +import com.server.hispath.auth.domain.OauthUserInfo; +import com.server.hispath.auth.infrastructure.JwtProvider; +import com.server.hispath.auth.infrastructure.OauthHandler; +import com.server.hispath.exception.manager.ManagerNoAuthorizationException; +import com.server.hispath.exception.oauth.InvalidTokenException; +import com.server.hispath.exception.oauth.NotHandongEmailException; +import com.server.hispath.manager.application.ManagerService; +import com.server.hispath.manager.domain.DailyInfo; +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.manager.domain.repository.DailyInfoRepository; +import com.server.hispath.manager.domain.repository.ManagerRepository; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Service +public class AuthService { + + private final OauthHandler oauthHandler; + private final JwtProvider jwtProvider; + private final StudentRepository studentRepository; + private final StudentService studentService; + private final ManagerRepository managerRepository; + private final ManagerService managerService; + private final DailyInfoRepository dailyInfoRepository; + + public void validateEmail(String email) { + String domain = email.split("@")[1]; + if (!Objects.equals(domain, "handong.ac.kr")) { + throw new NotHandongEmailException(); + } + ; + } + + public OauthUserInfo getStudentInfo(LoginRequestDto loginRequestDto) { + String oauthProvider = loginRequestDto.getOauthProvider(); + return oauthHandler.getUserInfoFromCode(oauthProvider, loginRequestDto.getCode(), Member.STUDENT); + } + + public OauthUserInfo getManagerInfo(LoginRequestDto loginRequestDto) { + String oauthProvider = loginRequestDto.getOauthProvider(); + return oauthHandler.getUserInfoFromCode(oauthProvider, loginRequestDto.getCode(), Member.MANAGER); + } + + @Transactional + public LoginResponseDto studentLogin(LoginRequestDto loginRequestDto) { + OauthUserInfo userInfo = getStudentInfo(loginRequestDto); + String email = userInfo.getEmail(); +// validateEmail(email); + Optional student = studentRepository.findByEmail(email); + + return student.map(value -> { + addLoginCount(); + return new LoginResponseDto(false, + jwtProvider.createToken(String.valueOf(value.getId()), Member.STUDENT)); + }) + .orElseGet(() -> new LoginResponseDto(true, null)); + } + + @Transactional(readOnly = true) + public LoginResponseDto managerLogin(LoginRequestDto loginRequestDto) { + OauthUserInfo userInfo = getManagerInfo(loginRequestDto); + String email = userInfo.getEmail(); + Optional manager = managerRepository.findByEmail(email); + return manager.map(value -> new LoginResponseDto(!value.isApproved(), + jwtProvider.createToken(String.valueOf(value.getId()), Member.MANAGER))) + .orElseGet(() -> new LoginResponseDto(true, null)); + + } + + @Transactional(readOnly = true) + public LoginStudent findStudentByToken(String token) { + if (!jwtProvider.isValidToken(token, Member.STUDENT)) { + throw new InvalidTokenException(); + } + + String payLoad = jwtProvider.getPayLoad(token, Member.STUDENT); + Long id = Long.parseLong(payLoad); + Student student = studentService.findById(id); + student.updateLogin(); + return new LoginStudent(student.getId(), student.getStudentNum()); + } + + @Transactional(readOnly = true) + public LoginManager findManagerByToken(String token) { + if (!jwtProvider.isValidToken(token, Member.MANAGER)) { + throw new InvalidTokenException(); + } + String payLoad = jwtProvider.getPayLoad(token, Member.MANAGER); + Long id = Long.parseLong(payLoad); + Manager manager = managerService.findById(id); + return new LoginManager(manager.getId()); + } + + + @Transactional(readOnly = true) + public void checkSuperManagerByToken(String token) { + Manager manager = findSuperManagerByToken(token); + if (!manager.isSuperManager()) + throw new ManagerNoAuthorizationException(); + } + + @Transactional(readOnly = true) + public LoginManager getSuperManagerId(String token) { + Manager manager = findSuperManagerByToken(token); + return new LoginManager(manager.getId()); + } + + @Transactional(readOnly = true) + public Manager findSuperManagerByToken(String token) { + if (!jwtProvider.isValidToken(token, Member.SUPER_MANAGER)) { + throw new InvalidTokenException(); + } + String payLoad = jwtProvider.getPayLoad(token, Member.SUPER_MANAGER); + Long id = Long.parseLong(payLoad); + Manager manager = managerService.findById(id); + if (!manager.isSuperManager()) + throw new ManagerNoAuthorizationException(); + return manager; + } + + private void addLoginCount() { + Optional dailyInfo = dailyInfoRepository.findFirstByDate(LocalDate.now()); + if (dailyInfo.isPresent()) { + dailyInfo.get().login(); + return; + } + DailyInfo newDailyInfo = new DailyInfo(); + dailyInfoRepository.save(newDailyInfo); + } + + @Transactional(readOnly = true) + public String getStudentGuestToken(){ + return jwtProvider.createToken(String.valueOf(1L), Member.STUDENT); + } + + @Transactional(readOnly = true) + public String getManagerGuestToken(){ + return jwtProvider.createToken(String.valueOf(1L), Member.MANAGER); + } +} diff --git a/src/main/java/com/server/hispath/auth/application/dto/LoginRequestDto.java b/src/main/java/com/server/hispath/auth/application/dto/LoginRequestDto.java new file mode 100644 index 0000000..0c7911d --- /dev/null +++ b/src/main/java/com/server/hispath/auth/application/dto/LoginRequestDto.java @@ -0,0 +1,19 @@ +package com.server.hispath.auth.application.dto; + +import java.util.Locale; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class LoginRequestDto { + private String oauthProvider; + private String code; + + public String getOauthProvider() { + return oauthProvider.toLowerCase(Locale.ROOT); + } + + public String getCode() { + return code; + } +} diff --git a/src/main/java/com/server/hispath/auth/application/dto/LoginResponseDto.java b/src/main/java/com/server/hispath/auth/application/dto/LoginResponseDto.java new file mode 100644 index 0000000..a934359 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/application/dto/LoginResponseDto.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class LoginResponseDto { + private boolean needRegister; + private String token; +} diff --git a/src/main/java/com/server/hispath/auth/domain/LoginManager.java b/src/main/java/com/server/hispath/auth/domain/LoginManager.java new file mode 100644 index 0000000..5990931 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/LoginManager.java @@ -0,0 +1,13 @@ +package com.server.hispath.auth.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class LoginManager { + + private Long id; +} diff --git a/src/main/java/com/server/hispath/auth/domain/LoginStudent.java b/src/main/java/com/server/hispath/auth/domain/LoginStudent.java new file mode 100644 index 0000000..1863fbc --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/LoginStudent.java @@ -0,0 +1,14 @@ +package com.server.hispath.auth.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class LoginStudent { + + private Long id; + private String studentNum; +} diff --git a/src/main/java/com/server/hispath/auth/domain/ManagerLogin.java b/src/main/java/com/server/hispath/auth/domain/ManagerLogin.java new file mode 100644 index 0000000..3a3ab3c --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/ManagerLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface ManagerLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/Member.java b/src/main/java/com/server/hispath/auth/domain/Member.java new file mode 100644 index 0000000..f1ba817 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/Member.java @@ -0,0 +1,19 @@ +package com.server.hispath.auth.domain; + +public enum Member { + STUDENT, MANAGER, ALL, SUPER_MANAGER; + + public static boolean isStudent(Member member) { + return member.equals(STUDENT); + } + + public static boolean isManager(Member member) { + return member.equals(MANAGER); + } + + public static boolean isSuperManager(Member member) { + return member.equals(SUPER_MANAGER); + } + + public static boolean isALl(Member member) {return member.equals(ALL);} +} diff --git a/src/main/java/com/server/hispath/auth/domain/OauthAttributes.java b/src/main/java/com/server/hispath/auth/domain/OauthAttributes.java new file mode 100644 index 0000000..1ba46fa --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/OauthAttributes.java @@ -0,0 +1,31 @@ +package com.server.hispath.auth.domain; + +import java.util.Arrays; +import java.util.Map; + +public enum OauthAttributes { + GOOGLE("google") { + @Override + public OauthUserInfo of(Map attributes) { + return OauthUserInfo.builder() + .email((String) attributes.get("email")) + .build(); + } + }; + + private final String providerName; + + OauthAttributes(String name) { + this.providerName = name; + } + + public static OauthUserInfo extract(String providerName, Map attributes) { + return Arrays.stream(values()) + .filter(provider -> providerName.equals(provider.providerName)) + .findFirst() + .orElseThrow(IllegalArgumentException::new) + .of(attributes); + } + + public abstract OauthUserInfo of(Map attributes); +} diff --git a/src/main/java/com/server/hispath/auth/domain/OauthProperties.java b/src/main/java/com/server/hispath/auth/domain/OauthProperties.java new file mode 100644 index 0000000..f1d579e --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/OauthProperties.java @@ -0,0 +1,40 @@ +package com.server.hispath.auth.domain; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@ConfigurationProperties(prefix = "oauth2") +public class OauthProperties { + + private final Map user = new HashMap<>(); + private final Map provider = new HashMap<>(); + + @Getter + @Setter + public static class User { + private String clientId; + private String clientSecret; + private String studentRedirectUri; + private String managerRedirectUri; + } + + @Getter + @Setter + public static class Provider { + private String tokenUri; + private String userInfoUri; + } + + public Map getOauthProviders() { + Map oauthProviders = new HashMap<>(); + user.forEach((key, value) -> oauthProviders.put(key, new OauthProvider(value, provider.get(key)))); + + return oauthProviders; + } +} diff --git a/src/main/java/com/server/hispath/auth/domain/OauthProvider.java b/src/main/java/com/server/hispath/auth/domain/OauthProvider.java new file mode 100644 index 0000000..57f6e2e --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/OauthProvider.java @@ -0,0 +1,20 @@ +package com.server.hispath.auth.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class OauthProvider { + private final String clientId; + private final String clientSecret; + private final String studentRedirectUrl; + private final String managerRedirectUrl; + private final String tokenUrl; + private final String userInfoUrl; + + public OauthProvider(OauthProperties.User user, OauthProperties.Provider provider) { + this(user.getClientId(), user.getClientSecret(), user.getStudentRedirectUri(), user.getManagerRedirectUri(), + provider.getTokenUri(), provider.getUserInfoUri()); + } +} diff --git a/src/main/java/com/server/hispath/auth/domain/OauthUserInfo.java b/src/main/java/com/server/hispath/auth/domain/OauthUserInfo.java new file mode 100644 index 0000000..89a4e54 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/OauthUserInfo.java @@ -0,0 +1,10 @@ +package com.server.hispath.auth.domain; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class OauthUserInfo { + private String email; +} diff --git a/src/main/java/com/server/hispath/auth/domain/RequiredLogin.java b/src/main/java/com/server/hispath/auth/domain/RequiredLogin.java new file mode 100644 index 0000000..d6ab726 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/RequiredLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequiredLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/RequiredManagerLogin.java b/src/main/java/com/server/hispath/auth/domain/RequiredManagerLogin.java new file mode 100644 index 0000000..3476326 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/RequiredManagerLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequiredManagerLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/RequiredStudentLogin.java b/src/main/java/com/server/hispath/auth/domain/RequiredStudentLogin.java new file mode 100644 index 0000000..ec65040 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/RequiredStudentLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequiredStudentLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/RequiredSuperManagerLogin.java b/src/main/java/com/server/hispath/auth/domain/RequiredSuperManagerLogin.java new file mode 100644 index 0000000..86fed78 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/RequiredSuperManagerLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequiredSuperManagerLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/StudentLogin.java b/src/main/java/com/server/hispath/auth/domain/StudentLogin.java new file mode 100644 index 0000000..d830732 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/StudentLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface StudentLogin { +} diff --git a/src/main/java/com/server/hispath/auth/domain/SuperManagerLogin.java b/src/main/java/com/server/hispath/auth/domain/SuperManagerLogin.java new file mode 100644 index 0000000..1673227 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/domain/SuperManagerLogin.java @@ -0,0 +1,11 @@ +package com.server.hispath.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface SuperManagerLogin { +} diff --git a/src/main/java/com/server/hispath/auth/infrastructure/ApiRequester.java b/src/main/java/com/server/hispath/auth/infrastructure/ApiRequester.java new file mode 100644 index 0000000..29810a8 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/infrastructure/ApiRequester.java @@ -0,0 +1,95 @@ +package com.server.hispath.auth.infrastructure; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; + +import com.server.hispath.auth.domain.Member; +import com.server.hispath.auth.domain.OauthProvider; +import com.server.hispath.exception.oauth.GetAccessTokenException; +import com.server.hispath.exception.oauth.GetUserInfoException; +import com.server.hispath.exception.oauth.UnableToGetOauthResponseException; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.core.publisher.Mono; + +public class ApiRequester { + + public Map getUserInfo(String code, OauthProvider oauthProvider, Member member) { + String token = getToken(code, oauthProvider, member); + return getUserInfoByToken(token, oauthProvider.getUserInfoUrl()); + } + + private String getToken(String code, OauthProvider oauthProvider, Member member) { + Map responseBody = WebClient.create() + .post() + .uri(oauthProvider.getTokenUrl()) + .headers(header -> { + header.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + header.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + header.setAcceptCharset(Collections.singletonList(StandardCharsets.UTF_8)); + }) + .bodyValue(tokenRequest(code, oauthProvider, member)) + .retrieve() + .onStatus(HttpStatus::isError, response -> + response.bodyToMono(String.class) + .flatMap(error -> Mono.error(new UnableToGetOauthResponseException(error)))) + .bodyToMono(new ParameterizedTypeReference>() { + }) + .flux() + .toStream() + .findFirst() + .orElseThrow(GetAccessTokenException::new); + validateResponseBody(responseBody); + return responseBody.get("access_token").toString(); + } + + private String getRedirectUrlByMember(Member member, OauthProvider oauthProvider) { + + if (Member.isStudent(member)) { + return oauthProvider.getStudentRedirectUrl(); + } + return oauthProvider.getManagerRedirectUrl(); + + } + + private MultiValueMap tokenRequest(String code, OauthProvider oauthProvider, Member member) { + MultiValueMap formData = new LinkedMultiValueMap<>(); + formData.add("code", code); + formData.add("grant_type", "authorization_code"); + formData.add("redirect_uri", getRedirectUrlByMember(member, oauthProvider)); + formData.add("client_id", oauthProvider.getClientId()); + formData.add("client_secret", oauthProvider.getClientSecret()); + return formData; + } + + private void validateResponseBody(Map responseBody) { + if (!responseBody.containsKey("access_token")) { + throw new GetAccessTokenException(); + } + } + + private static Map getUserInfoByToken(String token, String userInfoUri) { + + return WebClient.create() + .get() + .uri(userInfoUri) + .headers(httpHeaders -> httpHeaders.setBearerAuth(token)) + .retrieve() + .onStatus(HttpStatus::isError, response -> + response.bodyToMono(String.class) + .flatMap(error -> Mono.error(new UnableToGetOauthResponseException(error)))) + .bodyToMono(new ParameterizedTypeReference>() { + }) + .flux() + .toStream() + .findFirst() + .orElseThrow(GetUserInfoException::new); + } +} diff --git a/src/main/java/com/server/hispath/auth/infrastructure/JwtProvider.java b/src/main/java/com/server/hispath/auth/infrastructure/JwtProvider.java new file mode 100644 index 0000000..f4272af --- /dev/null +++ b/src/main/java/com/server/hispath/auth/infrastructure/JwtProvider.java @@ -0,0 +1,96 @@ +package com.server.hispath.auth.infrastructure; + +import java.util.Date; + +import com.server.hispath.auth.domain.Member; +import com.server.hispath.exception.authorization.InvalidTokenException; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import io.jsonwebtoken.*; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Component +public class JwtProvider { + + @Value("${jwt.student-secret-key}") + private String studentSecretKey; + + @Value("${jwt.manager-secret-key}") + private String managerSecretKey; + + @Value("${jwt.expired-time}") + private Long expiredTime; + + public String createToken(String payload, Member member) { + Date now = new Date(); + Date expiredDay = new Date(now.getTime() + expiredTime); + Claims claims = Jwts.claims().setSubject(payload); + + return Jwts.builder() + .setIssuedAt(now) + .setIssuer("MyPath") + .setExpiration(expiredDay) + .setClaims(claims) + .signWith(SignatureAlgorithm.HS256, getSecretKey(member)) + .compact(); + + } + + public String getSecretKey(Member member){ + if(Member.isStudent(member)) return studentSecretKey; + return managerSecretKey; + } + + public boolean validateBothToken(String token){ + + try{ + validateToken(token, Member.STUDENT); + return true; + } catch (InvalidTokenException | JwtException | IllegalArgumentException e){ + try{ + validateToken(token, Member.MANAGER); + return true; + } catch (JwtException | IllegalArgumentException e2){ + return false; + } + } + } + + public void validateToken(String token, Member member) { + try { + JwtParser jwtParser = getJwtParser(member); + jwtParser.parseClaimsJws(token); + } catch (JwtException | IllegalArgumentException e) { + throw new InvalidTokenException(); + } + } + + public String getPayLoad(String token, Member member) { + JwtParser jwtParser = getJwtParser(member); + return jwtParser.parseClaimsJws(token) + .getBody() + .getSubject(); + } + + private JwtParser getJwtParser(Member member) { + return Jwts.parser() + .setSigningKey(getSecretKey(member)); + } + + public boolean isValidToken(String token, Member member) { + try { + validateToken(token, member); + return true; + } catch (InvalidTokenException e) { + return false; + } + } +} diff --git a/src/main/java/com/server/hispath/auth/infrastructure/OauthHandler.java b/src/main/java/com/server/hispath/auth/infrastructure/OauthHandler.java new file mode 100644 index 0000000..9403270 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/infrastructure/OauthHandler.java @@ -0,0 +1,30 @@ +package com.server.hispath.auth.infrastructure; + +import java.util.Map; + +import com.server.hispath.auth.domain.Member; +import com.server.hispath.auth.domain.OauthAttributes; +import com.server.hispath.auth.domain.OauthProvider; +import com.server.hispath.auth.domain.OauthUserInfo; +import com.server.hispath.exception.oauth.UnsupportedOauthProviderException; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class OauthHandler { + private final Map oauthProviders; + private final ApiRequester apiRequester; + + public OauthUserInfo getUserInfoFromCode(String oauthProvider, String code, Member member) { + OauthProvider oauth = getOauthProvider(oauthProvider); + Map attributes = apiRequester.getUserInfo(code, oauth, member); + return OauthAttributes.extract(oauthProvider, attributes); + } + + private OauthProvider getOauthProvider(String oauthProvider) { + if (!oauthProviders.containsKey(oauthProvider)) { + throw new UnsupportedOauthProviderException(); + } + return oauthProviders.get(oauthProvider); + } +} diff --git a/src/main/java/com/server/hispath/auth/presentation/AuthController.java b/src/main/java/com/server/hispath/auth/presentation/AuthController.java new file mode 100644 index 0000000..3e4c5aa --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/AuthController.java @@ -0,0 +1,44 @@ +package com.server.hispath.auth.presentation; + +import com.server.hispath.auth.application.AuthService; +import com.server.hispath.auth.application.dto.LoginRequestDto; +import com.server.hispath.auth.application.dto.LoginResponseDto; +import com.server.hispath.auth.presentation.response.TokenResponse; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class AuthController { + private final AuthService authService; + + @GetMapping("/auth/{oauthProvider}/login-student/token") + public ResponseEntity loginStudent(@PathVariable String oauthProvider, @RequestParam String code) { + + LoginResponseDto loginResponseDto = authService.studentLogin(new LoginRequestDto(oauthProvider, code)); + return ResponseEntity.ok(TokenResponse.from(loginResponseDto)); + } + + @GetMapping("/auth/{oauthProvider}/login-manager/token") + public ResponseEntity loginManager(@PathVariable String oauthProvider, @RequestParam String code) { + + LoginResponseDto loginResponseDto = authService.managerLogin(new LoginRequestDto(oauthProvider, code)); + return ResponseEntity.ok(TokenResponse.from(loginResponseDto)); + } + + @GetMapping("/auth/login-student/guest/token") + public ResponseEntity loginGuestStudent() { + + return ResponseEntity.ok(new TokenResponse(false, authService.getStudentGuestToken())); + } + + @GetMapping("/auth/login-manager/guest/token") + public ResponseEntity loginGuestManager() { + + return ResponseEntity.ok(new TokenResponse(false, authService.getManagerGuestToken())); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/auth/presentation/LoginInterceptor.java b/src/main/java/com/server/hispath/auth/presentation/LoginInterceptor.java new file mode 100644 index 0000000..ef81759 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/LoginInterceptor.java @@ -0,0 +1,58 @@ +package com.server.hispath.auth.presentation; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.server.hispath.auth.application.AuthService; +import com.server.hispath.auth.domain.*; +import com.server.hispath.auth.infrastructure.JwtProvider; +import com.server.hispath.util.AuthorizationExtractor; + +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class LoginInterceptor implements HandlerInterceptor { + private final JwtProvider jwtProvider; + private final AuthService authService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if (isPreflight(request)) { + return true; + } + HandlerMethod handlerMethod = (HandlerMethod) handler; + if (!(hasAnnotation(handlerMethod))) { + return true; + } + String token = AuthorizationExtractor.extractAccessToken(request); + + if (handlerMethod.hasMethodAnnotation(RequiredStudentLogin.class)) { + jwtProvider.validateToken(token, Member.STUDENT); + } else if (handlerMethod.hasMethodAnnotation(RequiredManagerLogin.class)) { + jwtProvider.validateToken(token, Member.MANAGER); + } else if (handlerMethod.hasMethodAnnotation(RequiredLogin.class)) { + jwtProvider.validateBothToken(token); + } else if (handlerMethod.hasMethodAnnotation(RequiredSuperManagerLogin.class)) { + authService.checkSuperManagerByToken(token); + } + + return true; + } + + private boolean hasAnnotation(HandlerMethod handlerMethod) { + return handlerMethod.hasMethodAnnotation(RequiredLogin.class) + || handlerMethod.hasMethodAnnotation(RequiredStudentLogin.class) + || handlerMethod.hasMethodAnnotation(RequiredManagerLogin.class) + || handlerMethod.hasMethodAnnotation(RequiredSuperManagerLogin.class); + } + + private boolean isPreflight(HttpServletRequest request) { + return HttpMethod.OPTIONS.matches(request.getMethod()); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/auth/presentation/LoginManagerArgumentResolver.java b/src/main/java/com/server/hispath/auth/presentation/LoginManagerArgumentResolver.java new file mode 100644 index 0000000..f1087f6 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/LoginManagerArgumentResolver.java @@ -0,0 +1,37 @@ +package com.server.hispath.auth.presentation; + +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; + +import com.server.hispath.auth.application.AuthService; +import com.server.hispath.auth.domain.ManagerLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.util.AuthorizationExtractor; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +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 lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class LoginManagerArgumentResolver implements HandlerMethodArgumentResolver { + private final AuthService authService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(ManagerLogin.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + String accessToken = AuthorizationExtractor + .extractAccessToken(Objects.requireNonNull(webRequest.getNativeRequest(HttpServletRequest.class))); + return authService.findManagerByToken(accessToken); + } +} diff --git a/src/main/java/com/server/hispath/auth/presentation/LoginStudentArgumentResolver.java b/src/main/java/com/server/hispath/auth/presentation/LoginStudentArgumentResolver.java new file mode 100644 index 0000000..fc25ff3 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/LoginStudentArgumentResolver.java @@ -0,0 +1,36 @@ +package com.server.hispath.auth.presentation; + +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; + +import com.server.hispath.auth.application.AuthService; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.util.AuthorizationExtractor; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +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 lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class LoginStudentArgumentResolver implements HandlerMethodArgumentResolver { + private final AuthService authService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(StudentLogin.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + String accessToken = AuthorizationExtractor + .extractAccessToken(Objects.requireNonNull(webRequest.getNativeRequest(HttpServletRequest.class))); + return authService.findStudentByToken(accessToken); + } +} diff --git a/src/main/java/com/server/hispath/auth/presentation/LoginSuperManagerArgumentResolver.java b/src/main/java/com/server/hispath/auth/presentation/LoginSuperManagerArgumentResolver.java new file mode 100644 index 0000000..a2eadcf --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/LoginSuperManagerArgumentResolver.java @@ -0,0 +1,37 @@ +package com.server.hispath.auth.presentation; + +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; + +import com.server.hispath.auth.application.AuthService; +import com.server.hispath.auth.domain.ManagerLogin; +import com.server.hispath.auth.domain.SuperManagerLogin; +import com.server.hispath.util.AuthorizationExtractor; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +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 lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class LoginSuperManagerArgumentResolver implements HandlerMethodArgumentResolver { + private final AuthService authService; + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(SuperManagerLogin.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + String accessToken = AuthorizationExtractor + .extractAccessToken(Objects.requireNonNull(webRequest.getNativeRequest(HttpServletRequest.class))); + return authService.getSuperManagerId(accessToken); + } +} diff --git a/src/main/java/com/server/hispath/auth/presentation/response/TokenResponse.java b/src/main/java/com/server/hispath/auth/presentation/response/TokenResponse.java new file mode 100644 index 0000000..819d903 --- /dev/null +++ b/src/main/java/com/server/hispath/auth/presentation/response/TokenResponse.java @@ -0,0 +1,18 @@ +package com.server.hispath.auth.presentation.response; + +import com.server.hispath.auth.application.dto.LoginResponseDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TokenResponse { + private boolean needRegister; + private String token; + + public static TokenResponse from(LoginResponseDto loginResponseDto) { + return new TokenResponse(loginResponseDto.isNeedRegister(), loginResponseDto.getToken()); + } +} + diff --git a/src/main/java/com/server/hispath/category/application/CategoryService.java b/src/main/java/com/server/hispath/category/application/CategoryService.java new file mode 100644 index 0000000..0b52862 --- /dev/null +++ b/src/main/java/com/server/hispath/category/application/CategoryService.java @@ -0,0 +1,58 @@ +package com.server.hispath.category.application; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.category.application.dto.CategoryContentDto; +import com.server.hispath.category.application.dto.CategoryCUDto; +import com.server.hispath.category.domain.Category; +import com.server.hispath.category.domain.repository.CategoryRepository; +import com.server.hispath.exception.category.CategoryNotFoundException; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class CategoryService { + + private final CategoryRepository categoryRepository; + + @Transactional + public Long create(CategoryCUDto dto) { + Category savedCategory = categoryRepository.save(Category.from(dto)); + return savedCategory.getId(); + } + + @Transactional(readOnly = true) + public CategoryContentDto find(Long id) { + Category category = this.findById(id); + return CategoryContentDto.from(category); + } + + @Transactional(readOnly = true) + public List findAll() { + List categories = categoryRepository.findAll(); + return categories.stream() + .map(CategoryContentDto::from) + .collect(Collectors.toList()); + } + + @Transactional + public CategoryContentDto update(Long id, CategoryCUDto dto){ + Category category = categoryRepository.findById(id).orElseThrow(CategoryNotFoundException::new); + category.update(dto); + return CategoryContentDto.from(category); + } + + @Transactional + public void delete(Long id){ + categoryRepository.deleteById(id); + } + + public Category findById(Long id){ + return categoryRepository.findById(id).orElseThrow(CategoryNotFoundException::new); + } +} diff --git a/src/main/java/com/server/hispath/category/application/dto/CategoryCUDto.java b/src/main/java/com/server/hispath/category/application/dto/CategoryCUDto.java new file mode 100644 index 0000000..48cf416 --- /dev/null +++ b/src/main/java/com/server/hispath/category/application/dto/CategoryCUDto.java @@ -0,0 +1,18 @@ +package com.server.hispath.category.application.dto; + +import com.server.hispath.category.presentation.request.CategoryCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CategoryCUDto { + private String name; + + public static CategoryCUDto of(CategoryCURequest request) { + return new CategoryCUDto(request.getName()); + } +} diff --git a/src/main/java/com/server/hispath/category/application/dto/CategoryContentDto.java b/src/main/java/com/server/hispath/category/application/dto/CategoryContentDto.java new file mode 100644 index 0000000..f0e2a2a --- /dev/null +++ b/src/main/java/com/server/hispath/category/application/dto/CategoryContentDto.java @@ -0,0 +1,19 @@ +package com.server.hispath.category.application.dto; + +import com.server.hispath.category.domain.Category; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CategoryContentDto { + private Long id; + private String name; + + public static CategoryContentDto from(Category category) { + return new CategoryContentDto(category.getId(), category.getName()); + } +} diff --git a/src/main/java/com/server/hispath/category/application/dto/CategoryDto.java b/src/main/java/com/server/hispath/category/application/dto/CategoryDto.java new file mode 100644 index 0000000..af853c1 --- /dev/null +++ b/src/main/java/com/server/hispath/category/application/dto/CategoryDto.java @@ -0,0 +1,19 @@ +package com.server.hispath.category.application.dto; + +import com.server.hispath.category.domain.Category; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CategoryDto { + private Long id; + private String name; + + public static CategoryDto from(Category category) { + return new CategoryDto(category.getId(), category.getName()); + } +} diff --git a/src/main/java/com/server/hispath/category/domain/Category.java b/src/main/java/com/server/hispath/category/domain/Category.java new file mode 100644 index 0000000..b76ff0b --- /dev/null +++ b/src/main/java/com/server/hispath/category/domain/Category.java @@ -0,0 +1,51 @@ +package com.server.hispath.category.domain; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.*; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.category.application.dto.CategoryCUDto; +import com.server.hispath.common.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Where(clause = "deleted = false") +@Builder +@NoArgsConstructor +@AllArgsConstructor +@SQLDelete(sql = "UPDATE category SET deleted = true Where id = ?") +public class Category extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @OneToMany(mappedBy = "category") + private List activities = new ArrayList<>(); + + public void update(CategoryCUDto dto) { + this.name = dto.getName(); + } + + public static Category from(CategoryCUDto dto) { + return Category.builder() + .name(dto.getName()) + .build(); + } + + public static Category fromString(String category) { + return Category.builder().name(category).build(); + } + + +} diff --git a/src/main/java/com/server/hispath/category/domain/repository/CategoryRepository.java b/src/main/java/com/server/hispath/category/domain/repository/CategoryRepository.java new file mode 100644 index 0000000..f24a613 --- /dev/null +++ b/src/main/java/com/server/hispath/category/domain/repository/CategoryRepository.java @@ -0,0 +1,10 @@ +package com.server.hispath.category.domain.repository; + +import com.server.hispath.category.domain.Category; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryRepository extends JpaRepository { + Category findByName(String name); + +} diff --git a/src/main/java/com/server/hispath/category/presentation/CategoryController.java b/src/main/java/com/server/hispath/category/presentation/CategoryController.java new file mode 100644 index 0000000..8cec7a0 --- /dev/null +++ b/src/main/java/com/server/hispath/category/presentation/CategoryController.java @@ -0,0 +1,76 @@ +package com.server.hispath.category.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.category.application.CategoryService; +import com.server.hispath.category.application.dto.CategoryCUDto; +import com.server.hispath.category.application.dto.CategoryContentDto; +import com.server.hispath.category.presentation.request.CategoryCURequest; +import com.server.hispath.category.presentation.response.CategoryResponse; +import com.server.hispath.docs.ApiDoc; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class CategoryController { + + private final CategoryService categoryService; + + + @PostMapping("/category") + @ApiOperation(value = ApiDoc.CATEGORY_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@RequestBody CategoryCURequest request) { + Long savedId = categoryService.create(CategoryCUDto.of(request)); + return ResponseEntity.ok(savedId); + } + + + @GetMapping("/category/{id}") + @ApiOperation(value = ApiDoc.CATEGORY_READ) + @RequiredLogin + public ResponseEntity find(@PathVariable Long id) { + CategoryContentDto dto = categoryService.find(id); + CategoryResponse response = CategoryResponse.from(dto); + return ResponseEntity.ok(response); + } + + @GetMapping("/categories") + @ApiOperation(value = ApiDoc.CATEGORY_READ_ALL) + @RequiredLogin + public ResponseEntity> findAll() { + List dtos = categoryService.findAll(); + List responses = dtos.stream() + .map(CategoryResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @PutMapping("/category/{id}") + @ApiOperation(value = ApiDoc.CATEGORY_UPDATE) + @RequiredManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody CategoryCURequest request) { + CategoryContentDto dto = categoryService.update(id, CategoryCUDto.of(request)); + CategoryResponse response = CategoryResponse.from(dto); + + return ResponseEntity.ok(response); + } + + @DeleteMapping("/category/{id}") + @ApiOperation(value = ApiDoc.CATEGORY_DELETE) + @RequiredManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + categoryService.delete(id); + return ResponseEntity.ok(id); + } +} diff --git a/src/main/java/com/server/hispath/category/presentation/request/CategoryCURequest.java b/src/main/java/com/server/hispath/category/presentation/request/CategoryCURequest.java new file mode 100644 index 0000000..3e47898 --- /dev/null +++ b/src/main/java/com/server/hispath/category/presentation/request/CategoryCURequest.java @@ -0,0 +1,13 @@ +package com.server.hispath.category.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class CategoryCURequest { + private Long studentId; + private String name; +} diff --git a/src/main/java/com/server/hispath/category/presentation/response/CategoryResponse.java b/src/main/java/com/server/hispath/category/presentation/response/CategoryResponse.java new file mode 100644 index 0000000..7900313 --- /dev/null +++ b/src/main/java/com/server/hispath/category/presentation/response/CategoryResponse.java @@ -0,0 +1,21 @@ +package com.server.hispath.category.presentation.response; + +import com.server.hispath.category.application.dto.CategoryContentDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class CategoryResponse { + private Long categoryId; + private String name; + + public static CategoryResponse from(CategoryContentDto dto) { + return new CategoryResponse(dto.getId(), dto.getName()); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/common/BaseEntity.java b/src/main/java/com/server/hispath/common/BaseEntity.java new file mode 100644 index 0000000..34b830d --- /dev/null +++ b/src/main/java/com/server/hispath/common/BaseEntity.java @@ -0,0 +1,38 @@ +package com.server.hispath.common; + + +import java.time.LocalDateTime; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@MappedSuperclass +@NoArgsConstructor +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseEntity { + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + @CreatedDate + private LocalDateTime createdAt; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + @LastModifiedDate + private LocalDateTime updatedAt; + + private boolean deleted = Boolean.FALSE; + + public void deleteContent() { + deleted = true; + } + + +} diff --git a/src/main/java/com/server/hispath/common/TestController.java b/src/main/java/com/server/hispath/common/TestController.java new file mode 100644 index 0000000..259073c --- /dev/null +++ b/src/main/java/com/server/hispath/common/TestController.java @@ -0,0 +1,1399 @@ +package com.server.hispath.common; + +import java.time.LocalDate; +import java.time.Month; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.activity.domain.repository.ActivityRepository; +import com.server.hispath.auth.domain.*; +import com.server.hispath.category.domain.Category; +import com.server.hispath.category.domain.repository.CategoryRepository; +import com.server.hispath.department.domain.Department; +import com.server.hispath.department.domain.repository.DepartementRepository; +import com.server.hispath.exception.manager.ManagerNotFoundException; +import com.server.hispath.major.domain.Major; +import com.server.hispath.major.domain.repository.MajorRepository; +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.manager.domain.repository.ManagerRepository; +import com.server.hispath.notice.domain.Notice; +import com.server.hispath.notice.domain.repository.NoticeRepository; +import com.server.hispath.resume.application.ResumeService; +import com.server.hispath.resume.domain.Resume; +import com.server.hispath.resume.domain.repository.ResumeRepository; +import com.server.hispath.scholarship.application.ScholarshipService; +import com.server.hispath.scholarship.domain.repository.ScholarshipRepository; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.application.dto.StudentSimpleRefDto; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import lombok.Builder; +import lombok.RequiredArgsConstructor; + +@RestController +@Builder +@RequiredArgsConstructor +@RequestMapping("/test") +public class TestController { + + private final StudentRepository studentRepository; + private final CategoryRepository categoryRepository; + private final ActivityService activityService; + private final NoticeRepository noticeRepository; + private final MajorRepository majorRepository; + private final ManagerRepository managerRepository; + private final DepartementRepository departementRepository; + private final ActivityRepository activityRepository; + private final StudentService studentService; + private final ResumeRepository resumeRepository; + private final ResumeService resumeService; + private final ScholarshipRepository scholarshipRepository; + private final ScholarshipService scholarshipService; + + @GetMapping("/init/all") + public ResponseEntity initAll() { + saveCategory(); + saveMajor(); + saveDepartment(); + saveStudent(); + saveManager(); + saveNotice(); + saveActivities(); +// saveScholarship(); participant 실행 한 뒤 실행 +// saveParticipant(); init all에 포함 금지! 따로 실행 + // saveResumes(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/category") + public ResponseEntity initCategory() { + saveCategory(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/department") + public ResponseEntity initDepartment() { + saveDepartment(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/notice") + public ResponseEntity initNotice() { + saveNotice(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/activity") + public ResponseEntity initActivity() { + saveActivities(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/manager") + public ResponseEntity initManager() { + + saveManager(); + + return ResponseEntity.ok(null); + } + + @GetMapping("/init/major") + public ResponseEntity initMajor() { + saveMajor(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/student") + public ResponseEntity initStudent() { + saveStudent(); + return ResponseEntity.ok(null); + } + + @GetMapping("/init/participant") + public ResponseEntity initParticipant() { + saveParticipant(); + return ResponseEntity.ok(null); + } + + @GetMapping("/student/auth") + @RequiredStudentLogin + public ResponseEntity testStudentAuth(@StudentLogin LoginStudent loginStudent) { + System.out.println(loginStudent.getId()); + System.out.println(loginStudent.getStudentNum()); + return ResponseEntity.ok(null); + } + + @GetMapping("/manager/auth") + @RequiredManagerLogin + public ResponseEntity testManagerAuth(@ManagerLogin LoginManager loginManager) { + System.out.println(loginManager.getId()); + return ResponseEntity.ok(null); + } + + @GetMapping("init/resume") + public ResponseEntity initResume() { + + saveResumes(); + return ResponseEntity.ok(null); + } + + @GetMapping("init/scholarship") + public ResponseEntity initScholarship() { + + saveScholarship(); + + return ResponseEntity.ok(null); + } + + private void saveScholarship() { + List students = studentRepository.findAll(); + + List studentIds = students.stream() + .map(Student::getId) + .collect(Collectors.toList()); + + studentIds.forEach(id -> scholarshipService.create(id, "2022-2")); + studentIds.forEach(id -> scholarshipService.create(id, "2022-1")); + studentIds.forEach(id -> scholarshipService.create(id, "2021-2")); + + + // List studentIds2022_2 = students.stream() + // .map(Student::getId) + // .collect(Collectors.toList()); + // Collections.shuffle(studentIds2022_2); + // int num2022_2 = getRandomNum(students.size() - 10, students.size()); + // studentIds2022_2.subList(0, num2022_2) + // .forEach(id -> { + // scholarshipService.create(id, "2022-2"); + // }); + // + // + // List studentIds2022_1 = students.stream() + // .map(Student::getId) + // .collect(Collectors.toList()); + // Collections.shuffle(studentIds2022_1); + // int num2022_1 = getRandomNum(students.size() - 10, students.size()); + // studentIds2022_1.subList(0, num2022_1) + // .forEach(id -> { + // scholarshipService.create(id, "2022-1"); + // }); + // + // + // List studentIds2021_2 = students.stream() + // .map(Student::getId) + // .collect(Collectors.toList()); + // Collections.shuffle(studentIds2021_2); + // int num2021_2 = getRandomNum(students.size() - 10, students.size()); + // studentIds2021_2.subList(0, num2021_2) + // .forEach(id -> { + // scholarshipService.create(id, "2021-2"); + // }); + + } + + private void saveResumes() { + Student student = studentService.findById(1L); + resumeRepository.save(Resume.builder() + .student(student) + .title("첫번째 이력서") + .content("jsonData가 들어가야해") + .build()); + resumeRepository.save(Resume.builder() + .student(student) + .title("두번째 이력서") + .content("jsonData가 들어가야해") + .build()); + resumeRepository.save(Resume.builder() + .student(student) + .title("세번째 이력서") + .content("jsonData가 들어가야해") + .build()); + resumeRepository.save(Resume.builder() + .student(student) + .title("네번째 이력서") + .content("jsonData가 들어가야해") + .build()); + resumeRepository.save(Resume.builder() + .student(student) + .title("다섯번째 이력서") + .content("jsonData가 들어가야해") + .build()); + resumeRepository.save(Resume.builder() + .student(student) + .title("여섯번째 이력서") + .content("jsonData가 들어가야해") + .build()); + } + + + public int getRandomNum(int start, int end) { + // Start 에서 End까지의 랜덤 수 출력 + return (int) (Math.random() * end - start) + start; + } + + + public void saveParticipant() { + List activities = activityRepository.findAll(); + List students = studentRepository.findAll(); + AtomicInteger cnt = new AtomicInteger(); + activities.forEach(activity -> { + + // int num = getRandomNum(15, students.size()); + List refStudent = students.stream() + .map(student -> { + return new StudentSimpleRefDto(student.getStudentNum(), student.getName()); + }) + .collect(Collectors.toList()); + cnt.getAndIncrement(); + studentService.registerParticipants(activity.getId(), refStudent, cnt.get() %7); + // Collections.shuffle(refStudent); + // studentService.registerParticipants(activity.getId(), refStudent.subList(0, num)); + activity.updateStudentRegister(); + }); + + } + + private void saveManager() { + managerRepository.save(Manager.builder() + .name("이정재 교수님") + .email("kkim@handong.ac.kr") + .department("CSEE") + .profile("https://user-images.githubusercontent.com/63008958/203914314-2eb9a33d-efab-4f08-80cf-ce00757d232a.jpeg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("아이유 교수님") + .email("jerry1004@handong.ac.kr") + .department("CSEE") + .profile("https://user-images.githubusercontent.com/63008958/203914299-6d707193-28ab-457c-8d03-51efb758072d.jpeg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("송중기 박사님") + .email("janggiryeo@handong.ac.kr") + .department("JGR") + .profile("https://user-images.githubusercontent.com/63008958/203914292-50d8abb3-8e7a-45c1-90ca-22bc156b1165.jpeg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("공유 총장님") + .email("cds@handong.ac.kr") + .department("HGU") + .profile("https://user-images.githubusercontent.com/63008958/203914306-5dbc47d3-ae07-4314-8708-abef0fcdd7c1.jpeg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("김태리 선생님") + .email("cgh@handong.ac.kr") + .department("SW") + .profile("https://user-images.githubusercontent.com/63008958/203914310-b00e05a7-c827-4247-945c-737ac56eeaf1.jpeg") + .approved(false).build()); + + managerRepository.save(Manager.builder() + .name("이지은 선생님") + .email("lyj@handong.ac.kr") + .department("SW") + .profile("https://user-images.githubusercontent.com/63008958/203914295-2fc460fe-3998-4f3c-b298-fff9a6c5676a.jpeg") + .approved(false).build()); + + managerRepository.save(Manager.builder() + .name("손예진 선생님") + .email("lmn@handong.ac.kr") + .department("SW") + .profile("https://user-images.githubusercontent.com/63008958/203914281-9c0acb13-562b-45df-a16a-61015f6881ff.png") + .approved(true).build()); + managerRepository.save(Manager.builder() + .name("안병웅 관리자") + .email("BW_Ahn@handong.ac.kr") + .department("전산전자공학부") + .profile("https://user-images.githubusercontent.com/63008958/203915182-c8216b87-9e06-4a10-8efe-b8d0cb43b5af.png") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("박성진 괸리자") + .email("david@handong.ac.kr") + .department("글로벌리더쉽학부") + .profile("https://user-images.githubusercontent.com/63008958/203915214-b9d6ffef-b011-43a4-9a9b-bf160f88b07c.png") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("홍성헌") + .email("lukehongg@handong.ac.kr") + .department("전산전자공학부") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("이인혁") + .email("Bruse@handong.ac.kr") + .department("ICT 융합학부") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .approved(true).build()); + + managerRepository.save(Manager.builder() + .name("정수산나") + .email("Sanna@handong.ac.kr") + .department("경영경제학부") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .approved(false).build()); + + managerRepository.save(Manager.builder() + .name("정석민") + .email("PeterJung@handong.ac.kr") + .department("글로벌리더쉽학부") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .approved(false).build()); + + managerRepository.save(Manager.builder() + .name("송다빈") + .email("Emerson@handong.ac.kr") + .department("전산전자공학부") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .approved(true).build()); + } + + + private void saveNotice() { + List l = new ArrayList(); + for (Long i = Long.valueOf(1); i < 8; i++) { + if (i != 5 && i != 6) { + Manager temp = managerRepository.findById(i).orElseThrow(ManagerNotFoundException::new); + l.add(temp); + } + } + + noticeRepository.save(Notice.builder() + .manager(l.get(1)) + .title("원클릭 컴공 전공 상담신청 서비스 안내") + .content("

상담 받기 좋은 계절입니다.

 

질문거리, 고민거리는 있지만 어느 교수님께 물어야 할 지 모르겠다면...

교수님께 상담 요청 이메일, 어떻게 써야 할지 몰라 망설여지신다면...

편하게 이것저것 여쭤보고 싶은데 안면 있는 교수님이 없어 막막하시다면...

 

원클릭 컴공 전공상담신청을 이용해보시기 바랍니다!

 

 https://forms.gle/n8mvzfJ51Ahzaujz8

 

접수한 내용을 바탕으로 가능한 빨리 적절한 교수님을 찾아 매칭해드립니다. 

 

학생 이메일 도메인 변경에 따라 Google Form 주소도 업데이트 했으니

참고하시기 바랍니다.

 

- 홍신

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 19)) + .expDate(LocalDate.of(2023, Month.APRIL, 26)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(2)) + .title("2022 BizFlow M Pre-Contest (신청기간연장 ~6.7(화))") + .content("\"

■  접수기간 : 2022년 5월 25일 (수) ~ 6월 7일 (화)

 

 ■  접수링크 : https://docs.google.com/forms/d/1BR9IKalGSdDPKR4Hi6dvW8dpL57dKhvfz0oliJatRno/edit

         

 ■  참가자격

      한동대학교 재학생으로서 다음 사항 중 1개라도 해당되는 팀 (휴학생 팀원 참여 가능)

      1) 팀원 중 BizFlow Camp 수료자가 있는 경우

      2) 팀원 중 이전 BizFlow AppDev Contest 수상자(참가상 포함)가 있는 경우

      3) 팀원 중 BizFlow AppDev 사용 경험자가 있는 경우

      4) 팀원 모두 BizFlow AppDev 사용 경험은 없지만, 웹사이트 제작 경험이 있는 경우 

 

 ■ 컨테스트 내용   

     。사전 제시된 미션을 BizFlow M을 사용하여 구현한 후, 기한 내에 제출함 

     。미션 링크 : https://www.notion.so/HGU-X-AppDev-2022-Precontest-473e3aed71554cf2899238fd49ca3d6b

     。컨테스트 미션에 대한 설명 영상 : https://youtu.be/od_lQFIrj7g

     。이번 컨테스트 진행 중 질문답변을 위해 다음 링크를 사용하기 바랍니다.    

       클라썸 입장 링크www.classum.com/EXSTQA 

 

 ■ 팀 구성 : 1~3인으로 팀 구성 (개인 참가 가능)



 ■ 수상팀에게는 여름방학 중에 진행되는 본 컨테스트 출전 자격이 주어집니다.

    1) 최우수상 : 1팀 60만원

     2) 우수상 : 5팀 내외 40만원

     3) 장려상 : 10팀 내외 20만원

     4) 참가상 : 기념품 지급



\"") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 24)) + .expDate(LocalDate.of(2023, Month.MAY, 30)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(3)) + .title("2022-2 사전 학점인정 안내(타대학 교환·학점교류)") + .content("

22-2학기 타대학 교환·학점교류를 통해 전산전자공학부공학부의 컴퓨터공학(심화), 전자공학(심화) 전공 학점으로 인정받고자 하는 학생은, 아래의 내용을 확인하시고 사전학점인정원 제출하시기 바랍니다.



1. 신청기간: ~2022.8.14.

     * 각 대학마다 수강신청기간이 다르므로, 본인 대학 수강신청기간 전에 신청 바람



2. 제출서류: 사전학점인정원, 해당 과목 강의계획서



3. 제출방법: csee@handong.edu로 온라인 제출



4. 사전학점인정 절차

  가. 학생이 학부사무실로 사전학점인정원 제출

  나. 해당 전공의 프로그램위원회에서 제출된 자료 검토하여 학점인정 여부 판단

  다. 검토완료 된 사전학점인정원을 학부사무실에서 학생 메일로 송부



5. 유의사항

  가. 각 대학마다 수강신청기간이 다르므로, 사전학점인정 승인 받은 후 수강신청 할 수 있도록 시간 여유를 두고 미리 신청 바람

  나. 본인서명 필수 /  담당교수 확인란은 비워 제출

  다. '해당전공'란은 컴퓨터공학 or 전자공학을 기입

  라. 이전 학기에 학점교류를 통해 전공 인정받은 학생의 경우 아래 내용 함께 제출

    1) 이전 교류대학명: 

    2) 인정 과목명:

    3) 총 인정학점:

  마. 사전학점인정원 승인을 받았더라도, 다른 수강 교과목과 내용이 중복되는 경우 추후 학점인정을 받지 못할 수 있음





문의 : 260-1414 / csee@handong.edu

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 2)) + .expDate(LocalDate.of(2023, Month.JUNE, 15)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(4)) + .title("2022년 8월 졸업생 학위증 및 상장 교부 안내") + .content("

9/2(금) 15시까지 신청 건 우편 발송되었습니다. 

 

---------------------------------------------------------------------------

 

안녕하세요?

전산전자공학부공학부입니다.



졸업을 진심으로 축하드립니다.\uD83C\uDF89



학위증은 8/17(수)부터 학부사무실(NTH309)에서 직접 수령 가능합니다.



우편(착불 4500원 정도)으로 받고자 하는 학생은 

9/4(일)까지 구글폼( https://forms.gle/YC33x2dgMp2o6FFP7 ) 작성해주시기 바랍니다.



이전 졸업생 중 학위증을 수령하지 않은 학생도 신청하시기 바랍니다.



<유의사항>

1. 학위증은 23년 2월 학위수여식까지 보관하며, 그 후 분실에 대해 책임지지 않습니다.

2. 학위증 재발급은 불가하니, 꼭 수령하시기 바랍니다.



감사합니다:D



문의) 전산전자공학부공학부사무실 260-1414

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 7)) + .expDate(LocalDate.of(2023, Month.JUNE, 29)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(4)) + .title("2022년 8월 졸업생 학위증 및 상장 교부 안내") + .content("

9/2(금) 15시까지 신청 건 우편 발송되었습니다. 

 

---------------------------------------------------------------------------

 

안녕하세요?

전산전자공학부공학부입니다.



졸업을 진심으로 축하드립니다.\uD83C\uDF89



학위증은 8/17(수)부터 학부사무실(NTH309)에서 직접 수령 가능합니다.



우편(착불 4500원 정도)으로 받고자 하는 학생은 

9/4(일)까지 구글폼( https://forms.gle/YC33x2dgMp2o6FFP7 ) 작성해주시기 바랍니다.



이전 졸업생 중 학위증을 수령하지 않은 학생도 신청하시기 바랍니다.



<유의사항>

1. 학위증은 23년 2월 학위수여식까지 보관하며, 그 후 분실에 대해 책임지지 않습니다.

2. 학위증 재발급은 불가하니, 꼭 수령하시기 바랍니다.



감사합니다:D



문의) 전산전자공학부공학부사무실 260-1414

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 21)) + .expDate(LocalDate.of(2023, Month.JUNE, 27)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(3)) + .title("[BK21 인공지능 교육연구단] 2022-2 참여대학원생 등록서류 제출 및 연구장학금 신청 안내") + .content("

한동대학교 BK21 인공지능 사업단

2022학년도 2학기 참여대학원생 등록서류 제출 및 연구장학금 신청 안내

 

 

한동대학교 전산전자공학부공학과 4단계 BK21 ‘산업혁신을 위한 AI 고급 인재교육연구단’ (BK21 인공지능사업단)에서 다음과 같이 등록 서류를 제출하여주시기 바랍니다.

 


1. 4단계 BK21 참여대학원생 기준 (다음의 조건을 모두 충족한 자)

BK21 참여교수의 지도학생 중 전일제(4대보험에 가입되어 있지 않은 학생)로 등록(연구생 등록 포함)한 석·박사과정 대학원생으로 다음 각 호에 해당하는 자

-입학한 지 2년이 지나지 않은 석사과정생

-입학한 지 4년이 지나지 않은 박사과정생 및 박사 수료생

-입학한 지 6년이 지나지 않은 석박통합과정생 및 석박통합과정 수료생

(위의 기간 기산 시 휴학 및 군복무 기간은 제외함).

 

위의 자격을 충족한 경우 ‘참여대학원생’으로 등록되어 ‘지원대학원생’ 선발 기회 등 BK21 사업의 지원을 받을 수 있음.

 

2. 지원대학원생 선발 및 연구장학금 지급

1) 참여대학원생으로 등록된 학생 중 70% 이내의 대학원생을 ‘지원대학원생’으로 선발해 연구장학금을 지급함.

2) 지원기간: 2022.09.01.~2023.02.28. (6개월 단위로 선발)

3) 선발기준: 지도교수 추천을 받은 참여대학원생 중 연구/프로젝트 성과 평가에 의해 선발

4) 역할 및 임무

- BK21 참여교수 연구실에서 논문 연구 및 산학 프로젝트를 성실히 수행 (주 40시간 이상)

- 사업단이 주관하는 각종 세미나, 포럼 등의 학술 활동에 참여

- 사업단이 요구하는 성과 자료 보고

 


3. 참여대학원생 등록서류 제출안내(등록서류는 단순참여, 장학금 지원 받는 학생 모두 제출해주세요.)

1) 첨부된 제출서류 다운 및 작성 후 BK21 사업단 사무실로 서류 제출.

2) 지도교수로부터 지원대학원생(장학금 받는 학생)으로 추천받은 대학원생은 5.제출서류 함께 제출

 

4. 서류 제출 기간: 2022년 8월 29일(월) 13:00 - 9월 7일(수) 17:00 (제출기한 엄수)




5. 제출서류

- 연구자등록번호 발급 방법

: KRI(한국연구업적통합정보시스템 http://www.kri.go.kr)에 접속 회원가입→연구자등록번호 발급 

  (가입 시 소속을 반드시 ‘한동대학교’로 가입) 



1) 재학증명서 1부. 연구생등록자의 경우 연구생등록증 1부(2022년 9월 1일자 기준으로 제출)

2) 개인정보 수집 이용 제공 동의서 1부. (BK사업에 처음 참여하는 학생만 제출)

3) 참여인력 서약서 1부. 

4) 참여대학원생 확약서 1부.

5) BK21 연구장학금 신청서 1부. (지원대학원생-BK장학금 받는 학생만 제출)

6) 전산전자공학부공학과 학기 보고서 1부.

7) 재학증명서 1부.(9월 1일 기준)

 

8) 연구재단 필수 제출 서류 '4대 보험 가입 증명서' 1부. (22.10.1일 기준일로하여 메일로 회신)

(**10월1일 기준으로 출력 후 제출 바랍니다. 9월에는 제출하지 않아도 됩니다!)

- 출력 방법: 4대 사회보험 포털서비스(http://www.4insure.or.kr) 로그인(회원가입, 공인인증서 필요) → 상단 메뉴 증명서발급(가입내역확인) 클릭 후 출력

 

9) 대학원 성적표 1부. (신입생은 제출X)

 

<한국연구재단 필수 수강!!-참여기간 중 1회 수강 후 수료증 제출해야함, 교육 미이수자 및  22-2학기 신입생만 수강하면 됩니다.>

10) 온라인 교육 수료증 (http://alpha-campus.kr/) 에 접속하여 로그인 후 상단 메뉴의 '탐색'->'온라인교육' -> '건강한 연구환경 조성을 위한 인권침해예방교육'클릭 ->'수강신청' 클릭 후 팝업창에서 수강신청 정보 확인 및 '신청완료'-> '학습'-> '학습중과정'-> '건강한 연구환경 조성을 위한 인권침해예방교육' 순서대로 클릭 후 '학습하기'

컨텐츠 수강 후 ‘MY'-> '학습이력'클릭 후 수료증 발급 및 보관) 

*수료증은 메일로 회신부탁합니다. 

 

11) 통장사본 및 신분증 사본 각 1부.

 

※ 외국인 참여대학원생의 경우 외국인 등록증 앞, 뒤 사본(D-2비자 여부 및 만료기한 확인) 제출.

※ 기존 참여대학원생이 지원할 경우: 2)개인정보 수집 이용 제공 동의서, 10)온라인 교육 수료증 제출 생략.

 

6. 서류 제출 및 문의처

1) BK21사업단 사무실: 뉴턴홀 309호 전산전자공학부공학부 사무실 담당자 고라경(Tel: 260-3150)

2) 신청 시 모든 서류는 위 제출서류 순서대로 정리하여 원본 제출 바랍니다.

 

7. 유의사항: 제출된 서류는 반환하지 않으며, 허위사실 기재 시 선발을 취소함.

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2022, Month.JULY, 1)) + .expDate(LocalDate.of(2022, Month.JULY, 14)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(2)) + .title("2022 한동 SW페스티벌 수상자 안내 및 서류 제출 요청(10월 19일(수)까지)") + .content("

2022 한동 SW페스티벌 수상자 안내 및 서류 제출 요청(10월 19일(수)까지)

  

'2022 한동 SW페스티벌'에 참여한 모든 참가자들에게 감사드리며 수상팀을 안내드립니다. 

자세한 수상팀 명단은 첨부파일에서 확인 가능합니다.

수상한 모든 팀들 축하드립니다. 



[상금]

수상팀 제출 서류는 아래 설문지를 통해 팀대표 1명만 제출바랍니다.(팀장이 대표로 수령)

서류 제출 마감일은 10월 19일(수)입니다. 빠른 상금 수령을 위해 마감 기한을 꼭 지켜주세요!!

설문지로 바로이동



[상장]

배부기간: 10.20(목) ~ 21(금). 팀별 1부 발급

배  부  처: SW중심대학지원사업단, 뉴턴홀 218호

   * 상장 수령 시 개인정보 이용 동의서 서명도 함께 해주세요.

 

 

문의 : SW중심대학 지원사업단 이윤정(260-1478 / lyj1515@handong.edu)

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2022, Month.JULY, 7)) + .expDate(LocalDate.of(2022, Month.JULY, 12)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(1)) + .title("[전산전자공학부공학부] 2022 CSEE Lab Week에 초대합니다.") + .content("

안녕하세요?

전산전자공학부공학부, 일반대학원 전산전자공학부공학과가 9주차 10/24(월)~10/28(금)에 각 연구실에 대해 알아가고 다양한 연구의 내용을 공유하는 시간을 가지려고 합니다. 



저희 전산전자공학부공학부, 일반대학원 전산전자공학부공학과에서 어떤 주제의 연구들을 진행하고 있는지 Lab설명회, 포스터세션을 통해 이야기를 듣고 싶은 학생들의 많은 참여 바랍니다. 



행사에 참석하면 입시관련된 정보 또한 얻을 수 있으니 AI를 포함한 ICT 관련 분야 진학에 관심있는 모든 학부생들의 참여를 환영합니다. 



\"d24;\"온라인 Lab 멘토링 실시 (기간: 10/24(월)~10/28(금))

(아래 링크접속 후 각 Lab의 오픈카톡방을 통한 자유로운 상담 가능)


https://docs.google.com/document/d/1vPNIac3vfuBxzr3-IsqVqEAFwJtA-6dXiE_RvKhXJHo/edit#

 

 

\"d24;\" Lab토크쇼(10/27(목) 18시30분~) 사전질문 작성

제출된 질문은 Lab 토크쇼에서 활용되며, 추첨을 통하여 커피쿠폰을 드립니다.

https://forms.gle/a8XWyqXcTec8vdwq5

 

 

\"d24;\" CSEE Lab Week 행사 참석 희망자(만찬 참여 포함)는 아래 설문지 필수 작성


https://docs.google.com/forms/d/1wkUWbYgcPFFTfrI-M3aOonQYRd_Oq6VHugJx6rVkuRE/edit?pli=1



**10/28(금)** 포스터세션이 종료되고 만찬(오후 5시 예정)이 있을 예정입니다.

만찬은 인원수 제한으로 선착순으로 신청을 받습니다.






\"\uD83C\uDF81\"event\"\uD83C\uDF81\" CSEE Lab Week 참가자 커피쿠폰 증정 

 

 

* 문의: 전산전자공학부공학과 고라경 선생님 (전화: 054-260-3150)

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2022, Month.AUGUST, 5)) + .expDate(LocalDate.of(2022, Month.AUGUST, 25)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(0)) + .title("2022-2 비교과 졸업요건 서류 제출 안내(~12/16)") + .content("

안녕하세요?

17학번이후인 1전공 컴퓨터공학/AI·컴퓨터공학심화 학생 중 캡스톤디자인 교과목 수강생 및 2023.2월 졸업예정자에게 안내드립니다.

비교과 졸업요건 만족 여부 확인을 위해 첨부 된 양식 작성하여 구글폼으로 제출해주시기 바랍니다.

   * 비교과 졸업요건은 히즈넷-학생 졸업심사화면의 '학부추가졸업요건'에 해당합니다.

   * 해당 학생들에게는 문자로 안내하였습니다.

<17학번부터 적용되는 비교과 졸업요건>

- 산학프로젝트 1개 이상 수행 (산학R&D프로젝트, 또는 산학연계 교과목프로젝트 (예: 캡스톤디자인))

- 캡스톤프로젝트 결과물 등을 특허, 논문, SW시제품 중 한 가지 형태로 1건 이상 제출하여야 함 (공동 출원자/저자 모두 인정).

- 비교과 졸업요건은 캡스톤디자인 과목을 산학 주제로 수행한 결과를 논문 발표, 특허출원, 또는 SW등록함으로써 자연스럽게 충족 가능함.

1. 제출기한: 16주차 금요일(12/16)까지

2. 제출방법: 구글폼(https://forms.gle/Q7X1VfJL176h2TJ38) 제출

  - 23.2월에 졸업하는 경우, 12/16(금)까지 제출하셔야 졸업 가능합니다.(다음학기 ‘학사학위취득유예’ 학생 포함)

  - 23.2월에 졸업하지 않는 경우, 다음 학기에 제출하실 수 있습니다.(구글폼에 '졸업안함' 제출)

3. 참고사항

  가. 이전에 증빙서류로 제출하였던 사례

    1) 논문: 정식 게재된 목차 및 논문 스캔본, 발표 포스터 스캔본

    2) 특허: 특허청의 공식 문서로 출원번호 또는 등록번호와 발명자 정보(주소지 포함)가 기재되어 있는 서류

                 (특허출원서, 특허증, 공개특허공보, 등록특허공보 중 1개 선택)

    3) 시제품제작 (아래 3개 항목 중 1가지 선택)

      가) SW등록: SW등록증, 프로그램등록신청명세서, 저작권 등록증 등

      나) 앱 출시: 출시 된 앱의 스토어 게시 화면 캡쳐 이미지, 앱 출시 확인서 사본 등

      다) 상용서비스 수준 확인 : 산학프로젝트 참여 기업체의 담당자 또는 기업체 멘토가 작성한 시제품 확인서(첨부 양식)

  나. 자주묻는질문

    1) 비교과 졸업요건을 충족하기 위한 결과물은 꼭 캡스톤디자인의 결과물이어야 하나요?

          - 반드시 캡스톤 결과물이어야 할 필요는 없습니다.

    2) 저작권 등록을 한 학생이 대표로 하게되어 등록증에 한명의 이름만 기재되는데 어떻게 하나요?

          - 등록증에 들어있는 제목과 캡스톤 제목이 일치하면 같은 팀원에게 동일하게 적용됩니다.                                            다만, 서류는 개인별로 제출하셔야 합니다.



문의) csee@handong.edu

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.DECEMBER, 8)) + .expDate(LocalDate.of(2023, Month.DECEMBER, 16)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(0)) + .title("[이랜드이노플] 채용설명회 안내 및 수요조사") + .content("

안녕하세요:) 반갑습니다.

이랜드이노플 인사팀입니다.



금번 [이랜드이노플X한동대학교] 채용설명회에 참여해주시는 분들께 감사의 의미로 간식 및 기념품을 제공해드리고자 수요조사를 진행하게 되었습니다. 일정은 아래와 같이 진행되며, 참석을 원하시는 분들께서는 본 설문에 응답해주시기를 부탁드립니다:)

 

1. 채용설명회

  가. 일시: 2022.11.16(수) 12:00~12:50

  나. 장소: 뉴턴홀 310호

  다. 참석 혜택

    - 채용설명회에 발걸음 해주시는 학생분들께 아래와 같은 혜택을 드리고자 합니다.

      1) 서류전형 시 가산점 부여

      2) 기념품 제공

      3) Q&A 시간에 학생분들이 궁금해하시는 포인트들을 최대한 답변해드리고자 합니다.

    + (한동대 Only) 간식 제공> [한동대] 이랜드이노플 채용설명회 참여 신청서: https://forms.gle/s9B5JbDPsviRBEoq5

 

2. 채용 안내

  가. 채용일정: 2022.11.4(금)~11.21(월)

  나. 이랜드이노플 채용 관련 링크

    - 채용사이트: https://careers.eland.co.kr/announce/recruit/hxKeGGXNip4urmc1ZmHDz7PJVJ2-

    - Notion 이노플 공채 블로그: https://elandinnople.oopy.io/38d9b929-de4f-46eb-8234-d5b231973e74

    - 네이버블로그: https://blog.naver.com/elandinnople

 

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2023, Month.MARCH, 6)) + .expDate(LocalDate.of(2023, Month.SEPTEMBER, 26)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(1)) + .title("[대학원] 세미나(11월 11일, 손현우 교수)-아날로그 연산기 기반의 학습가능한 신경망 시스템") + .content("

한동대학교 BK21 인공지능 사업단

2022학년도 2학기 참여대학원생 등록서류 제출 및 연구장학금 신청 안내

 

 

한동대학교 전산전자공학과 4단계 BK21 ‘산업혁신을 위한 AI 고급 인재교육연구단’ (BK21 인공지능사업단)에서 다음과 같이 등록 서류를 제출하여주시기 바랍니다.

 


1. 4단계 BK21 참여대학원생 기준 (다음의 조건을 모두 충족한 자)

BK21 참여교수의 지도학생 중 전일제(4대보험에 가입되어 있지 않은 학생)로 등록(연구생 등록 포함)한 석·박사과정 대학원생으로 다음 각 호에 해당하는 자

-입학한 지 2년이 지나지 않은 석사과정생

-입학한 지 4년이 지나지 않은 박사과정생 및 박사 수료생

-입학한 지 6년이 지나지 않은 석박통합과정생 및 석박통합과정 수료생

(위의 기간 기산 시 휴학 및 군복무 기간은 제외함).

 

위의 자격을 충족한 경우 ‘참여대학원생’으로 등록되어 ‘지원대학원생’ 선발 기회 등 BK21 사업의 지원을 받을 수 있음.

 

2. 지원대학원생 선발 및 연구장학금 지급

1) 참여대학원생으로 등록된 학생 중 70% 이내의 대학원생을 ‘지원대학원생’으로 선발해 연구장학금을 지급함.

2) 지원기간: 2022.09.01.~2023.02.28. (6개월 단위로 선발)

3) 선발기준: 지도교수 추천을 받은 참여대학원생 중 연구/프로젝트 성과 평가에 의해 선발

4) 역할 및 임무

- BK21 참여교수 연구실에서 논문 연구 및 산학 프로젝트를 성실히 수행 (주 40시간 이상)

- 사업단이 주관하는 각종 세미나, 포럼 등의 학술 활동에 참여

- 사업단이 요구하는 성과 자료 보고

 


3. 참여대학원생 등록서류 제출안내(등록서류는 단순참여, 장학금 지원 받는 학생 모두 제출해주세요.)

1) 첨부된 제출서류 다운 및 작성 후 BK21 사업단 사무실로 서류 제출.

2) 지도교수로부터 지원대학원생(장학금 받는 학생)으로 추천받은 대학원생은 5.제출서류 함께 제출

 

4. 서류 제출 기간: 2022년 8월 29일(월) 13:00 - 9월 7일(수) 17:00 (제출기한 엄수)




5. 제출서류

- 연구자등록번호 발급 방법

: KRI(한국연구업적통합정보시스템 http://www.kri.go.kr)에 접속 회원가입→연구자등록번호 발급 

  (가입 시 소속을 반드시 ‘한동대학교’로 가입) 



1) 재학증명서 1부. 연구생등록자의 경우 연구생등록증 1부(2022년 9월 1일자 기준으로 제출)

2) 개인정보 수집 이용 제공 동의서 1부. (BK사업에 처음 참여하는 학생만 제출)

3) 참여인력 서약서 1부. 

4) 참여대학원생 확약서 1부.

5) BK21 연구장학금 신청서 1부. (지원대학원생-BK장학금 받는 학생만 제출)

6) 전산전자공학과 학기 보고서 1부.

7) 재학증명서 1부.(9월 1일 기준)

 

8) 연구재단 필수 제출 서류 '4대 보험 가입 증명서' 1부. (22.10.1일 기준일로하여 메일로 회신)

(**10월1일 기준으로 출력 후 제출 바랍니다. 9월에는 제출하지 않아도 됩니다!)

- 출력 방법: 4대 사회보험 포털서비스(http://www.4insure.or.kr) 로그인(회원가입, 공인인증서 필요) → 상단 메뉴 증명서발급(가입내역확인) 클릭 후 출력

 

9) 대학원 성적표 1부. (신입생은 제출X)

 

<한국연구재단 필수 수강!!-참여기간 중 1회 수강 후 수료증 제출해야함, 교육 미이수자 및  22-2학기 신입생만 수강하면 됩니다.>

10) 온라인 교육 수료증 (http://alpha-campus.kr/) 에 접속하여 로그인 후 상단 메뉴의 '탐색'->'온라인교육' -> '건강한 연구환경 조성을 위한 인권침해예방교육'클릭 ->'수강신청' 클릭 후 팝업창에서 수강신청 정보 확인 및 '신청완료'-> '학습'-> '학습중과정'-> '건강한 연구환경 조성을 위한 인권침해예방교육' 순서대로 클릭 후 '학습하기'

컨텐츠 수강 후 ‘MY'-> '학습이력'클릭 후 수료증 발급 및 보관) 

*수료증은 메일로 회신부탁합니다. 

 

11) 통장사본 및 신분증 사본 각 1부.

 

※ 외국인 참여대학원생의 경우 외국인 등록증 앞, 뒤 사본(D-2비자 여부 및 만료기한 확인) 제출.

※ 기존 참여대학원생이 지원할 경우: 2)개인정보 수집 이용 제공 동의서, 10)온라인 교육 수료증 제출 생략.

 

6. 서류 제출 및 문의처

1) BK21사업단 사무실: 뉴턴홀 309호 전산전자공학부 사무실 담당자 고라경(Tel: 260-3150)

2) 신청 시 모든 서류는 위 제출서류 순서대로 정리하여 원본 제출 바랍니다.

 

7. 유의사항: 제출된 서류는 반환하지 않으며, 허위사실 기재 시 선발을 취소함.

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2023, Month.FEBRUARY, 9)) + .expDate(LocalDate.of(2023, Month.SEPTEMBER, 15)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(2)) + .title("[SW중심대] 11월 2일(수) 류석문 쏘카 CTO 특강 안내") + .content("

[SW중심대] 11월 2일(수) 류석문  쏘카 CTO 특강 안내






 

1. 강사 : 류석문 쏘카 CTO


2. 주제 :  프로그래머로 산다는 것

 

3. 일시 : 2022년 11월 2일 (수) 오후 1시 

 

4. 장소 : 오석관 405호, 401호,

 

5. 소감문 제출 방법 : 링크 접속 후 제출 (https://forms.gle/gRtNgqWtFnxYmMXVA)


    * 공프기 및 캡스톤 수강생 외 학생들은 강의 시청 후 반드시 소감문을 제출하셔야 합니다. (11. 4(금) 밤12시까지)







   ☎ 문의 : SW중심대학 지원사업단 김선영 (T.260-1492, E-Mail : pooh8276@handong.edu)

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.OCTOBER, 7)) + .expDate(LocalDate.of(2022, Month.OCTOBER, 28)) + .build()); + + noticeRepository.save(Notice.builder() + .manager(l.get(3)) + .title("일본 IT 강독 2022년 2학기 첫번쨰 모임이 이번주 수요일 11월 09일 저녁 8시에 열립니다.") + .content("

 일본 IT 강독   2022년 2학기 첫번? 모임이 이번주  수요일 11월 09일 저녁 8시에 열립니다.



2022년2학기 일본IT학회 주관 \"일본 IT 강독\"



일본의  IT시스템 개발문서, IT 트렌드 관련 일본어 기사 등을 같이 읽어 나가는 시간입니다. 일본은 IT시스템 개발과정에서 Documentation을 아주 철저히 하고 있습니다. 따라서 일본 IT 취업시 일본어를 읽고 쓰는 능력은 회화능력 이상으로 중요합니다. IT관련 일본어 문서를 읽어나가며 일본어를 더 공부하고 싶게 하고자 합니다.



본 시간은 22년이상 일본에서 IT개발자로서 일본인들과 함께 일해오신 일본 도레이쿠 김종환 대표님이 직접 강의합니다.



참여자격 : 일본어 초급 수준(한동대학교 일본어  I 수강 수준)



일정

제 1 차 모임. 11월 09일(수 저녁 8시) 11주차 

제 2 차 모임. 11월 23일(수 저녁 8시) 13주차 

 

줌 접속 주소

https://handong.zoom.us/j/82808657679



- 참석자에게는 마일리지가 부여됩니다.

- 문의 : 김기석 교수(peterkim@handong.edu) ,박훈성(01043417017 / 21800333@handong.ac.kr) 

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2023, Month.JANUARY, 1)) + .expDate(LocalDate.of(2023, Month.JULY, 7)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(2)) + .title("23-1학기 공학프로젝트기획(공프기) 사전신청 안내") + .content("

2023년 봄학기 공학프로젝트기획(공프기)을 수강하기 원하는 학생은

11월 6일까지 아래 링크의 웹사이트에서 사전 신청을 접수하시기 바랍니다.

http://walab.handong.edu/csc/

사전 신청은 공학프로젝트기획 주제 제안과 팀 구성 과정을 효율적으로 하기 위한 작업이니, 

수강 의사가 조금이라도 있다면 반드시 사전 신청을 접수하기 바랍니다.

사전신청에 접수한 학생에 한하여 관련 공지사항과 공프기 주제 제안 내용을 공개할 예정입니다.


  • 2023-1학기 공프기를 위한 일정 계획

    • 2022-2학기 9주차

      • CSEE Lab week (연구실 소개)

    • 2022-2학기 10주차

      • 2023-1학기를 위한 사전신청

      • 수강 예정 학생 수 파악 및 예상 프로젝트 팀 수 확정

    • 2022-2학기 12주차 ~

      • 주제 공개

      • 관심이 있는 주제/교수님께 개별 연락하여 팀 구성

") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.OCTOBER, 25)) + .expDate(LocalDate.of(2022, Month.OCTOBER, 31)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(3)) + .title(" 2022 한동대 C프로그래밍 컨테스트 안내") + .content("
  • 일시 : 2022년 12월 9일 15주차 금요일 오후 8시~10시(120분)

  • 대상 : 전교생 중 1학년 또는 SW관련 전공이 아닌 학생

  • 시험방법 : Replit.com 사이트에 온라인 접속 후 문제를 풀어 제출함(시험 중 구글링 또는 본인의 소스 참조 가능, 타인과 대화, 메시징, 이메일 금지)

  • 출제범위 : C프로그래밍 수업 전반

  • 문제 수 : 10문제 이내



▶ 컨테스트 관련 질문응답 : www.classum.com/EXZRQI 



▶ 시험 서버 접속 및 테스트 문제 풀이 : 2022년 12월 9일(금) 18시까지

  • Replit.com 링크에 접속한다. (Chrome 사용 권장)

  • https://replit.com/teams/join/whodntufxzxetztsmzbadhqtdqrfbzpn-HGUCContest

  • 만일 회원가입이 되어 있지 않다면 가입 후 로그인한다.

  • 본인 Profile에서 반드시 First name에 자신의 한글이름, Last name에 자신의 학번8자리를 기입할 것. (인적사항 확인불가 시 수상 제외)

  • 회원가입 후 이메일주소 인증할 것

  • 테스트용 문제를 확인하고, 문제를 해결하는 코드를 작성하여 실행해본다.

  • 테스트케이스를 실행해본 후, 제출(submit)한다.



▶ 컨테스트 참여 시 주의사항

  • 시험 시작 전에 Replit.com 링크에 접속한다. (Chrome 사용 권장)

  • https://replit.com/teams/join/whodntufxzxetztsmzbadhqtdqrfbzpn-HGUCContest

  • 시작시간이 되면 문제가 공개됩니다. (새로고침 필수)

  • 제한 시간 내에 공개된 문제를 최대한 해결하여 테스트케이스를 실행한 후, 제출(submit)한다. 반드시 순서대로 문제를 풀지 않아도 됨

  • 다음의 경우에는 제출 무효로 처리됨

    • Due date가 지난 후, 제출하는 경우

    • Due date가 지난 후, 문제를 다시 열어 보는 경우

    • Due date가 지난 후, 자신의 코드를 수정한 경우

    • 동일계정으로 동시에 2개 이상의 Replit.com 접속한 경우

▶ 채점 기준

  • 기준 1 : 성공적으로 해결하여 테스트케이스 모두 통과한 후, 제출한 문제 갯수가 많은 순

  • 기준 2 : 해결한 모든 문제의 평균제출시간이 빠른 순

  • 기준 3 : 미완성 제출 경우 통과된 테스트 케이스가 많은 순



▶ 참가자 혜택

  • 1문제 이상을 성공 제출한 모든 참가자에게 소중대 마일리지 적립

  • 우수자에게는 상금 지급 (1학년 또는 SW전공이력이 없는 학생만 수상)

    • 총상금 200만원

    • 대상 1명 : 20만원

    • 최우수상 5명 내외 : 각 15만원

    • 우수상 10명 내외 : 각 10만원

    • 장려상 : 각 5만원

  • 수상 규모는 변동될 수 있음



") + .viewCnt(0) + .importance(true) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 2)) + .expDate(LocalDate.of(2023, Month.NOVEMBER, 9)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(2)) + .title("[지역선도대학] 2022 대경권 대학생 AI프로그래밍 경진대회 개최") + .content("

2022 대경권 대학생 AI프로그래밍 경진대회 개최 









지역선도대학육성사업에서는 재학생들의 인공지능(AI) 컴퓨팅 사고역량, 프로그래밍 역량 문제해결 역량 강화 등을 위하여 2022 대경권 대학생 AI프로그래밍 경진대회를 개최합니다.





■ 접수기간: 2022. 10. 26.(수) ~ 11. 9.(수) 까지 

■ 접수방법: 대회 홈페이지에서 직접 신청(참가비 무료)



대회 홈페이지 주소 및 자세한 내용은 지역선도대학육성사업 홈페이지 → 온라인신청 → 진행프로그램에서 가능

(https://spoke.knu.ac.kr/03_sub/01_sub.html)



■ 문의 : 안영은 연구원(054-260-3124, aye3384@handong.edu)

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2023, Month.OCTOBER, 21)) + .expDate(LocalDate.of(2023, Month.OCTOBER, 27)) + .build()); + noticeRepository.save(Notice.builder() + .manager(l.get(0)) + .title("[CSEE Lab Week] Lab 토크쇼 관련 사전 질문") + .content("

안녕하세요. 컴퓨터 공학 전공 주임 안민규 교수입니다.

 

이전 글에 공지된 것처럼 다음 주 9주차에는 전산전자공학부공학부/전산전자공학부공학과가 CSEE Lab Week가 진행됩니다.

관련 글> https://hisnet.handong.edu/myboard/read.php?id=35135&Board=B0029

 

연구실에 관심이 있거나, 2023-1학기 공학프로젝트 기획 수강을 계획하는 학생들에게는 큰 도움이 될 것 같습니다.

 

 

각 연구실에 대하여 궁금한 점은 9주차 동안 진행되는 Lab 멘토링을 통해 문의하고 답변을 받기 바랍니다.

또한, 목요일 18:30에는 CSEE 연구실, 연구실 생활, 졸업 프로젝트, 진로 등에 관하여 이야기를 교수님들과 나눌 수 있는 자리를 마련하였으니 많은 학생들이 참여하여 정보를 얻는 시간이 되길 빕니다.

 

 

관련하여 현재 사전 질문을 받고 있습니다. 아래의 링크를 통하여 묻고 싶은 사항을 남겨주시기 바랍니다.

 

 

\"d24;\" Lab토크쇼(10/27(목) 18시30분~) 사전질문 작성

제출된 질문은 Lab 토크쇼에서 활용되며, 추첨을 통하여 커피쿠폰을 드립니다.

https://forms.gle/a8XWyqXcTec8vdwq5

 

 

 

 

안민규 교수.

") + .viewCnt(0) + .importance(false) + .pubDate(LocalDate.of(2022, Month.NOVEMBER, 2)) + .expDate(LocalDate.of(2023, Month.NOVEMBER, 9)) + .build()); + } + + + private void saveStudent() { + studentRepository.save(Student.builder() + .name("박성진") + .department(departementRepository.findByName("전산전자공학부")) + .studentNum("21700266") + .semester(8) + .major1(majorRepository.findByName("컴퓨터공학심화전공")) + .major2(majorRepository.findByName("-")) + .phone("010-9484-4321") + .email("david@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203534676-49fb985a-c686-4965-9dc4-d46ae90cc3e7.png") + .blog("blog.com") + .githubId("@davidpiao.github") + .loginCnt(0L) + .readme("david's readme") + .build()); + studentRepository.save(Student.builder() + .name("안병웅") + .department(departementRepository.findByName("생명과학부")) + .studentNum("21600399") + .semester(6) + .major1(majorRepository.findByName("생명과학전공")) + .major2(majorRepository.findByName("-")) + .phone("010-1623-1512") + .email("mh030315@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203915182-c8216b87-9e06-4a10-8efe-b8d0cb43b5af.png") + .blog("blog.com") + .githubId("@wooong.github") + .loginCnt(0L) + .readme("an's readme") + .build()); + studentRepository.save(Student.builder() + .name("홍성헌") + .department(departementRepository.findByName("커뮤니케이션학부")) + .studentNum("21800929") + .semester(8) + .major1(majorRepository.findByName("공연영상학전공")) + .major2(majorRepository.findByName("언론정보학전공")) + .phone("010-1623-3322") + .email("hong@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203469086-7e27bf70-cca1-4bf2-be74-e16dbcee7507.jpeg") + .blog("blog.com") + .githubId("@hong.github") + .loginCnt(0L) + .readme("hong's readme") + .build()); + studentRepository.save(Student.builder() + .name("이인혁") + .department(departementRepository.findByName("기계제어공학부")) + .studentNum("21700032") + .semester(5) + .major1(majorRepository.findByName("전자제어공학전공")) + .major2(majorRepository.findByName("기계공학전공")) + .phone("010-4983-6555") + .email("lee@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203468795-8bf6ee4b-5ee6-4ae4-87ed-ca438307c30f.jpeg") + .blog("blog.com") + .githubId("@ee.github") + .loginCnt(0L) + .readme("lee's readme") + .build()); + studentRepository.save(Student.builder() + .name("정석민") + .department(departementRepository.findByName("콘텐츠융합디자인학부")) + .studentNum("22000432") + .semester(3) + .major1(majorRepository.findByName("시각디자인전공")) + .major2(majorRepository.findByName("-")) + .phone("010-4983-6555") + .email("jeong@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@jeong.github") + .loginCnt(0L) + .readme("jeong's readme") + .build()); + studentRepository.save(Student.builder() + .name("송다빈") + .department(departementRepository.findByName("법학부")) + .studentNum("22000332") + .semester(3) + .major1(majorRepository.findByName("US & International Law")) + .major2(majorRepository.findByName("한국법전공")) + .phone("010-7788-0142") + .email("song@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203534764-4f30254d-d917-444c-84f9-d8e922b967fa.png") + .blog("blog.com") + .githubId("@song.github") + .loginCnt(0L) + .readme("song's readme") + .build()); + studentRepository.save(Student.builder() + .name("문하현") + .department(departementRepository.findByName("전산전자공학부")) + .studentNum("22200000") + .semester(5) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("생명과학전공")) + .phone("010-1234-1234") + .email("kim@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203492174-ef61e68c-a3d9-429e-8947-75542423977a.png") + .blog("blog.com") + .githubId("@kim.github") + .loginCnt(0L) + .readme("kim's readme") + .build()); + studentRepository.save(Student.builder() + .name("박관희") + .department(departementRepository.findByName("국제어문학부")) + .studentNum("22200001") + .semester(3) + .major1(majorRepository.findByName("국제지역학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-1234-5678") + .email("park@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203862630-2915aaad-8ff0-42ae-b217-fcbce19e4791.png") + .blog("blog.com") + .githubId("@park.github") + .loginCnt(0L) + .readme("park's readme") + .build()); + studentRepository.save(Student.builder() + .name("이연진") + .department(departementRepository.findByName("경영경제학부")) + .studentNum("22200002") + .semester(5) + .major1(majorRepository.findByName("경영학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-5678-1234") + .email("lee@handong.ac.kr") + .profile("https://user-images.githubusercontent.com/63008958/203536628-985c37e3-49a9-4a50-82a3-485c09c456c4.png") + .blog("blog.com") + .githubId("@lee.github") + .loginCnt(0L) + .readme("lee's readme") + .build()); + studentRepository.save(Student.builder() + .name("게스트") + .department(departementRepository.findByName("법학부")) + .studentNum("22200003") + .semester(6) + .major1(majorRepository.findByName("한국법전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-1111-1111") + .email("jeong@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-10/Original Logo.png") + .blog("blog.com") + .githubId("@jeong.github") + .loginCnt(0L) + .readme("jeong's readme") + .build()); + studentRepository.save(Student.builder() + .name("김건휘") + .department(departementRepository.findByName("전산전자공학부")) + .studentNum("21700234") + .semester(2) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("생명과학전공")) + .phone("010-1234-1234") + .email("kim@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@kim.github") + .loginCnt(0L) + .readme("kim's readme") + .build()); + studentRepository.save(Student.builder() + .name("이도경") + .department(departementRepository.findByName("국제어문학부")) + .studentNum("21200012") + .semester(9) + .major1(majorRepository.findByName("국제지역학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-1234-5678") + .email("park@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@park.github") + .loginCnt(0L) + .readme("park's readme") + .build()); + studentRepository.save(Student.builder() + .name("정민수") + .department(departementRepository.findByName("경영경제학부")) + .studentNum("22200032") + .semester(5) + .major1(majorRepository.findByName("경영학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-6655-4232") + .email("lee@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@lee.github") + .loginCnt(0L) + .readme("lee's readme") + .build()); + studentRepository.save(Student.builder() + .name("조수아") + .department(departementRepository.findByName("법학부")) + .studentNum("21600223") + .semester(5) + .major1(majorRepository.findByName("한국법전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-9292-9292") + .email("jeong@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@jeong.github") + .loginCnt(0L) + .readme("jeong's readme") + .build()); + studentRepository.save(Student.builder() + .name("김빛나리") + .department(departementRepository.findByName("커뮤니케이션학부")) + .studentNum("22200023") + .semester(3) + .major1(majorRepository.findByName("공연영상학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-2332-4333") + .email("woo@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@woo.github") + .loginCnt(0L) + .readme("woo's readme") + .build()); + studentRepository.save(Student.builder() + .name("김혜린") + .department(departementRepository.findByName("상담심리사회복지학부")) + .studentNum("21900021") + .semester(4) + .major1(majorRepository.findByName("사회복지학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4444-1234") + .email("wi@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@wi.github") + .loginCnt(0L) + .readme("wi's readme") + .build()); + studentRepository.save(Student.builder() + .name("이소희") + .department(departementRepository.findByName("공간환경시스템공학부")) + .studentNum("21800002") + .semester(9) + .major1(majorRepository.findByName("도시환경공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-3221-6665") + .email("ha@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ha.github") + .loginCnt(0L) + .readme("ha's readme") + .build()); + studentRepository.save(Student.builder() + .name("이소연") + .department(departementRepository.findByName("콘텐츠융합디자인학부")) + .studentNum("21400025") + .semester(2) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4211-1123") + .email("ma@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ma.github") + .loginCnt(0L) + .readme("ma's readme") + .build()); + studentRepository.save(Student.builder() + .name("이동영") + .department(departementRepository.findByName("기계제어공학부")) + .studentNum("21100234") + .semester(10) + .major1(majorRepository.findByName("기계공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-2311-9992") + .email("yu@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@yu.github") + .loginCnt(0L) + .readme("yu's readme") + .build()); + studentRepository.save(Student.builder() + .name("김시온") + .department(departementRepository.findByName("전산전자공학부")) + .studentNum("22100032") + .semester(2) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("생명과학전공")) + .phone("010-3232-6767") + .email("kim@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@kim.github") + .loginCnt(0L) + .readme("kim's readme") + .build()); + studentRepository.save(Student.builder() + .name("황유민") + .department(departementRepository.findByName("국제어문학부")) + .studentNum("21600432") + .semester(1) + .major1(majorRepository.findByName("국제지역학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4322-9009") + .email("park@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@park.github") + .loginCnt(0L) + .readme("park's readme") + .build()); + studentRepository.save(Student.builder() + .name("엄서영") + .department(departementRepository.findByName("경영경제학부")) + .studentNum("22000231") + .semester(5) + .major1(majorRepository.findByName("경영학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-6653-4231") + .email("lee@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@lee.github") + .loginCnt(0L) + .readme("lee's readme") + .build()); + studentRepository.save(Student.builder() + .name("이찬유") + .department(departementRepository.findByName("법학부")) + .studentNum("21600423") + .semester(5) + .major1(majorRepository.findByName("한국법전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-9292-9232") + .email("jeong@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@jeong.github") + .loginCnt(0L) + .readme("jeong's readme") + .build()); + studentRepository.save(Student.builder() + .name("천그루") + .department(departementRepository.findByName("커뮤니케이션학부")) + .studentNum("22200026") + .semester(3) + .major1(majorRepository.findByName("공연영상학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-2312-4343") + .email("woo@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@woo.github") + .loginCnt(0L) + .readme("woo's readme") + .build()); + studentRepository.save(Student.builder() + .name("이하민") + .department(departementRepository.findByName("상담심리사회복지학부")) + .studentNum("21910032") + .semester(4) + .major1(majorRepository.findByName("사회복지학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4444-4234") + .email("wi@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@wi.github") + .loginCnt(0L) + .readme("wi's readme") + .build()); + studentRepository.save(Student.builder() + .name("현요섭") + .department(departementRepository.findByName("콘텐츠융합디자인학부")) + .studentNum("21400325") + .semester(2) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4211-1673") + .email("ma@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ma.github") + .loginCnt(0L) + .readme("ma's readme") + .build()); + studentRepository.save(Student.builder() + .name("이찬호") + .department(departementRepository.findByName("기계제어공학부")) + .studentNum("21100734") + .semester(10) + .major1(majorRepository.findByName("기계공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-2911-9192") + .email("yu@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@yu.github") + .loginCnt(0L) + .readme("yu's readme") + .build()); + studentRepository.save(Student.builder() + .name("곤잘레스") + .department(departementRepository.findByName("상담심리사회복지학부")) + .studentNum("21900112") + .semester(4) + .major1(majorRepository.findByName("사회복지학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-1144-4214") + .email("wi@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@wi.github") + .loginCnt(0L) + .readme("wi's readme") + .build()); + studentRepository.save(Student.builder() + .name("다비드") + .department(departementRepository.findByName("공간환경시스템공학부")) + .studentNum("21800332") + .semester(9) + .major1(majorRepository.findByName("도시환경공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-3331-6365") + .email("ha@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ha.github") + .loginCnt(0L) + .readme("ha's readme") + .build()); + studentRepository.save(Student.builder() + .name("김영헌") + .department(departementRepository.findByName("공간환경시스템공학부")) + .studentNum("21810232") + .semester(9) + .major1(majorRepository.findByName("도시환경공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-3431-6365") + .email("ha@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ha.github") + .loginCnt(0L) + .readme("ha's readme") + .build()); + studentRepository.save(Student.builder() + .name("김하은") + .department(departementRepository.findByName("콘텐츠융합디자인학부")) + .studentNum("21400825") + .semester(2) + .major1(majorRepository.findByName("컴퓨터공학전공")) + .major2(majorRepository.findByName("컴퓨터공학전공")) + .phone("010-4111-2673") + .email("ma@handong.ac.kr") + .profile("https://hispath.s3.ap-northeast-2.amazonaws.com/upload/student-5/plant-2004483_1920.jpg") + .blog("blog.com") + .githubId("@ma.github") + .loginCnt(0L) + .readme("ma's readme") + .build()); + } + + private void saveCategory() { + categoryRepository.save(Category.builder() + .name("전공마일리지") + .build()); + categoryRepository.save(Category.builder() + .name("산학마일리지") + .build()); + categoryRepository.save(Category.builder() + .name("비교과-연구활동") + .build()); + categoryRepository.save(Category.builder() + .name("비교과-특강참여") + .build()); + categoryRepository.save(Category.builder() + .name("비교과-행사참여") + .build()); + categoryRepository.save(Category.builder() + .name("비교과-학회활동") + .build()); + categoryRepository.save(Category.builder() + .name("기타") + .build()); + } + + + private void saveDepartment() { + departementRepository.save(Department.builder() + .name("전산전자공학부") + .profile("https://user-images.githubusercontent.com/63008958/203982136-82098fb9-f082-40e3-a677-e84076ea7745.png") + .build()); + departementRepository.save(Department.builder() + .name("국제어문학부") + .profile("https://user-images.githubusercontent.com/63008958/203982173-f22aa5a5-0e7f-45cc-91b0-1870ced20441.png") + .build()); + departementRepository.save(Department.builder() + .name("경영경제학부") + .profile("https://user-images.githubusercontent.com/63008958/203982171-65bbc7d2-a8de-43d2-9db3-ca361aa36b1c.png") + .build()); + departementRepository.save(Department.builder() + .name("법학부") + .profile("https://user-images.githubusercontent.com/63008958/203982170-44a91016-1b6a-4d88-b7a1-4560966521f2.png") + .build()); + departementRepository.save(Department.builder() + .name("커뮤니케이션학부") + .profile("https://user-images.githubusercontent.com/63008958/203982168-d3cba5e1-2627-4941-a414-aa3e17fd2959.png") + .build()); + departementRepository.save(Department.builder() + .name("상담심리사회복지학부") + .profile("https://user-images.githubusercontent.com/63008958/203982129-0ed8a671-c04a-443f-b48e-7471074112ea.png") + .build()); + departementRepository.save(Department.builder() + .name("공간환경시스템공학부") + .profile("https://user-images.githubusercontent.com/63008958/203982164-378d214b-04ce-4d1f-b909-36daf17b5cdb.png") + .build()); + departementRepository.save(Department.builder() + .name("콘텐츠융합디자인학부") + .profile("https://user-images.githubusercontent.com/63008958/203982153-f2ae91d9-8984-40ed-9802-5b2f71f123b5.png") + .build()); + departementRepository.save(Department.builder() + .name("기계제어공학부") + .profile("https://user-images.githubusercontent.com/63008958/203982161-61e66aa6-6625-4eb0-819c-71edc01f47ad.png") + .build()); + departementRepository.save(Department.builder() + .name("ICT 창업학부") + .profile("https://user-images.githubusercontent.com/63008958/203982115-30963e7f-19e9-4f45-8390-bec128a1981b.png") + .build()); + departementRepository.save(Department.builder() + .name("생명과학부") + .profile("https://user-images.githubusercontent.com/63008958/203982143-6972a9ad-8b43-4024-b63f-59ce0969e922.png") + .build()); + departementRepository.save(Department.builder() + .name("글로벌리더쉽학부") + .profile("https://user-images.githubusercontent.com/63008958/203982177-4324201c-63d8-4df0-abe7-09fd1c7cfd21.png") + .build()); + } + + + public void saveActivities() { + activityRepository.save(Activity.builder() + .semester("2021-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("공학프로젝트기획") + .weight(7) + .category(categoryRepository.findByName("전공마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-1") + .personal(false) + .remark("") + .requestStatus(1) + .name("공학설계입문") + .weight(5) + .category(categoryRepository.findByName("전공마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("캡스톤 디자인") + .weight(10) + .category(categoryRepository.findByName("전공마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("AI 프로젝트 입문") + .weight(5) + .category(categoryRepository.findByName("전공마일리지")) + .build()); +// 산학 + activityRepository.save(Activity.builder() + .semester("2021-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("현장실습") + .weight(7) + .category(categoryRepository.findByName("산학마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2021-2") + .personal(false) + .remark("BizFlow") + .requestStatus(1) + .name("현장실습") + .weight(7) + .category(categoryRepository.findByName("산학마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("카카오") + .requestStatus(1) + .name("현장실습") + .weight(7) + .category(categoryRepository.findByName("산학마일리지")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("엑슨투") + .requestStatus(1) + .name("현장실습") + .weight(7) + .category(categoryRepository.findByName("산학마일리지")) + .build()); +// 비교과연구활동 + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("AI Deep Learning") + .requestStatus(1) + .name("논문 분석") + .weight(5) + .category(categoryRepository.findByName("비교과-연구활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("Brain Computer Interface") + .requestStatus(1) + .name("논문 분석") + .weight(5) + .category(categoryRepository.findByName("비교과-연구활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("ResNet Review") + .requestStatus(1) + .name("논문 분석") + .weight(5) + .category(categoryRepository.findByName("비교과-연구활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("Anomaly Analysis") + .requestStatus(1) + .name("논문 분석") + .weight(5) + .category(categoryRepository.findByName("비교과-연구활동")) + .build()); +// 비교과특강참여 + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("디지털 시대와 개발자 (10.26)") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("프로그래머로 산다는 것 (11.2)") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("제네시스랩의 기술 창업 스토리") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("웹과 클라우드 개발자 취업의 현장 (11.07)") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("웹 개발자로 살아남는 법 (11.27)") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("빅데이터 분석과 활용법 (12.10)") + .requestStatus(1) + .name("CSEE 특강") + .weight(2) + .category(categoryRepository.findByName("비교과-특강참여")) + .build()); +// 행사참여 + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("(캠프)웹서비스 프로젝트(spring)_장소연") + .weight(6) + .category(categoryRepository.findByName("비교과-행사참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("최우수상 수상") + .requestStatus(1) + .name("(캠프)미리미리C 캠프_김광") + .weight(5) + .category(categoryRepository.findByName("비교과-행사참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("우수상 수상") + .requestStatus(1) + .name("(캠프)Advanced Flutter Camp_조성배") + .weight(6) + .category(categoryRepository.findByName("비교과-행사참여")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("") + .requestStatus(1) + .name("캡스톤 페스티벌 참여") + .weight(5) + .category(categoryRepository.findByName("비교과-행사참여")) + .build()); +// 비교과 학회활동 + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("CRA") + .requestStatus(1) + .name("전공동아리") + .weight(7) + .category(categoryRepository.findByName("비교과-학회활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("GHOST") + .requestStatus(1) + .name("전공동아리") + .weight(7) + .category(categoryRepository.findByName("비교과-학회활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("실전프로젝트 1스터디") + .requestStatus(1) + .name("전공스터디") + .weight(3) + .category(categoryRepository.findByName("비교과-학회활동")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("시선") + .requestStatus(1) + .name("전공학회") + .weight(5) + .category(categoryRepository.findByName("비교과-학회활동")) + .build()); + +// 기타 + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("SW중심대학 협의회장상") + .requestStatus(1) + .name("SW중심대학 공동해커톤 2022") + .weight(7) + .category(categoryRepository.findByName("기타")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("정보처리기사") + .requestStatus(1) + .name("자격증") + .weight(5) + .category(categoryRepository.findByName("기타")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("네이버 부스트캠프") + .requestStatus(1) + .name("외부캠프") + .weight(6) + .category(categoryRepository.findByName("기타")) + .build()); + activityRepository.save(Activity.builder() + .semester("2022-2") + .personal(false) + .remark("TOPCIT") + .requestStatus(1) + .name("전공역량시험") + .weight(4) + .category(categoryRepository.findByName("기타")) + .build()); + } + + + private void saveMajor() { + majorRepository.save(Major.builder().name("-").profile("https://user-images.githubusercontent.com/63008958/203987348-497d8992-98e2-47ff-9769-a7207e6961ed.png").build()); + majorRepository.save(Major.builder().name("건설공학전공").profile("https://user-images.githubusercontent.com/63008958/203986081-cc605f80-7cb3-4fc9-93ed-9712a38506c6.jpg").build()); + majorRepository.save(Major.builder().name("도시환경공학전공").profile("https://user-images.githubusercontent.com/63008958/203986080-4921f01e-8fdd-480c-b764-f1d926b070d3.jpg").build()); + majorRepository.save(Major.builder().name("기계공학전공").profile("https://user-images.githubusercontent.com/63008958/203986079-59fe24a6-d934-4dad-9b80-35a1a5306535.jpg").build()); + majorRepository.save(Major.builder().name("전자제어공학전공").profile("https://user-images.githubusercontent.com/63008958/203986077-425b14ae-37f5-480a-b00c-fdec96f09b9d.jpg").build()); + majorRepository.save(Major.builder().name("생명과학전공").profile("https://user-images.githubusercontent.com/63008958/203986074-b785eed9-1531-4c32-b153-dec59ea10982.jpg").build()); + majorRepository.save(Major.builder().name("글로벌융합전공").profile("https://user-images.githubusercontent.com/63008958/203986073-4a098ecc-5f91-4ab4-abb3-2a90149c566a.jpg").build()); + majorRepository.save(Major.builder().name("수학통계전공").profile("https://user-images.githubusercontent.com/63008958/203986071-ba9e0fb7-e246-4cfc-b1cc-788264a9086b.jpg").build()); + majorRepository.save(Major.builder().name("학생설계융합전공").profile("https://user-images.githubusercontent.com/63008958/203986068-5fd2f7d5-c894-49ed-92d7-30a63b4e88f9.jpg").build()); + majorRepository.save(Major.builder().name("시각디자인전공").profile("https://user-images.githubusercontent.com/63008958/203986065-746e6d2d-38e0-494e-b5c4-9060d5bb329e.jpg").build()); + majorRepository.save(Major.builder().name("제품디자인전공").profile("https://user-images.githubusercontent.com/63008958/203986063-d3aa8474-58c6-4e22-a23f-1a17edb40300.jpg").build()); + majorRepository.save(Major.builder().name("컴퓨터공학전공").profile("https://user-images.githubusercontent.com/63008958/203986059-4fc80f57-49b3-453f-94de-6f51b729730a.jpg").build()); + majorRepository.save(Major.builder().name("컴퓨터공학심화전공").profile("https://user-images.githubusercontent.com/63008958/203986052-b02066c1-0ff5-41ed-81e7-72bcf5284dc3.jpg").build()); + majorRepository.save(Major.builder().name("전자공학전공").profile("https://user-images.githubusercontent.com/63008958/204516545-6c7ca818-1c99-4c1a-a4d4-569577d344d8.jpg").build()); + majorRepository.save(Major.builder().name("전자공학심화전공").profile("https://user-images.githubusercontent.com/63008958/204516569-13f7310b-b5a5-4f9d-8171-065884cbf59c.jpg").build()); + majorRepository.save(Major.builder().name("Information Technology").profile("https://user-images.githubusercontent.com/63008958/204516579-bad0d03e-d9ca-4a76-9e94-4a31fe605ce4.jpg").build()); + majorRepository.save(Major.builder().name("ICT 융합전공").profile("https://user-images.githubusercontent.com/63008958/204516638-7c5c13c2-ebb7-4d41-895b-8af61801e7b4.jpg").build()); + majorRepository.save(Major.builder().name("AI Convergence & Entrepreneurship 전공").profile("https://user-images.githubusercontent.com/63008958/204517597-e463b42b-17f3-4476-9314-fe33edb23e8e.jpg").build()); + majorRepository.save(Major.builder().name("Global Entrepreneurship 전공").profile("https://user-images.githubusercontent.com/63008958/204516633-5be00a69-d31e-4edb-ada1-9f143f9ec5ee.jpg").build()); + majorRepository.save(Major.builder().name("AI 융합 전공").profile("https://user-images.githubusercontent.com/63008958/204517614-2fd82907-7e30-488e-8df5-b34c1f5fd05f.jpg").build()); + majorRepository.save(Major.builder().name("데이터 사이언스 전공").profile("https://user-images.githubusercontent.com/63008958/204516681-cee59ca5-3e83-45b0-9f2d-77d38aa9772a.jpg").build()); + majorRepository.save(Major.builder().name("경영학전공").profile("https://user-images.githubusercontent.com/63008958/204516699-8d4ae330-79ce-4827-a9b1-4c6bb94a04dd.jpg").build()); + majorRepository.save(Major.builder().name("경제학전공").profile("https://user-images.githubusercontent.com/63008958/204516724-255d3f3d-586c-44f2-bf30-20ae74500e5e.jpg").build()); + majorRepository.save(Major.builder().name("Global Management").profile("https://user-images.githubusercontent.com/63008958/204516745-795ffbf4-3e25-410a-bb87-8957b17f974a.jpg").build()); + majorRepository.save(Major.builder().name("국제지역학전공").profile("https://user-images.githubusercontent.com/63008958/204516767-6d058e2b-98eb-4156-84f2-41adc5961487.jpg").build()); + majorRepository.save(Major.builder().name("영어전공").profile("https://user-images.githubusercontent.com/63008958/204516780-97509626-d605-4b33-871e-6c66d8b9bccb.jpg").build()); + majorRepository.save(Major.builder().name("한국법전공").profile("https://user-images.githubusercontent.com/63008958/204519931-bd711496-c4cf-453c-9159-21bd471abdf7.jpg").build()); + majorRepository.save(Major.builder().name("US & International Law").profile("https://user-images.githubusercontent.com/63008958/204519949-fbc6196b-3b22-4893-a94c-6aaf43404db3.jpg").build()); + majorRepository.save(Major.builder().name("상담심리학전공").profile("https://user-images.githubusercontent.com/63008958/204519961-dfcc4cb7-770d-414c-b503-62daf17cb348.jpg").build()); + majorRepository.save(Major.builder().name("사회복지학전공").profile("https://user-images.githubusercontent.com/63008958/204519984-9bd89f56-8bd5-4643-9c23-92e86fc3c97e.jpg").build()); + majorRepository.save(Major.builder().name("공연영상학전공").profile("https://user-images.githubusercontent.com/63008958/204520461-e38be0f3-c3d4-42e8-b791-d57a914d90bb.jpg").build()); + majorRepository.save(Major.builder().name("언론정보학전공").profile("https://user-images.githubusercontent.com/63008958/204520001-123c3cda-ab11-4009-b139-ebb6d0b4b458.jpg").build()); + majorRepository.save(Major.builder().name("글로벌한국학전공").profile("https://user-images.githubusercontent.com/63008958/204520021-dc82a562-fab3-438c-abb2-9e1d85b27415.jpg").build()); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/config/OauthConfig.java b/src/main/java/com/server/hispath/config/OauthConfig.java new file mode 100644 index 0000000..9f2300d --- /dev/null +++ b/src/main/java/com/server/hispath/config/OauthConfig.java @@ -0,0 +1,28 @@ +package com.server.hispath.config; + +import java.util.Map; + +import com.server.hispath.auth.domain.OauthProperties; +import com.server.hispath.auth.domain.OauthProvider; +import com.server.hispath.auth.infrastructure.ApiRequester; +import com.server.hispath.auth.infrastructure.OauthHandler; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import lombok.RequiredArgsConstructor; + +@Configuration +@RequiredArgsConstructor +@EnableConfigurationProperties(OauthProperties.class) +public class OauthConfig { + + private final OauthProperties properties; + + @Bean + public OauthHandler oauthHandler() { + Map providers = properties.getOauthProviders(); + return new OauthHandler(providers, new ApiRequester()); + } +} diff --git a/src/main/java/com/server/hispath/config/QuerydslConfig.java b/src/main/java/com/server/hispath/config/QuerydslConfig.java new file mode 100644 index 0000000..53e7f44 --- /dev/null +++ b/src/main/java/com/server/hispath/config/QuerydslConfig.java @@ -0,0 +1,20 @@ +package com.server.hispath.config; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QuerydslConfig { + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory(){ + return new JPAQueryFactory(entityManager); + } +} diff --git a/src/main/java/com/server/hispath/config/SwaggerConfig.java b/src/main/java/com/server/hispath/config/SwaggerConfig.java new file mode 100644 index 0000000..a34c3ae --- /dev/null +++ b/src/main/java/com/server/hispath/config/SwaggerConfig.java @@ -0,0 +1,33 @@ +package com.server.hispath.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@Configuration +public class SwaggerConfig { + @Bean + public Docket api() { + return new Docket(DocumentationType.OAS_30) + .useDefaultResponseMessages(false) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.ant("/api/**")) + .build() + .apiInfo(apiInfo()); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("HisPath Swagger") + .description("HisPath") + .version("1.0") + .build(); + } +} diff --git a/src/main/java/com/server/hispath/config/WebConfig.java b/src/main/java/com/server/hispath/config/WebConfig.java new file mode 100644 index 0000000..f32ea09 --- /dev/null +++ b/src/main/java/com/server/hispath/config/WebConfig.java @@ -0,0 +1,41 @@ +package com.server.hispath.config; + +import java.util.List; + +import com.server.hispath.auth.presentation.LoginInterceptor; +import com.server.hispath.auth.presentation.LoginManagerArgumentResolver; +import com.server.hispath.auth.presentation.LoginStudentArgumentResolver; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Configuration +public class WebConfig implements WebMvcConfigurer { + private final LoginInterceptor loginInterceptor; + private final LoginStudentArgumentResolver loginStudentArgumentResolver; + private final LoginManagerArgumentResolver loginManagerArgumentResolver; + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedMethods("*") + .allowedOrigins("http://localhost:3000", "http://localhost:8080", "https://hispath.kro.kr", "https://hispath-manager.kro.kr", "https://hispath-server.kro.kr"); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**"); + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginStudentArgumentResolver); + resolvers.add(loginManagerArgumentResolver); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/department/application/DepartmentService.java b/src/main/java/com/server/hispath/department/application/DepartmentService.java new file mode 100644 index 0000000..5089cc3 --- /dev/null +++ b/src/main/java/com/server/hispath/department/application/DepartmentService.java @@ -0,0 +1,54 @@ +package com.server.hispath.department.application; + +import com.server.hispath.department.application.dto.DepartmentDto; +import com.server.hispath.department.domain.Department; +import com.server.hispath.department.domain.repository.DepartementRepository; +import com.server.hispath.exception.student.StudentNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class DepartmentService { + private final DepartementRepository departmentRepository; + + @Transactional + public Long create(DepartmentDto dto){ + Department savedDepartment = departmentRepository.save(Department.from(dto)); + return savedDepartment.getId(); + } + + @Transactional + public DepartmentDto find(Long id) { + Department department = this.findById(id); + return DepartmentDto.from(department); + } + + @Transactional + public List findAll() { + List department = departmentRepository.findAll(); + return department.stream() + .map(DepartmentDto::from) + .collect(Collectors.toList()); + } + + @Transactional + public DepartmentDto update(Long id, DepartmentDto dto) { + Department department = departmentRepository.findById(id).orElseThrow(StudentNotFoundException::new);; + department.update(dto); + return DepartmentDto.from(department); + } + + @Transactional + public void delete(Long id) { + departmentRepository.deleteById(id); + } + + public Department findById(Long id) { + return departmentRepository.findById(id).orElseThrow(StudentNotFoundException::new); + } +} diff --git a/src/main/java/com/server/hispath/department/application/dto/DepartmentDto b/src/main/java/com/server/hispath/department/application/dto/DepartmentDto new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/server/hispath/department/application/dto/DepartmentDto.java b/src/main/java/com/server/hispath/department/application/dto/DepartmentDto.java new file mode 100644 index 0000000..0307f01 --- /dev/null +++ b/src/main/java/com/server/hispath/department/application/dto/DepartmentDto.java @@ -0,0 +1,31 @@ +package com.server.hispath.department.application.dto; + +import com.server.hispath.department.domain.Department; +import com.server.hispath.department.presentation.request.DepartmentCRRequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class DepartmentDto { + private Long id; + private String name; + private String profile; + + public DepartmentDto(Long id, String name) { + this.id = id; + this.name = name; + } + + public static DepartmentDto from (Department department) { + return new DepartmentDto(department.getId(), department.getName(), department.getProfile()); + } + + public static DepartmentDto from(DepartmentCRRequest request) { + return new DepartmentDto(request.getDepartmentId(), request.getName()); + } +} diff --git a/src/main/java/com/server/hispath/department/domain/Department.java b/src/main/java/com/server/hispath/department/domain/Department.java new file mode 100644 index 0000000..9eed012 --- /dev/null +++ b/src/main/java/com/server/hispath/department/domain/Department.java @@ -0,0 +1,45 @@ +package com.server.hispath.department.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import com.server.hispath.common.BaseEntity; + +import com.server.hispath.department.application.dto.DepartmentDto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE department SET deleted = true Where id = ?") +public class Department extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String profile; + + public void update(DepartmentDto dto) { + this.name = dto.getName(); + } + + public static Department from(DepartmentDto dto) { + return Department.builder() + .name(dto.getName()) + .build(); + } +} + diff --git a/src/main/java/com/server/hispath/department/domain/repository/DepartementRepository.java b/src/main/java/com/server/hispath/department/domain/repository/DepartementRepository.java new file mode 100644 index 0000000..a44c17b --- /dev/null +++ b/src/main/java/com/server/hispath/department/domain/repository/DepartementRepository.java @@ -0,0 +1,10 @@ +package com.server.hispath.department.domain.repository; + +import java.util.Optional; + +import com.server.hispath.department.domain.Department; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DepartementRepository extends JpaRepository { + Department findByName(String name); +} diff --git a/src/main/java/com/server/hispath/department/presentation/DepartmentController.java b/src/main/java/com/server/hispath/department/presentation/DepartmentController.java new file mode 100644 index 0000000..6d49e92 --- /dev/null +++ b/src/main/java/com/server/hispath/department/presentation/DepartmentController.java @@ -0,0 +1,71 @@ +package com.server.hispath.department.presentation; + +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.department.application.DepartmentService; +import com.server.hispath.department.application.dto.DepartmentDto; +import com.server.hispath.department.presentation.request.DepartmentCRRequest; +import com.server.hispath.department.presentation.response.DepartmentResponse; +import com.server.hispath.docs.ApiDoc; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class DepartmentController { + private final DepartmentService departmentService; + + @PostMapping("/department") + @ApiOperation(value = ApiDoc.DEPARTMENT_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@RequestBody DepartmentCRRequest request) { + + Long savedId = departmentService.create(DepartmentDto.from(request)); + return ResponseEntity.ok(savedId); + } + + @GetMapping("/department/{id}") + @ApiOperation(value = ApiDoc.DEPARTMENT_READ) + @RequiredLogin + public ResponseEntity find(@PathVariable Long id) { + + DepartmentDto dto = departmentService.find(id); + DepartmentResponse response = DepartmentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @GetMapping("/departments") + @ApiOperation(value = ApiDoc.DEPARTMENT_READ_ALL) + @RequiredLogin + public ResponseEntity> findAll() { + + List dtos = departmentService.findAll(); + List responses = dtos.stream() + .map(DepartmentResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @PatchMapping("/department/{id}") + @ApiOperation(value = ApiDoc.DEPARTMENT_UPDATE) + @RequiredManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody DepartmentCRRequest request) { + DepartmentDto dto = departmentService.update(id, DepartmentDto.from(request)); + DepartmentResponse response = DepartmentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/department/{id}") + @ApiOperation(value = ApiDoc.DEPARTMENT_DELETE) + @RequiredManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + departmentService.delete(id); + return ResponseEntity.ok(id); + } +} diff --git a/src/main/java/com/server/hispath/department/presentation/request/DepartmentCRRequest.java b/src/main/java/com/server/hispath/department/presentation/request/DepartmentCRRequest.java new file mode 100644 index 0000000..5224c2b --- /dev/null +++ b/src/main/java/com/server/hispath/department/presentation/request/DepartmentCRRequest.java @@ -0,0 +1,12 @@ +package com.server.hispath.department.presentation.request; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class DepartmentCRRequest { + private Long departmentId; + private String name; +} diff --git a/src/main/java/com/server/hispath/department/presentation/response/DepartmentResponse.java b/src/main/java/com/server/hispath/department/presentation/response/DepartmentResponse.java new file mode 100644 index 0000000..7112792 --- /dev/null +++ b/src/main/java/com/server/hispath/department/presentation/response/DepartmentResponse.java @@ -0,0 +1,21 @@ +package com.server.hispath.department.presentation.response; + +import com.server.hispath.department.application.dto.DepartmentDto; +import com.server.hispath.student.application.dto.StudentDto; +import com.server.hispath.student.presentation.response.StudentResponse; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class DepartmentResponse { + private Long departmentId; + private String name; + private String profile; + + public static DepartmentResponse from (DepartmentDto dto) { + return new DepartmentResponse(dto.getId(), dto.getName(), dto.getProfile()); + } +} diff --git a/src/main/java/com/server/hispath/docs/ApiDoc.java b/src/main/java/com/server/hispath/docs/ApiDoc.java new file mode 100644 index 0000000..593d473 --- /dev/null +++ b/src/main/java/com/server/hispath/docs/ApiDoc.java @@ -0,0 +1,115 @@ +package com.server.hispath.docs; + +public class ApiDoc { + + /* Activity 관련 API 명세 */ + public static final String ACTIVITY_CREATE = "단일 활동 생성"; + public static final String ACTIVITY_READ = "단일 활동 조회"; + public static final String ACTIVITY_READ_ALL = "모든 활동 조회"; + public static final String ACTIVITY_UPDATE = "활동 수정"; + public static final String ACTIVITY_DELETE = "학생 활동 삭제"; + public static final String MILEAGE_CREATE = "단일 마일리지 활동 등록"; + public static final String MILEAGES_CREATE = "단일 마일리지 다중 등록"; + public static final String MILEAGE_UPDATE = "마일리지 활동 수정"; + public static final String MILEAGE_DELETE = "마일리지 활동 삭제"; + public static final String MILEAGE_READ_SEMESTER = "승인된 마일리지 활동 학기별 조회"; + public static final String MILEAGE_READ_ALL = "모든 승인된 마일리지 활동 조회"; + public static final String MILEAGE_REGISTER_STUDENTS = "마일리지 활동 참가 학생 엑셀 등록"; + public static final String MILEAGE_REGISTER_STUDENT = "마일리지 활동 참가 학생 단일 등록"; + public static final String ACTIVITY_STUDENT_DELETE = "마일리지 활동 학생 참가 정보 삭제"; + public static final String MILEAGE_READ = "단일 마일리지 활동 조회"; + public static final String STUDENT_MILEAGE_READ = "학생별 마일리지 활동 조회"; + public static final String STUDENT_READ_SEMESTER = "학생별 활동 학기 조회"; + public static final String STUDENT_ACTIVITY_CREATE = "학생의 개인 활동 생성"; + public static final String STUDENT_ACTIVITY_UPDATE = "학생의 참여 활동 수정"; + public static final String STUDENT_ACTIVITY_READ_SEMESTER = "학생의 참여 활동 학기별 조회"; + public static final String STUDENT_ACTIVITY_READ_SEMESTER_SECTION_STATUS = "학생의 참여 활동 상태와 함께 학기별, 섹션별 조회"; + + public static final String STUDENT_ACTIVITY_READ_PARTICIPATE = "전체 활동 중 학생 참여 활동 조회"; + public static final String SECTION_READ_ALL = "모든 섹션 조회"; + public static final String PARTICIPANT_DELETE = "학생 참여 데이터 삭제"; + public static final String ACTIVITY_APPLY = "학생 활동 마일리지 신청"; + public static final String ACTIVITY_APPROVE = "학생 활동 마일리지 승인"; + public static final String ACTIVITY_REJECT = "학생 활동 마일리지 반려"; + public static final String MILEAGE_CATEGORY_CHART_DATAS = "카테고리 당 마일리지 참여, 평균 수 조회"; + public static final String ACTIVITY_STUDENT_DETAIL = "학생 개인 활동 상세 조회"; + + /* Chart 관련 API 명세 */ + public static final String CHART_MILEAGE_CATEGORY = "카테고리에 따른 학생 마일리지 활동 차트 데이터 조회"; + public static final String CHART_MILEAGE_POPULARITY_CATEGORY = "카테고리에 따른 전체 활동 갯수와 나의 참여수, 평균 참여수 차트 데이터 조회"; + public static final String CHART_MILEAGE_RANK = "내 마일리지 총점이 어느정도 위치하는지 차트 데이터 조회"; + public static final String CHART_MILEAGE_TIMELINE = "마일리지 활동 Timeline 차트 데이터 조회"; + public static final String CHART_SCHOLARSHIP_WEIGHT = "학생의 전체 가중치 분포 차트 데이터 조회"; + public static final String CHART_ACTIVITY_CATEGORY = "카테고리 별 활동 갯수 분포 차트 데이터 조회"; + public static final String CHART_STUDENT_ACTIVITY = "학생들의 전체 섹션 활동 분포 차트 데이터 조회"; + public static final String CHART_SCHOLARSHIP_GRADE = "학년 별 마일리지 수혜 학생 분포 차트 데이터 조회"; + public static final String CHART_SCHOLARSHIP_DEPARTMENT = "학부 별 마일리지 수혜 학생 분포 차트 데이터 조회"; + + /* Category 관련 API 명세 */ + public static final String CATEGORY_READ = "단일 카테고리 조회"; + public static final String CATEGORY_READ_ALL = "모든 카테고리 조회"; + public static final String CATEGORY_CREATE = "카테고리 생성"; + public static final String CATEGORY_UPDATE = "카테고리 수정"; + public static final String CATEGORY_DELETE = "카테고리 삭제"; + + public static final String ACTIVITY_READ_SEMESTER = "활동 학기 조회"; + public static final String MAJOR_CREATE = "전공 생성"; + public static final String MAJOR_READ = "단일 전공 조회"; + public static final String MAJOR_READ_ALL = "모든 전공 조회"; + public static final String MAJOR_UPDATE = "전공 수정"; + public static final String MAJOR_DELETE = "전공 삭제"; + + public static final String NOTICE_CREATE = "공지 생성"; + public static final String NOTICE_READ_ALL = "전체 공지 조회"; + public static final String NOTICE_READ_IMP = "강제 공지 조회"; + public static final String NOTICE_READ = "단일 공지 조회"; + public static final String NOTICE_DELETE = "공지 삭제"; + public static final String NOTICE_UPDATE = "공지 수정"; + + + /* Student 관련 API 명세 */ + public static final String STUDENT_READ = "단일 학생 조회"; + public static final String STUDENT_READ_ALL = "모든 학생 조회"; + public static final String STUDENT_CREATE = "학생 추가"; + public static final String STUDENTS_CREATE = "학생 단일 추가"; + public static final String STUDENT_UPDATE = "학생 수정"; + public static final String STUDENT_DELETE = "학생 삭제"; + public static final String DASHBOARD = "메인페이지 대시보드 정보 조회"; + public static final String STUDENT_SEMESTER = "학생의 활동 학기들 조회"; + + /* Manager 관련 API 명세 */ + public static final String MANAGER_READ = "단일 관리자 조회"; + public static final String MANAGER_READ_ALL = "모든 관리자 조회"; + public static final String MANAGER_CREATE = "관리자 생성"; + public static final String MANAGER_UPDATE = "관리자 수정"; + public static final String MANAGER_PROFILE_UPDATE = "관리자 프로필 수정"; + public static final String MANAGER_APPROVE = "관리자 승인"; + public static final String MANAGER_DELETE = "관리자 삭제"; + public static final String MANAGER_DASHBOARD = "관리자 대시보드 조회"; + public static final String MANAGER_EMAIL = "접속한 관리자 이메일 조회"; + + /* Department 관련 API 명세 */ + public static final String DEPARTMENT_READ = "단일 학부 조회"; + public static final String DEPARTMENT_READ_ALL = "모든 학부 조회"; + public static final String DEPARTMENT_CREATE = "학부 추가"; + public static final String DEPARTMENT_UPDATE = "학부 수정"; + public static final String DEPARTMENT_DELETE = "학부 삭제"; + + + /* Resume 관련 API 명세 */ + public static final String RESUME_READ = "학생의 단일 이력서 조회"; + public static final String RESUME_READ_ALL = "학생의 모든 이력서 조회"; + public static final String RESUME_CREATE = "단일 이력서 생성"; + public static final String RESUME_UPDATE = "이력서 수정"; + public static final String RESUME_DELETE = "이력서 삭제"; + public static final String RESUME_INFO = "학생의 모든 정보 및 활동정보 조회"; + + /* Scholarship 관련 API 명세 */ + public static final String SCHOLARSHIP_CREATE = "장학금 신청 등록"; + public static final String SCHOLARSHIP_READ_ALL = "장학금 수혜자들 명단 조회"; + public static final String SCHOLARSHIP_ACTIVITIES = "장학금 수혜자 정보와 그 활동들 조회"; + public static final String APPROVE_SCHOLARSHIPS = "현학기 장학금 승인 명단 엑셀 업로드"; + public static final String SCHOLARSHIP_SEARCH_STUDENT = "장학금 수혜 학생 필터 검색"; + + +} diff --git a/src/main/java/com/server/hispath/exception/ExceptionResponse.java b/src/main/java/com/server/hispath/exception/ExceptionResponse.java new file mode 100644 index 0000000..63709f8 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/ExceptionResponse.java @@ -0,0 +1,12 @@ +package com.server.hispath.exception; + +import lombok.Getter; + +@Getter +public class ExceptionResponse { + private final String message; + + public ExceptionResponse(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/server/hispath/exception/GlobalExceptionHandler.java b/src/main/java/com/server/hispath/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..fd7dc9d --- /dev/null +++ b/src/main/java/com/server/hispath/exception/GlobalExceptionHandler.java @@ -0,0 +1,37 @@ +package com.server.hispath.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(HisPathException.class) + public ResponseEntity hisPathException(HisPathException e) { + + if (e.getHttpStatus().is4xxClientError()) { + logger.info("Client Error : " + e.getMessage()); + } else if (e.getHttpStatus().is5xxServerError()) { + logger.error("Server Error : " + e.getMessage()); + } + + return ResponseEntity.status(e.getHttpStatus()) + .body(new ExceptionResponse(e.getMessage())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity commonException(Exception e) { + + logger.error("Unknown Exception : " + e.getMessage()); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ExceptionResponse(e.getMessage())); + } +} diff --git a/src/main/java/com/server/hispath/exception/HisPathException.java b/src/main/java/com/server/hispath/exception/HisPathException.java new file mode 100644 index 0000000..d6d9b39 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/HisPathException.java @@ -0,0 +1,16 @@ +package com.server.hispath.exception; + +import org.springframework.http.HttpStatus; + +public class HisPathException extends RuntimeException{ + private final HttpStatus httpStatus; + + public HisPathException(String message, HttpStatus httpStatus){ + super(message); + this.httpStatus = httpStatus; + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } +} diff --git a/src/main/java/com/server/hispath/exception/MyPathLoginException.java b/src/main/java/com/server/hispath/exception/MyPathLoginException.java new file mode 100644 index 0000000..fe3096e --- /dev/null +++ b/src/main/java/com/server/hispath/exception/MyPathLoginException.java @@ -0,0 +1,16 @@ +package com.server.hispath.exception; + +import org.springframework.http.HttpStatus; + +public class MyPathLoginException extends RuntimeException { + private final HttpStatus httpStatus; + + public MyPathLoginException(String message, HttpStatus httpStatus) { + super(message); + this.httpStatus = httpStatus; + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } +} diff --git a/src/main/java/com/server/hispath/exception/activity/ActivityApplyException.java b/src/main/java/com/server/hispath/exception/activity/ActivityApplyException.java new file mode 100644 index 0000000..68fdd6f --- /dev/null +++ b/src/main/java/com/server/hispath/exception/activity/ActivityApplyException.java @@ -0,0 +1,12 @@ +package com.server.hispath.exception.activity; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class ActivityApplyException extends ActivityException { + public ActivityApplyException() { + super("이미 처리된 활동은 다시 신청할 수 없습니다.", HttpStatus.BAD_REQUEST); + } +} + diff --git a/src/main/java/com/server/hispath/exception/activity/ActivityException.java b/src/main/java/com/server/hispath/exception/activity/ActivityException.java new file mode 100644 index 0000000..e5e13be --- /dev/null +++ b/src/main/java/com/server/hispath/exception/activity/ActivityException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.activity; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class ActivityException extends HisPathException { + protected ActivityException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/activity/ActivityNotFoundException.java b/src/main/java/com/server/hispath/exception/activity/ActivityNotFoundException.java new file mode 100644 index 0000000..0ca6077 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/activity/ActivityNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.activity; + +import org.springframework.http.HttpStatus; + +public class ActivityNotFoundException extends ActivityException { + public ActivityNotFoundException() { + super("존재하지 않는 활동입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/activity/ParticipantDuplicateException.java b/src/main/java/com/server/hispath/exception/activity/ParticipantDuplicateException.java new file mode 100644 index 0000000..ba7a982 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/activity/ParticipantDuplicateException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.activity; + +import org.springframework.http.HttpStatus; + +public class ParticipantDuplicateException extends ActivityException { + public ParticipantDuplicateException(String studentNum, String name) { + super("이미 존재하는 참여자입니다.\n" + "학번: " + studentNum + " 이름: " + name, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/activity/ParticipantNotFoundException.java b/src/main/java/com/server/hispath/exception/activity/ParticipantNotFoundException.java new file mode 100644 index 0000000..e18dc92 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/activity/ParticipantNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.activity; + +import org.springframework.http.HttpStatus; + +public class ParticipantNotFoundException extends ActivityException { + public ParticipantNotFoundException() { + super("존재하지 않는 참여자 정보입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/authorization/AuthorizationException.java b/src/main/java/com/server/hispath/exception/authorization/AuthorizationException.java new file mode 100644 index 0000000..abf4062 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/authorization/AuthorizationException.java @@ -0,0 +1,12 @@ +package com.server.hispath.exception.authorization; + +import com.server.hispath.exception.MyPathLoginException; + +import org.springframework.http.HttpStatus; + +public abstract class AuthorizationException extends MyPathLoginException { + + protected AuthorizationException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/authorization/AuthorizationHeaderException.java b/src/main/java/com/server/hispath/exception/authorization/AuthorizationHeaderException.java new file mode 100644 index 0000000..8bd90d4 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/authorization/AuthorizationHeaderException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.authorization; + +import org.springframework.http.HttpStatus; + +public class AuthorizationHeaderException extends AuthorizationException { + public AuthorizationHeaderException() { + super("로그인이 필요한 서비스입니다.", HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/server/hispath/exception/authorization/InvalidTokenException.java b/src/main/java/com/server/hispath/exception/authorization/InvalidTokenException.java new file mode 100644 index 0000000..c2d5702 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/authorization/InvalidTokenException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.authorization; + +import org.springframework.http.HttpStatus; + +public class InvalidTokenException extends AuthorizationException { + public InvalidTokenException() { + super("로그인이 필요한 서비스입니다.", HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/server/hispath/exception/category/CategoryException.java b/src/main/java/com/server/hispath/exception/category/CategoryException.java new file mode 100644 index 0000000..be6e934 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/category/CategoryException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.category; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class CategoryException extends HisPathException { + protected CategoryException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/category/CategoryNotFoundException.java b/src/main/java/com/server/hispath/exception/category/CategoryNotFoundException.java new file mode 100644 index 0000000..9512ca1 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/category/CategoryNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.category; + +import org.springframework.http.HttpStatus; + +public class CategoryNotFoundException extends CategoryException { + public CategoryNotFoundException() { + super("존재하지 않는 카테고리입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/common/CommonException.java b/src/main/java/com/server/hispath/exception/common/CommonException.java new file mode 100644 index 0000000..b295bb3 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/common/CommonException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.common; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class CommonException extends HisPathException { + public CommonException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/common/ExcelDataFormatException.java b/src/main/java/com/server/hispath/exception/common/ExcelDataFormatException.java new file mode 100644 index 0000000..730d0bd --- /dev/null +++ b/src/main/java/com/server/hispath/exception/common/ExcelDataFormatException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.common; + +import org.springframework.http.HttpStatus; + +public class ExcelDataFormatException extends CommonException{ + public ExcelDataFormatException(String data) { + super("등록하려는 데이터의 양식에 문제가 있습니다.\n 문제되는 데이터 : " + data, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/common/ExcelFormatException.java b/src/main/java/com/server/hispath/exception/common/ExcelFormatException.java new file mode 100644 index 0000000..02cd485 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/common/ExcelFormatException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.common; + +import org.springframework.http.HttpStatus; + +public class ExcelFormatException extends CommonException{ + public ExcelFormatException(String msg) { + super("등록하려는 데이터의 양식에 문제가 있습니다. : " + msg, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/common/NotExcelExtensionException.java b/src/main/java/com/server/hispath/exception/common/NotExcelExtensionException.java new file mode 100644 index 0000000..4366c32 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/common/NotExcelExtensionException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.common; + +import org.springframework.http.HttpStatus; + +public class NotExcelExtensionException extends CommonException{ + public NotExcelExtensionException() { + super("Excel양식의 파일이 아닙니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/major/MajorException.java b/src/main/java/com/server/hispath/exception/major/MajorException.java new file mode 100644 index 0000000..30eaee0 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/major/MajorException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.major; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class MajorException extends HisPathException { + protected MajorException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/major/MajorNotFoundException.java b/src/main/java/com/server/hispath/exception/major/MajorNotFoundException.java new file mode 100644 index 0000000..ea6b9fd --- /dev/null +++ b/src/main/java/com/server/hispath/exception/major/MajorNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.major; + +import org.springframework.http.HttpStatus; + +public class MajorNotFoundException extends MajorException { + public MajorNotFoundException() { + super("존재하지 않는 전공입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/manager/ManagerException.java b/src/main/java/com/server/hispath/exception/manager/ManagerException.java new file mode 100644 index 0000000..e994378 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/manager/ManagerException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.manager; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class ManagerException extends HisPathException { + protected ManagerException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/manager/ManagerNoAuthorizationException.java b/src/main/java/com/server/hispath/exception/manager/ManagerNoAuthorizationException.java new file mode 100644 index 0000000..96d20ee --- /dev/null +++ b/src/main/java/com/server/hispath/exception/manager/ManagerNoAuthorizationException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.manager; + +import org.springframework.http.HttpStatus; + +public class ManagerNoAuthorizationException extends ManagerException { + public ManagerNoAuthorizationException() { + super("사용 권한이 없습니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/manager/ManagerNotFoundException.java b/src/main/java/com/server/hispath/exception/manager/ManagerNotFoundException.java new file mode 100644 index 0000000..20d1ec2 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/manager/ManagerNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.manager; + +import org.springframework.http.HttpStatus; + +public class ManagerNotFoundException extends ManagerException { + public ManagerNotFoundException() { + super("존재하지 않는 관리자입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/notice/NoticeException.java b/src/main/java/com/server/hispath/exception/notice/NoticeException.java new file mode 100644 index 0000000..f12dad1 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/notice/NoticeException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.notice; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class NoticeException extends HisPathException { + protected NoticeException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/notice/NoticeNotFoundException.java b/src/main/java/com/server/hispath/exception/notice/NoticeNotFoundException.java new file mode 100644 index 0000000..7c8b991 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/notice/NoticeNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.notice; + +import org.springframework.http.HttpStatus; + +public class NoticeNotFoundException extends NoticeException { + public NoticeNotFoundException() { + super("존재하지 않는 공지입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/GetAccessTokenException.java b/src/main/java/com/server/hispath/exception/oauth/GetAccessTokenException.java new file mode 100644 index 0000000..8d46e21 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/GetAccessTokenException.java @@ -0,0 +1,10 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class GetAccessTokenException extends OauthException { + + public GetAccessTokenException() { + super("소셜 로그인에 실패했습니다.", HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/GetUserInfoException.java b/src/main/java/com/server/hispath/exception/oauth/GetUserInfoException.java new file mode 100644 index 0000000..b95d708 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/GetUserInfoException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class GetUserInfoException extends OauthException { + public GetUserInfoException() { + super("소셜 로그인에 실패했습니다.", HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/InvalidTokenException.java b/src/main/java/com/server/hispath/exception/oauth/InvalidTokenException.java new file mode 100644 index 0000000..2c1093c --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/InvalidTokenException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class InvalidTokenException extends OauthException { + public InvalidTokenException() { + super("유효하지 않은 토큰입니다.", HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/NoSuchOAuthMemberException.java b/src/main/java/com/server/hispath/exception/oauth/NoSuchOAuthMemberException.java new file mode 100644 index 0000000..3ed0cf1 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/NoSuchOAuthMemberException.java @@ -0,0 +1,16 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +import lombok.Getter; + +@Getter +public class NoSuchOAuthMemberException extends OauthException { + + private final String email; + + public NoSuchOAuthMemberException(String email) { + super("소셜 로그인 회원이 아닙니다. 회원가입을 진행합니다.", HttpStatus.UNAUTHORIZED); + this.email = email; + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/NotHandongEmailException.java b/src/main/java/com/server/hispath/exception/oauth/NotHandongEmailException.java new file mode 100644 index 0000000..f893087 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/NotHandongEmailException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class NotHandongEmailException extends OauthException { + public NotHandongEmailException() { + super("한동대학교 메일이 아닙니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/OAuthLoginFailErrorResponse.java b/src/main/java/com/server/hispath/exception/oauth/OAuthLoginFailErrorResponse.java new file mode 100644 index 0000000..106b945 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/OAuthLoginFailErrorResponse.java @@ -0,0 +1,19 @@ +package com.server.hispath.exception.oauth; + +import com.server.hispath.exception.ExceptionResponse; + +import lombok.Getter; + +@Getter +public class OAuthLoginFailErrorResponse extends ExceptionResponse { + private final String email; + + private OAuthLoginFailErrorResponse(String message, String email) { + super(message); + this.email = email; + } + + public static OAuthLoginFailErrorResponse from(NoSuchOAuthMemberException exception) { + return new OAuthLoginFailErrorResponse(exception.getMessage(), exception.getEmail()); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/OauthException.java b/src/main/java/com/server/hispath/exception/oauth/OauthException.java new file mode 100644 index 0000000..ef3b66e --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/OauthException.java @@ -0,0 +1,12 @@ +package com.server.hispath.exception.oauth; + +import com.server.hispath.exception.MyPathLoginException; + +import org.springframework.http.HttpStatus; + +public abstract class OauthException extends MyPathLoginException { + + protected OauthException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/UnableToGetOauthResponseException.java b/src/main/java/com/server/hispath/exception/oauth/UnableToGetOauthResponseException.java new file mode 100644 index 0000000..aed4135 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/UnableToGetOauthResponseException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class UnableToGetOauthResponseException extends OauthException { + public UnableToGetOauthResponseException(String message) { + super(message, HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/server/hispath/exception/oauth/UnsupportedOauthProviderException.java b/src/main/java/com/server/hispath/exception/oauth/UnsupportedOauthProviderException.java new file mode 100644 index 0000000..3c81df2 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/oauth/UnsupportedOauthProviderException.java @@ -0,0 +1,10 @@ +package com.server.hispath.exception.oauth; + +import org.springframework.http.HttpStatus; + +public class UnsupportedOauthProviderException extends OauthException { + + public UnsupportedOauthProviderException() { + super("지원되지 않는 소셜로그인입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/resume/ResumeException.java b/src/main/java/com/server/hispath/exception/resume/ResumeException.java new file mode 100644 index 0000000..61ed34d --- /dev/null +++ b/src/main/java/com/server/hispath/exception/resume/ResumeException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.resume; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class ResumeException extends HisPathException { + protected ResumeException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/resume/ResumeNotFoundException.java b/src/main/java/com/server/hispath/exception/resume/ResumeNotFoundException.java new file mode 100644 index 0000000..d64c412 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/resume/ResumeNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.resume; + +import org.springframework.http.HttpStatus; + +public class ResumeNotFoundException extends ResumeException { + public ResumeNotFoundException() { + super("존재하지 않는 이력서입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/scholarship/ScholarshipDuplicateException.java b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipDuplicateException.java new file mode 100644 index 0000000..bfccd1d --- /dev/null +++ b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipDuplicateException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.scholarship; + +import org.springframework.http.HttpStatus; + +public class ScholarshipDuplicateException extends ScholarshipException { + public ScholarshipDuplicateException() { + super("중복되는 학생의 정보가 존재합니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/scholarship/ScholarshipException.java b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipException.java new file mode 100644 index 0000000..711f3e2 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.scholarship; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class ScholarshipException extends HisPathException { + protected ScholarshipException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotFoundException.java b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotFoundException.java new file mode 100644 index 0000000..9ad2a11 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotFoundException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.scholarship; + +import com.server.hispath.exception.resume.ResumeException; + +import org.springframework.http.HttpStatus; + +public class ScholarshipNotFoundException extends ScholarshipException { + public ScholarshipNotFoundException() { + super("존재하지 않는 장학금 수혜 내역입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotMatchException.java b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotMatchException.java new file mode 100644 index 0000000..0cd8181 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/scholarship/ScholarshipNotMatchException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.scholarship; + +import org.springframework.http.HttpStatus; + +public class ScholarshipNotMatchException extends ScholarshipException { + public ScholarshipNotMatchException(String msg) { + super("입력 맞지 않는 내역입니다.\n" + msg, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/student/SectionNotExistException.java b/src/main/java/com/server/hispath/exception/student/SectionNotExistException.java new file mode 100644 index 0000000..203ff9d --- /dev/null +++ b/src/main/java/com/server/hispath/exception/student/SectionNotExistException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.student; + +import org.springframework.http.HttpStatus; + +public class SectionNotExistException extends StudentException{ + public SectionNotExistException() { + super("존재하지 않는 섹션입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/student/StudentDataNotMatchException.java b/src/main/java/com/server/hispath/exception/student/StudentDataNotMatchException.java new file mode 100644 index 0000000..879cd2c --- /dev/null +++ b/src/main/java/com/server/hispath/exception/student/StudentDataNotMatchException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.student; + +import org.springframework.http.HttpStatus; + +public class StudentDataNotMatchException extends StudentException { + public StudentDataNotMatchException(String studentNum, String name) { + super("정보가 일치하지 않습니다.\n 학번 : " + studentNum + "\n 이름 : " + name, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/exception/student/StudentException.java b/src/main/java/com/server/hispath/exception/student/StudentException.java new file mode 100644 index 0000000..1e96c76 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/student/StudentException.java @@ -0,0 +1,11 @@ +package com.server.hispath.exception.student; + +import com.server.hispath.exception.HisPathException; + +import org.springframework.http.HttpStatus; + +public class StudentException extends HisPathException { + protected StudentException(String message, HttpStatus httpStatus) { + super(message, httpStatus); + } +} diff --git a/src/main/java/com/server/hispath/exception/student/StudentNotFoundException.java b/src/main/java/com/server/hispath/exception/student/StudentNotFoundException.java new file mode 100644 index 0000000..f2de707 --- /dev/null +++ b/src/main/java/com/server/hispath/exception/student/StudentNotFoundException.java @@ -0,0 +1,9 @@ +package com.server.hispath.exception.student; + +import org.springframework.http.HttpStatus; + +public class StudentNotFoundException extends StudentException{ + public StudentNotFoundException() { + super("존재하지 않는 학생입니다.", HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/server/hispath/filters/LoggingFilter.java b/src/main/java/com/server/hispath/filters/LoggingFilter.java new file mode 100644 index 0000000..002ca00 --- /dev/null +++ b/src/main/java/com/server/hispath/filters/LoggingFilter.java @@ -0,0 +1,133 @@ +package com.server.hispath.filters; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +@Component +public class LoggingFilter extends OncePerRequestFilter { + protected static final Logger log = LoggerFactory.getLogger(LoggingFilter.class); + + @Override + public void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain + ) throws ServletException, IOException { + + MDC.put("traceId", UUID.randomUUID().toString()); + if(isFileUpload(request)){ + filterChain.doFilter(request,response); + MDC.clear(); + return; + } + doFilterWrapped(new RequestWrapper(request), new ResponseWrapper(response), filterChain); + MDC.clear(); + } + + public void doFilterWrapped( + RequestWrapper request, + ContentCachingResponseWrapper response, + FilterChain filterChain + ) throws ServletException, IOException { + + try { + logRequest(request); + filterChain.doFilter(request, response); + } finally { + logResponse(response); + response.copyBodyToResponse(); + } + } + + private static void logRequest(RequestWrapper request) throws IOException { + String queryString = request.getQueryString(); + String requestURI = request.getRequestURI(); + if (!Objects.isNull(queryString)) { + requestURI += queryString; + } + log.info("Request : {} uri=[{}] content-type=[{}]", + request.getMethod(), + requestURI, + request.getContentType() + ); + + logPayload("Request", request.getContentType(), request.getInputStream()); + } + + private static void logResponse(ContentCachingResponseWrapper response) throws IOException { + logPayload("Response", response.getContentType(), response.getContentInputStream()); + } + + private static void logPayload(String prefix, String contentType, InputStream inputStream) throws IOException { + if (Objects.isNull(contentType)) { + contentType = "application/json"; + } + boolean visible = isVisible(MediaType.valueOf(contentType)); + if (visible) { + logContentPayload(prefix, inputStream); + return; + } + log.info("{} Payload: Binary Content", prefix); + } + + private static void logContentPayload(String prefix, InputStream inputStream) throws IOException { + byte[] content = StreamUtils.copyToByteArray(inputStream); + if (content.length > 0) { + String contentString = new String(content); + log.info("{} Payload: {}", prefix, contentString); + } + } + + private static boolean isVisible(MediaType mediaType) { + final List VISIBLE_TYPES = Arrays.asList( + MediaType.valueOf("text/*"), + MediaType.APPLICATION_FORM_URLENCODED, + MediaType.APPLICATION_JSON, + MediaType.APPLICATION_XML, + MediaType.valueOf("application/*+json"), + MediaType.valueOf("application/*+xml"), + MediaType.MULTIPART_FORM_DATA + ); + + return VISIBLE_TYPES.stream() + .anyMatch(visibleType -> visibleType.includes(mediaType)); + } + + + private boolean isFileUpload(HttpServletRequest request){ + if(Objects.equals("POST", request.getMethod())){ + if(Objects.equals("/api/mileages",request.getRequestURI())){ + return true; + } + if(Objects.equals("/api/students",request.getRequestURI())){ + return true; + } + if(Objects.equals("/api/mileage/students",request.getRequestURI())){ + return true; + } + } + if(Objects.equals("PUT", request.getMethod()) && Objects.equals("/api/scholarship/approval", request.getRequestURI())){ + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/filters/RequestWrapper.java b/src/main/java/com/server/hispath/filters/RequestWrapper.java new file mode 100644 index 0000000..339490b --- /dev/null +++ b/src/main/java/com/server/hispath/filters/RequestWrapper.java @@ -0,0 +1,54 @@ +package com.server.hispath.filters; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import org.springframework.util.StreamUtils; + +public class RequestWrapper extends HttpServletRequestWrapper { + + private byte[] cachedInputStream; + + public RequestWrapper(HttpServletRequest request) throws IOException { + super(request); + InputStream requestInputStream = request.getInputStream(); + this.cachedInputStream = StreamUtils.copyToByteArray(requestInputStream); + } + + @Override + public ServletInputStream getInputStream() { + return new ServletInputStream() { + private InputStream cachedBodyInputStream = new ByteArrayInputStream(cachedInputStream); + + @Override + public boolean isFinished() { + try { + return cachedBodyInputStream.available() == 0; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + throw new UnsupportedOperationException(); + } + + @Override + public int read() throws IOException { + return cachedBodyInputStream.read(); + } + }; + } +} diff --git a/src/main/java/com/server/hispath/filters/ResponseWrapper.java b/src/main/java/com/server/hispath/filters/ResponseWrapper.java new file mode 100644 index 0000000..0c88e01 --- /dev/null +++ b/src/main/java/com/server/hispath/filters/ResponseWrapper.java @@ -0,0 +1,11 @@ +package com.server.hispath.filters; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.util.ContentCachingResponseWrapper; + +public class ResponseWrapper extends ContentCachingResponseWrapper { + public ResponseWrapper(HttpServletResponse response) { + super(response); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/major/application/MajorService.java b/src/main/java/com/server/hispath/major/application/MajorService.java new file mode 100644 index 0000000..a70e18a --- /dev/null +++ b/src/main/java/com/server/hispath/major/application/MajorService.java @@ -0,0 +1,61 @@ +package com.server.hispath.major.application; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.exception.major.MajorNotFoundException; +import com.server.hispath.major.application.dto.MajorContentDto; +import com.server.hispath.major.application.dto.MajorDto; +import com.server.hispath.major.domain.Major; +import com.server.hispath.major.domain.repository.MajorRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + + +@Service +@RequiredArgsConstructor +public class MajorService { + + private final MajorRepository majorRepository; + + @Transactional + public Long create(MajorContentDto dto) { + Major major = Major.from(dto); + Major savedMajor = majorRepository.save(major); + return savedMajor.getId(); + } + + @Transactional + public MajorDto find(Long id) { + Major major = this.findById(id); + return MajorDto.from(major); + } + + @Transactional + public MajorDto update(Long id, MajorContentDto dto) { + Major major = this.findById(id); + major.update(dto); + + return MajorDto.from(major); + } + + @Transactional + public void delete(Long id) { + majorRepository.deleteById(id); + } + + public Major findById(Long id) { + return majorRepository.findById(id).orElseThrow(MajorNotFoundException::new); + } + + @Transactional(readOnly = true) + public List findAll() { + return majorRepository.findAll() + .stream() + .map(MajorDto::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/major/application/dto/MajorContentDto.java b/src/main/java/com/server/hispath/major/application/dto/MajorContentDto.java new file mode 100644 index 0000000..03c4008 --- /dev/null +++ b/src/main/java/com/server/hispath/major/application/dto/MajorContentDto.java @@ -0,0 +1,20 @@ +package com.server.hispath.major.application.dto; + +import com.server.hispath.major.presentation.request.MajorCURequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class MajorContentDto { + + private String majorName; + + public static MajorContentDto from(MajorCURequest request) { + return new MajorContentDto(request.getMajorName()); + } +} diff --git a/src/main/java/com/server/hispath/major/application/dto/MajorDto.java b/src/main/java/com/server/hispath/major/application/dto/MajorDto.java new file mode 100644 index 0000000..6e95742 --- /dev/null +++ b/src/main/java/com/server/hispath/major/application/dto/MajorDto.java @@ -0,0 +1,18 @@ +package com.server.hispath.major.application.dto; + +import com.server.hispath.major.domain.Major; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MajorDto { + private Long id; + private String name; + private String profile; + public static MajorDto from(Major major) { + return new MajorDto(major.getId(), major.getName(), major.getProfile()); + } +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/major/domain/Major.java b/src/main/java/com/server/hispath/major/domain/Major.java new file mode 100644 index 0000000..44afc87 --- /dev/null +++ b/src/main/java/com/server/hispath/major/domain/Major.java @@ -0,0 +1,48 @@ +package com.server.hispath.major.domain; + +import javax.persistence.*; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.server.hispath.common.BaseEntity; + + +import com.server.hispath.major.application.dto.MajorContentDto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +import java.time.LocalDate; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE major SET deleted = true Where id = ?") +public class Major extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String profile; + + public static Major from(MajorContentDto dto){ + return Major.builder() + .name(dto.getMajorName()) + .build(); + } + + public void update(MajorContentDto dto){ + this.name = dto.getMajorName(); + } + + + + +} diff --git a/src/main/java/com/server/hispath/major/domain/repository/MajorRepository.java b/src/main/java/com/server/hispath/major/domain/repository/MajorRepository.java new file mode 100644 index 0000000..1cd245b --- /dev/null +++ b/src/main/java/com/server/hispath/major/domain/repository/MajorRepository.java @@ -0,0 +1,12 @@ +package com.server.hispath.major.domain.repository; + +import java.util.Optional; + +import com.server.hispath.major.domain.Major; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MajorRepository extends JpaRepository { + + Major findByName(String name); +} diff --git a/src/main/java/com/server/hispath/major/presentation/MajorController.java b/src/main/java/com/server/hispath/major/presentation/MajorController.java new file mode 100644 index 0000000..0fcca8e --- /dev/null +++ b/src/main/java/com/server/hispath/major/presentation/MajorController.java @@ -0,0 +1,74 @@ +package com.server.hispath.major.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.major.application.MajorService; +import com.server.hispath.major.application.dto.MajorContentDto; +import com.server.hispath.major.application.dto.MajorDto; +import com.server.hispath.major.presentation.request.MajorCURequest; +import com.server.hispath.major.presentation.response.MajorResponse; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class MajorController { + + private final MajorService majorService; + + @PostMapping("/major") + @ApiOperation(value = ApiDoc.MAJOR_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@RequestBody MajorCURequest request) { + Long id = majorService.create(MajorContentDto.from(request)); + return ResponseEntity.ok(id); + } + + + @GetMapping("/major/{id}") + @ApiOperation(value = ApiDoc.MAJOR_READ) + @RequiredLogin + public ResponseEntity find(@PathVariable Long id) { + MajorResponse response = MajorResponse.from(majorService.find(id)); + return ResponseEntity.ok(response); + } + + @PatchMapping("/major/{id}") + @ApiOperation(value = ApiDoc.MAJOR_UPDATE) + @RequiredManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody MajorCURequest request) { + MajorDto dto = majorService.update(id, MajorContentDto.from(request)); + MajorResponse response = MajorResponse.from(dto); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/major/{id}") + @ApiOperation(value = ApiDoc.MAJOR_DELETE) + @RequiredManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + majorService.delete(id); + return ResponseEntity.ok(id); + } + + @GetMapping("/majors") + @ApiOperation(value = ApiDoc.MAJOR_READ_ALL) + @RequiredLogin + public ResponseEntity> findAll() { + List responses = majorService.findAll() + .stream() + .map(MajorResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + +} diff --git a/src/main/java/com/server/hispath/major/presentation/request/MajorCURequest.java b/src/main/java/com/server/hispath/major/presentation/request/MajorCURequest.java new file mode 100644 index 0000000..b275101 --- /dev/null +++ b/src/main/java/com/server/hispath/major/presentation/request/MajorCURequest.java @@ -0,0 +1,12 @@ +package com.server.hispath.major.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class MajorCURequest { + private String majorName; +} diff --git a/src/main/java/com/server/hispath/major/presentation/response/MajorResponse.java b/src/main/java/com/server/hispath/major/presentation/response/MajorResponse.java new file mode 100644 index 0000000..514dbda --- /dev/null +++ b/src/main/java/com/server/hispath/major/presentation/response/MajorResponse.java @@ -0,0 +1,20 @@ +package com.server.hispath.major.presentation.response; + + +import com.server.hispath.major.application.dto.MajorDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MajorResponse { + private Long id; + private String name; + private String profile; + + public static MajorResponse from(MajorDto dto) { + return new MajorResponse(dto.getId(), dto.getName(), dto.getProfile()); + } +} diff --git a/src/main/java/com/server/hispath/manager/application/ManagerService.java b/src/main/java/com/server/hispath/manager/application/ManagerService.java new file mode 100644 index 0000000..089259f --- /dev/null +++ b/src/main/java/com/server/hispath/manager/application/ManagerService.java @@ -0,0 +1,97 @@ +package com.server.hispath.manager.application; + +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.exception.manager.ManagerNotFoundException; +import com.server.hispath.manager.application.dto.ManagerCUDto; +import com.server.hispath.manager.application.dto.ManagerDashboardDto; +import com.server.hispath.manager.application.dto.ManagerDto; +import com.server.hispath.manager.application.dto.ManagerUpdateDto; +import com.server.hispath.manager.domain.DailyInfo; +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.manager.domain.repository.DailyInfoRepository; +import com.server.hispath.manager.domain.repository.ManagerRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ManagerService { + + private final ManagerRepository managerRepository; + private final DailyInfoRepository dailyInfoRepository; + + @Transactional + public Long create(ManagerCUDto dto) { + Manager savedManager = managerRepository.save(Manager.of(dto)); + return savedManager.getId(); + } + + @Transactional(readOnly = true) + public ManagerDto findManager(Long id) { + return ManagerDto.of(this.findById(id)); + } + + @Transactional(readOnly = true) + public List findManagers() { + return managerRepository.findAll() + .stream() + .map(ManagerDto::of) + .collect(Collectors.toList()); + } + + @Transactional + public ManagerDto update(Long id, ManagerCUDto dto) { + Manager manager = this.findById(id); + manager.update(dto); + return ManagerDto.of(manager); + } + + @Transactional + public ManagerDto update(Long id, ManagerUpdateDto dto){ + Manager manager = this.findById(id); + manager.update(dto); + return ManagerDto.of(manager); + } + + @Transactional + public Long delete(Long id) { + managerRepository.deleteById(id); + return id; + } + + @Transactional + public Long approve(Long managerId, int level) { + Manager manager = this.findById(managerId); + manager.approve(); + manager.updateLevel(level); + return managerId; + } + + public Manager findById(Long id) { + return managerRepository.findById(id).orElseThrow(ManagerNotFoundException::new); + } + + @Transactional(readOnly = true) + public ManagerDashboardDto getDashboard(Long managerId) { + Manager manager = this.findById(managerId); + List dailyInfos = dailyInfoRepository.findDailyInfoByDateBetweenOrderByDateAsc(LocalDate.now() + .minusDays(6), LocalDate.now()); + Long[] loginCounts = dailyInfos.stream() + .map(DailyInfo::getLoginCnt) + .toArray(Long[]::new); + Long totalLoginCnt = dailyInfoRepository.getTotalLoginCnt(); + + return ManagerDashboardDto.of(manager, loginCounts, totalLoginCnt); + } + + @Transactional(readOnly = true) + public String getEmail(Long memberId){ + return this.findById(memberId).getEmail(); + } +} diff --git a/src/main/java/com/server/hispath/manager/application/dto/ManagerCUDto.java b/src/main/java/com/server/hispath/manager/application/dto/ManagerCUDto.java new file mode 100644 index 0000000..b6df6d5 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/application/dto/ManagerCUDto.java @@ -0,0 +1,23 @@ +package com.server.hispath.manager.application.dto; + +import com.server.hispath.manager.presentation.request.ManagerCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerCUDto { + + private String name; + private String profile; + private String email; + private String department; + + public static ManagerCUDto of(ManagerCURequest request) { + return new ManagerCUDto(request.getName(), request.getProfile(), request.getEmail(), request.getDepartment()); + } + +} \ No newline at end of file diff --git a/src/main/java/com/server/hispath/manager/application/dto/ManagerDashboardDto.java b/src/main/java/com/server/hispath/manager/application/dto/ManagerDashboardDto.java new file mode 100644 index 0000000..64aba69 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/application/dto/ManagerDashboardDto.java @@ -0,0 +1,27 @@ +package com.server.hispath.manager.application.dto; + +import com.server.hispath.manager.domain.Manager; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerDashboardDto { + private Long id; + private String profile; + private String name; + private String department; + private boolean approved; + private String email; + private int power; + private Long[] loginCounts; + private Long totalCounts; + + public static ManagerDashboardDto of(Manager manager, Long[] loginCounts, Long totalCounts) { + return new ManagerDashboardDto(manager.getId(), manager.getProfile(), manager.getName(), manager.getDepartment(), + manager.isApproved(), manager.getEmail(), manager.getPower(), loginCounts, totalCounts); + } +} diff --git a/src/main/java/com/server/hispath/manager/application/dto/ManagerDto.java b/src/main/java/com/server/hispath/manager/application/dto/ManagerDto.java new file mode 100644 index 0000000..8bf1496 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/application/dto/ManagerDto.java @@ -0,0 +1,31 @@ +package com.server.hispath.manager.application.dto; + +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.notice.domain.Notice; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerDto { + private Long id; + private String name; + private String email; + private String profile; + private String department; + private int power; + private boolean approved; + + public static ManagerDto of(Manager manager) { + return new ManagerDto(manager.getId(), manager.getName(), manager.getEmail(), + manager.getProfile(), manager.getDepartment(), manager.getPower(), manager.isApproved()); + } + + +} diff --git a/src/main/java/com/server/hispath/manager/application/dto/ManagerUpdateDto.java b/src/main/java/com/server/hispath/manager/application/dto/ManagerUpdateDto.java new file mode 100644 index 0000000..f171d65 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/application/dto/ManagerUpdateDto.java @@ -0,0 +1,22 @@ +package com.server.hispath.manager.application.dto; + +import com.server.hispath.manager.presentation.request.ManagerUpdateRequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerUpdateDto { + private String name; + private String profile; + private String email; + private String department; + private int power; + + public static ManagerUpdateDto from(ManagerUpdateRequest request){ + return new ManagerUpdateDto(request.getName(), request.getProfile(), request.getEmail(), request.getDepartment(), request.getPower()); + } +} diff --git a/src/main/java/com/server/hispath/manager/domain/DailyInfo.java b/src/main/java/com/server/hispath/manager/domain/DailyInfo.java new file mode 100644 index 0000000..0736443 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/domain/DailyInfo.java @@ -0,0 +1,36 @@ +package com.server.hispath.manager.domain; + +import java.time.LocalDate; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import com.server.hispath.common.BaseEntity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE dailyInfo SET deleted = true Where id = ?") +public class DailyInfo extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + LocalDate date = LocalDate.now(); + + Long loginCnt = 1L; + + public void login(){ + loginCnt++; + } +} diff --git a/src/main/java/com/server/hispath/manager/domain/Manager.java b/src/main/java/com/server/hispath/manager/domain/Manager.java new file mode 100644 index 0000000..b3b54eb --- /dev/null +++ b/src/main/java/com/server/hispath/manager/domain/Manager.java @@ -0,0 +1,73 @@ +package com.server.hispath.manager.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import com.server.hispath.common.BaseEntity; +import com.server.hispath.manager.application.dto.ManagerCUDto; +import com.server.hispath.manager.application.dto.ManagerUpdateDto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE manager SET deleted = true Where id = ?") +public class Manager extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private int power; + private String name; + private String email; + private String profile; + private String department; + private boolean approved; + + + public static Manager of(ManagerCUDto dto) { + return Manager.builder() + .name(dto.getName()) + .email(dto.getEmail()) + .profile(dto.getProfile()) + .department(dto.getDepartment()) + .approved(false) + .build(); + } + + public void update(ManagerCUDto dto) { + this.email = dto.getEmail(); + this.name = dto.getName(); + this.profile = dto.getProfile(); + this.department = dto.getDepartment(); + } + + public void update(ManagerUpdateDto dto){ + this.email = dto.getEmail(); + this.name = dto.getName(); + this.profile = dto.getProfile(); + this.department = dto.getDepartment(); + this.power = dto.getPower(); + } + + public void approve() { + this.approved = true; + } + + public void updateLevel(int level) {this.power = level;} + + public boolean isSuperManager() { + return this.power > 1; + } +} diff --git a/src/main/java/com/server/hispath/manager/domain/repository/DailyInfoRepository.java b/src/main/java/com/server/hispath/manager/domain/repository/DailyInfoRepository.java new file mode 100644 index 0000000..5c5d54e --- /dev/null +++ b/src/main/java/com/server/hispath/manager/domain/repository/DailyInfoRepository.java @@ -0,0 +1,20 @@ +package com.server.hispath.manager.domain.repository; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +import com.server.hispath.manager.domain.DailyInfo; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface DailyInfoRepository extends JpaRepository { + Optional findFirstByDate(LocalDate date); + + List findDailyInfoByDateBetweenOrderByDateAsc(LocalDate start, LocalDate end); + + @Query("select sum(d.loginCnt) from DailyInfo d ") + Long getTotalLoginCnt(); + +} diff --git a/src/main/java/com/server/hispath/manager/domain/repository/ManagerRepository.java b/src/main/java/com/server/hispath/manager/domain/repository/ManagerRepository.java new file mode 100644 index 0000000..734b2d4 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/domain/repository/ManagerRepository.java @@ -0,0 +1,12 @@ +package com.server.hispath.manager.domain.repository; + +import java.util.Optional; + +import com.server.hispath.manager.domain.Manager; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ManagerRepository extends JpaRepository { + + Optional findByEmail(String email); +} diff --git a/src/main/java/com/server/hispath/manager/presentation/ManagerController.java b/src/main/java/com/server/hispath/manager/presentation/ManagerController.java new file mode 100644 index 0000000..b754262 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/ManagerController.java @@ -0,0 +1,107 @@ +package com.server.hispath.manager.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.auth.domain.LoginManager; +import com.server.hispath.auth.domain.ManagerLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.auth.domain.RequiredSuperManagerLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.manager.application.ManagerService; +import com.server.hispath.manager.application.dto.ManagerCUDto; +import com.server.hispath.manager.application.dto.ManagerDashboardDto; +import com.server.hispath.manager.application.dto.ManagerUpdateDto; +import com.server.hispath.manager.presentation.request.ManagerApproveRequest; +import com.server.hispath.manager.presentation.request.ManagerCURequest; +import com.server.hispath.manager.presentation.request.ManagerUpdateRequest; +import com.server.hispath.manager.presentation.response.ManagerEmailResponse; +import com.server.hispath.manager.presentation.response.ManagerResponse; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ManagerController { + + private final ManagerService managerService; + + @PostMapping("/manager") + @ApiOperation(value = ApiDoc.MANAGER_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@RequestBody ManagerCURequest request) { + Long savedId = managerService.create(ManagerCUDto.of(request)); + return ResponseEntity.ok(savedId); + } + + @GetMapping("/manager/{id}") + @ApiOperation(value = ApiDoc.MANAGER_READ) + @RequiredManagerLogin + public ResponseEntity find(@PathVariable Long id) { + ManagerResponse response = ManagerResponse.of(managerService.findManager(id)); + return ResponseEntity.ok(response); + } + + @GetMapping("/managers") + @ApiOperation(value = ApiDoc.MANAGER_READ_ALL) + @RequiredManagerLogin + public ResponseEntity> findAll() { + List responses = managerService.findManagers() + .stream() + .map(ManagerResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @PutMapping("/manager/{id}") + @ApiOperation(value = ApiDoc.MANAGER_UPDATE) + @RequiredSuperManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody ManagerUpdateRequest request) { + ManagerResponse response = ManagerResponse.of(managerService.update(id, ManagerUpdateDto.from(request))); + return ResponseEntity.ok(response); + } + + @PutMapping("/manager") + @ApiOperation(value = ApiDoc.MANAGER_PROFILE_UPDATE) + @RequiredManagerLogin + public ResponseEntity updateProfile(@ManagerLogin LoginManager loginManager, @RequestBody ManagerCURequest request) { + ManagerResponse response = ManagerResponse.of(managerService.update(loginManager.getId(), ManagerCUDto.of(request))); + return ResponseEntity.ok(response); + } + + @PutMapping("/manager/approve") + @ApiOperation(value = ApiDoc.MANAGER_APPROVE) + @RequiredSuperManagerLogin + public ResponseEntity approve(@RequestBody ManagerApproveRequest request) { + Long response = managerService.approve(request.getManagerId(), request.getLevel()); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/manager/{id}") + @ApiOperation(value = ApiDoc.MANAGER_DELETE) + @RequiredSuperManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + Long response = managerService.delete(id); + return ResponseEntity.ok(response); + } + + @GetMapping("/manager/dashboard") + @ApiOperation(value = ApiDoc.MANAGER_DASHBOARD) + @RequiredManagerLogin + public ResponseEntity getDashboard(@ManagerLogin LoginManager loginManager) { + return ResponseEntity.ok(managerService.getDashboard(loginManager.getId())); + } + + @GetMapping("/manager/email") + @ApiOperation(value = ApiDoc.MANAGER_EMAIL) + @RequiredManagerLogin + public ResponseEntity getEmail(@ManagerLogin LoginManager loginManager) { + return ResponseEntity.ok(new ManagerEmailResponse(managerService.getEmail(loginManager.getId()))); + } +} diff --git a/src/main/java/com/server/hispath/manager/presentation/request/ManagerApproveRequest.java b/src/main/java/com/server/hispath/manager/presentation/request/ManagerApproveRequest.java new file mode 100644 index 0000000..ff4f801 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/request/ManagerApproveRequest.java @@ -0,0 +1,15 @@ +package com.server.hispath.manager.presentation.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerApproveRequest { + private Long managerId; + private int level; +} diff --git a/src/main/java/com/server/hispath/manager/presentation/request/ManagerCURequest.java b/src/main/java/com/server/hispath/manager/presentation/request/ManagerCURequest.java new file mode 100644 index 0000000..d2e58e8 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/request/ManagerCURequest.java @@ -0,0 +1,17 @@ +package com.server.hispath.manager.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ManagerCURequest { + + private String name; + private String profile; + private String email; + private String department; + +} diff --git a/src/main/java/com/server/hispath/manager/presentation/request/ManagerUpdateRequest.java b/src/main/java/com/server/hispath/manager/presentation/request/ManagerUpdateRequest.java new file mode 100644 index 0000000..3829524 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/request/ManagerUpdateRequest.java @@ -0,0 +1,18 @@ +package com.server.hispath.manager.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ManagerUpdateRequest { + + private String name; + private String profile; + private String email; + private String department; + private int power; + +} diff --git a/src/main/java/com/server/hispath/manager/presentation/response/ManagerEmailResponse.java b/src/main/java/com/server/hispath/manager/presentation/response/ManagerEmailResponse.java new file mode 100644 index 0000000..a2ededf --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/response/ManagerEmailResponse.java @@ -0,0 +1,12 @@ +package com.server.hispath.manager.presentation.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerEmailResponse { + private String email; +} diff --git a/src/main/java/com/server/hispath/manager/presentation/response/ManagerResponse.java b/src/main/java/com/server/hispath/manager/presentation/response/ManagerResponse.java new file mode 100644 index 0000000..b967442 --- /dev/null +++ b/src/main/java/com/server/hispath/manager/presentation/response/ManagerResponse.java @@ -0,0 +1,27 @@ +package com.server.hispath.manager.presentation.response; + +import com.server.hispath.manager.application.dto.ManagerDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ManagerResponse { + private Long id; + private int power; + private String name; + private String email; + private String profile; + private String department; + private boolean approved; + + + public static ManagerResponse of(ManagerDto dto) { + return new ManagerResponse(dto.getId(), dto.getPower(), dto.getName(), + dto.getEmail(), dto.getProfile(), dto.getDepartment(), dto.isApproved()); + } + +} diff --git a/src/main/java/com/server/hispath/notice/application/NoticeService.java b/src/main/java/com/server/hispath/notice/application/NoticeService.java new file mode 100644 index 0000000..5d9754e --- /dev/null +++ b/src/main/java/com/server/hispath/notice/application/NoticeService.java @@ -0,0 +1,83 @@ +package com.server.hispath.notice.application; + +import com.server.hispath.exception.notice.NoticeNotFoundException; +import com.server.hispath.manager.application.ManagerService; +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.notice.application.dto.DashboardNoticeDto; +import com.server.hispath.notice.application.dto.NoticeContentDto; +import com.server.hispath.notice.application.dto.NoticeDto; +import com.server.hispath.notice.domain.Notice; +import com.server.hispath.notice.domain.repository.NoticeRepository; + +import com.server.hispath.notice.presentation.request.NoticeRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class NoticeService { + + private final NoticeRepository noticeRepository; + + private final ManagerService managerService; + + private Notice findById(Long id) { + Notice ret = noticeRepository.findById(id).orElseThrow(NoticeNotFoundException::new); + return ret; + } + + @Transactional + public Long create(Long managerId, NoticeContentDto dto) { + Manager manager = managerService.findById(managerId); + Notice notice = Notice.from(manager, dto); + Notice savedNotice = noticeRepository.save(notice); + return savedNotice.getId(); + } + + @Transactional(readOnly = true) + public List findAll() { + List notices = noticeRepository.findAll(); + return notices.stream().map(NoticeDto::from).collect(Collectors.toList()); + } + @Transactional(readOnly = true) + public List findImp() { + LocalDate today = LocalDate.now(); + List notices = noticeRepository.findAllImpInPub(today); + return notices.stream().map(DashboardNoticeDto::of).collect(Collectors.toList()); + } + + @Transactional + public NoticeDto find(Long id) { + Notice notice = this.findById(id); + notice.viewCount(); + return NoticeDto.from(notice); + } + + @Transactional + public NoticeDto update(Long id, Long managerId, NoticeContentDto dto) { + Notice notice = this.findById(id); + Manager manager = managerService.findById(managerId); + notice.update(manager, dto); + return NoticeDto.from(notice); + } + + @Transactional + public void delete(Long id) { + noticeRepository.deleteById(id); + } + + @Transactional(readOnly = true) + public List findRecentNotice() { + List notices = noticeRepository.findTop6ByPubDateLessThanEqualAndExpDateGreaterThanEqualOrderByPubDateDesc(LocalDate.now(), LocalDate.now()); + + return notices.stream() + .map(DashboardNoticeDto::of) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/notice/application/dto/DashboardNoticeDto.java b/src/main/java/com/server/hispath/notice/application/dto/DashboardNoticeDto.java new file mode 100644 index 0000000..b21421d --- /dev/null +++ b/src/main/java/com/server/hispath/notice/application/dto/DashboardNoticeDto.java @@ -0,0 +1,25 @@ +package com.server.hispath.notice.application.dto; + +import java.time.LocalDate; + +import com.server.hispath.notice.domain.Notice; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class DashboardNoticeDto { + private Long id; + private String title; + private String content; + private LocalDate pubDate; + private LocalDate expDate; + private LocalDate regDate; + + public static DashboardNoticeDto of(Notice notice) { + return new DashboardNoticeDto(notice.getId(), notice.getTitle(), notice.getContent(), notice.getPubDate(), notice.getExpDate(), notice.getCreatedAt().toLocalDate()); + } +} diff --git a/src/main/java/com/server/hispath/notice/application/dto/NoticeContentDto.java b/src/main/java/com/server/hispath/notice/application/dto/NoticeContentDto.java new file mode 100644 index 0000000..a043d16 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/application/dto/NoticeContentDto.java @@ -0,0 +1,33 @@ +package com.server.hispath.notice.application.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.server.hispath.notice.presentation.request.NoticeRequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import java.time.LocalDate; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class NoticeContentDto { + private String title; + private String content; + private int viewCnt; + private boolean importance; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate pubDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate expDate; + + public static NoticeContentDto from(NoticeRequest request){ + return new NoticeContentDto(request.getTitle(), request.getContent(), + request.getViewCnt(), request.isImportance(), request.getPubDate(), request.getExpDate()); + } +} diff --git a/src/main/java/com/server/hispath/notice/application/dto/NoticeDto.java b/src/main/java/com/server/hispath/notice/application/dto/NoticeDto.java new file mode 100644 index 0000000..f3cb7b7 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/application/dto/NoticeDto.java @@ -0,0 +1,38 @@ +package com.server.hispath.notice.application.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.server.hispath.manager.application.dto.ManagerDto; +import com.server.hispath.notice.domain.Notice; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NoticeDto{ + private Long id; + private ManagerDto manager; + private String title; + private String content; + private int viewCnt; + private boolean importance; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDateTime regDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate pubDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate expDate; + + public static NoticeDto from(Notice notice) { + return new NoticeDto(notice.getId(), ManagerDto.of(notice.getManager()), notice.getTitle(), + notice.getContent(), notice.getViewCnt(), notice.isImportance(),notice.getCreatedAt() ,notice.getPubDate(), notice.getExpDate()); + } +} diff --git a/src/main/java/com/server/hispath/notice/domain/Notice.java b/src/main/java/com/server/hispath/notice/domain/Notice.java new file mode 100644 index 0000000..d9f8394 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/domain/Notice.java @@ -0,0 +1,78 @@ +package com.server.hispath.notice.domain; + +import javax.persistence.*; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.server.hispath.manager.domain.Manager; +import com.server.hispath.common.BaseEntity; + +import com.server.hispath.notice.application.dto.NoticeContentDto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +import java.time.LocalDate; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE notice SET deleted = true Where id = ?") +public class Notice extends BaseEntity { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Manager manager; + + private String title; + + @Column(columnDefinition = "TEXT") + private String content; + + private int viewCnt; + + private boolean importance; + + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate pubDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate expDate; + + public static Notice from(Manager manager, NoticeContentDto dto) { + return Notice.builder() + .manager(manager) + .title(dto.getTitle()) + .content(dto.getContent()) + .viewCnt(dto.getViewCnt()) + .importance(dto.isImportance()) + .pubDate(dto.getPubDate()) + .expDate(dto.getExpDate()) + .build(); + } + + public void update(Manager manager, NoticeContentDto dto) { + this.manager = manager; + this.title = dto.getTitle(); + this.content = dto.getContent(); + this.viewCnt = dto.getViewCnt(); + this.importance = dto.isImportance(); + this.pubDate = dto.getPubDate(); + this.expDate = dto.getExpDate(); + } + public void viewCount(){ + this.viewCnt++; + } + + +} diff --git a/src/main/java/com/server/hispath/notice/domain/repository/NoticeRepository.java b/src/main/java/com/server/hispath/notice/domain/repository/NoticeRepository.java new file mode 100644 index 0000000..74395a8 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/domain/repository/NoticeRepository.java @@ -0,0 +1,26 @@ +package com.server.hispath.notice.domain.repository; + +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.notice.domain.Notice; + +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.time.LocalDate; +import java.util.List; +import java.util.Optional; + +@Repository +public interface NoticeRepository extends JpaRepository { + List findTop6ByPubDateLessThanEqualAndExpDateGreaterThanEqualOrderByPubDateDesc(LocalDate pubDate, LocalDate expDate); + + @Query("select n from Notice n " + + "where n.importance = true " + + "and n.pubDate <= :today " + + "and n.expDate >= :today") + List findAllImpInPub(LocalDate today); + +} diff --git a/src/main/java/com/server/hispath/notice/presentation/NoticeController.java b/src/main/java/com/server/hispath/notice/presentation/NoticeController.java new file mode 100644 index 0000000..deeef36 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/presentation/NoticeController.java @@ -0,0 +1,86 @@ +package com.server.hispath.notice.presentation; + +import com.server.hispath.auth.domain.LoginManager; +import com.server.hispath.auth.domain.ManagerLogin; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.notice.application.dto.DashboardNoticeDto; +import com.server.hispath.notice.application.dto.NoticeContentDto; +import com.server.hispath.notice.application.dto.NoticeDto; +import com.server.hispath.notice.application.NoticeService; + +import com.server.hispath.notice.domain.Notice; +import com.server.hispath.notice.presentation.request.NoticeRequest; +import com.server.hispath.notice.presentation.response.NoticeDashboardResponse; +import com.server.hispath.notice.presentation.response.NoticeResponse; +import io.swagger.annotations.ApiOperation; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import lombok.RequiredArgsConstructor; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class NoticeController { + + private final NoticeService noticeService; + + + @PostMapping("/notice/add") + @ApiOperation(value= ApiDoc.NOTICE_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@ManagerLogin LoginManager loginManager, @RequestBody NoticeRequest request){ + Long id = noticeService.create(loginManager.getId(), NoticeContentDto.from(request)); + return ResponseEntity.ok(id); + } + + @GetMapping("/notice") + @RequiredLogin + @ApiOperation(value = ApiDoc.NOTICE_READ_ALL) + public ResponseEntity> findAll() { + List responses = noticeService.findAll().stream().sorted(Comparator.comparing(NoticeDto::getRegDate).reversed()).map(NoticeResponse::from).collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/notice/imp") + @ApiOperation(value = ApiDoc.NOTICE_READ_IMP) + @RequiredLogin + public ResponseEntity> findImp() { + List responses = noticeService.findImp().stream().sorted(Comparator.comparing(DashboardNoticeDto::getPubDate).reversed()).map(NoticeDashboardResponse::of).collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/notice/{id}") + @ApiOperation(value = ApiDoc.NOTICE_READ) + @RequiredLogin + public ResponseEntity find(@PathVariable Long id){ +// noticeService.increaseViewCnt(id); + NoticeResponse response = NoticeResponse.from(noticeService.find(id)); + return ResponseEntity.ok(response); + } + + + @PatchMapping("/notice/{id}") + @ApiOperation(value = ApiDoc.NOTICE_UPDATE) + @RequiredManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody NoticeRequest request){ + NoticeDto dto = noticeService.update(id, request.getManagerId(), NoticeContentDto.from(request)); + NoticeResponse response = NoticeResponse.from(dto); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/notice/{id}") + @ApiOperation(value = ApiDoc.NOTICE_DELETE) + @RequiredManagerLogin + public ResponseEntity delete(@PathVariable Long id){ + noticeService.delete(id); + return ResponseEntity.ok(id); + } + +} diff --git a/src/main/java/com/server/hispath/notice/presentation/request/NoticeRequest.java b/src/main/java/com/server/hispath/notice/presentation/request/NoticeRequest.java new file mode 100644 index 0000000..3fbb87f --- /dev/null +++ b/src/main/java/com/server/hispath/notice/presentation/request/NoticeRequest.java @@ -0,0 +1,28 @@ +package com.server.hispath.notice.presentation.request; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Column; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Setter +@Getter +@NoArgsConstructor +public class NoticeRequest{ + + private Long managerId; + private String title; + private String content; + private int viewCnt; + private boolean importance; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate pubDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate expDate; + + +} diff --git a/src/main/java/com/server/hispath/notice/presentation/response/NoticeDashboardResponse.java b/src/main/java/com/server/hispath/notice/presentation/response/NoticeDashboardResponse.java new file mode 100644 index 0000000..ea3ad12 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/presentation/response/NoticeDashboardResponse.java @@ -0,0 +1,25 @@ +package com.server.hispath.notice.presentation.response; + +import java.time.LocalDate; + +import com.server.hispath.notice.application.dto.DashboardNoticeDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NoticeDashboardResponse { + private Long noticeId; + private String title; + private String content; + private LocalDate pubDate; + private LocalDate expDate; + private LocalDate regDate; + + static public NoticeDashboardResponse of(DashboardNoticeDto dto) { + return new NoticeDashboardResponse(dto.getId(), dto.getTitle(), dto.getContent(), dto.getPubDate(), dto.getExpDate(), dto.getRegDate()); + } +} diff --git a/src/main/java/com/server/hispath/notice/presentation/response/NoticeResponse.java b/src/main/java/com/server/hispath/notice/presentation/response/NoticeResponse.java new file mode 100644 index 0000000..f50bba4 --- /dev/null +++ b/src/main/java/com/server/hispath/notice/presentation/response/NoticeResponse.java @@ -0,0 +1,41 @@ +package com.server.hispath.notice.presentation.response; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.server.hispath.notice.application.dto.NoticeDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import java.time.LocalDate; + + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NoticeResponse { + + + private Long id; + private Long managerId; + private String managerName; + private String title; + private String content; + private int viewCnt; + private boolean importance; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate regDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate pubDate; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul") + private LocalDate expDate; + + public static NoticeResponse from(NoticeDto dto) { + return new NoticeResponse(dto.getId(), dto.getManager().getId(), dto.getManager().getName(), + dto.getTitle(), dto.getContent(), dto.getViewCnt(), dto.isImportance(),dto.getRegDate().toLocalDate() ,dto.getPubDate(), dto.getExpDate()); + } +} diff --git a/src/main/java/com/server/hispath/resume/application/ResumeService.java b/src/main/java/com/server/hispath/resume/application/ResumeService.java new file mode 100644 index 0000000..02fdac5 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/application/ResumeService.java @@ -0,0 +1,77 @@ +package com.server.hispath.resume.application; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.exception.resume.ResumeNotFoundException; +import com.server.hispath.resume.application.dto.ResumeDto; +import com.server.hispath.resume.domain.Resume; +import com.server.hispath.resume.domain.repository.ResumeRepository; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.domain.Student; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ResumeService { + + private final ResumeRepository resumeRepository; + private final StudentService studentService; + + @Transactional + public Long create(Long studentId, ResumeDto resumeDto) { + Student student = studentService.findById(studentId); + Resume resume = Resume.builder() + .student(student) + .title(resumeDto.getTitle()) + .content(resumeDto.getContent()) + .build(); + + Resume savedResume = resumeRepository.save(resume); + student.addResume(savedResume); + return savedResume.getId(); + } + + @Transactional + public ResumeDto update(ResumeDto resumeDto) { + Resume resume = this.findById(resumeDto.getId()); + resume.updateContent(resumeDto); + return ResumeDto.of(resume); + } + + public Resume findById(Long id) { + return resumeRepository.findById(id).orElseThrow(ResumeNotFoundException::new); + } + + @Transactional + public void delete(Long id) { + resumeRepository.deleteById(id); + } + + @Transactional(readOnly = true) + public ResumeDto find(Long id) { + return ResumeDto.of(this.findById(id)); + } + + @Transactional(readOnly = true) + public List findAllStudentResumes(Long studentId) { + Student student = studentService.findById(studentId); + return resumeRepository.findByStudent(student) + .stream() + .map(ResumeDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List findRecentResumes(Long studentId) { + Student student = studentService.findById(studentId); + return resumeRepository.findTop6ByStudentOrderByUpdatedAtDesc(student) + .stream() + .map(ResumeDto::of) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/resume/application/dto/ResumeDto.java b/src/main/java/com/server/hispath/resume/application/dto/ResumeDto.java new file mode 100644 index 0000000..990ebf7 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/application/dto/ResumeDto.java @@ -0,0 +1,37 @@ +package com.server.hispath.resume.application.dto; + +import java.time.LocalDateTime; + +import com.server.hispath.resume.domain.Resume; +import com.server.hispath.resume.presentation.request.ResumeCURequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ResumeDto { + private Long id; + private String title; + private String content; + private LocalDateTime createdAt; + private LocalDateTime updateAt; + + public ResumeDto(Long id, ResumeCURequest request) { + this.id = id; + this.title = request.getTitle(); + this.content = request.getContent(); + } + + public ResumeDto(ResumeCURequest request) { + this.title = request.getTitle(); + this.content = request.getContent(); + } + + public static ResumeDto of(Resume resume) { + return new ResumeDto(resume.getId(), resume.getTitle(), resume.getContent(), + resume.getCreatedAt(), resume.getUpdatedAt()); + } +} diff --git a/src/main/java/com/server/hispath/resume/domain/Resume.java b/src/main/java/com/server/hispath/resume/domain/Resume.java new file mode 100644 index 0000000..1b7a059 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/domain/Resume.java @@ -0,0 +1,44 @@ +package com.server.hispath.resume.domain; + +import javax.persistence.*; + +import com.server.hispath.common.BaseEntity; +import com.server.hispath.resume.application.dto.ResumeDto; +import com.server.hispath.student.domain.Student; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE resume SET deleted = true Where id = ?") +public class Resume extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Student student; + + private String title; + + @Column(length = 5555) + private String content; + + // ToDo 여러 템플릿을 위한 필드 + // private Template template; + + public void updateContent(ResumeDto resumeDto){ + this.title = resumeDto.getTitle(); + this.content = resumeDto.getContent(); + } +} diff --git a/src/main/java/com/server/hispath/resume/domain/repository/ResumeRepository.java b/src/main/java/com/server/hispath/resume/domain/repository/ResumeRepository.java new file mode 100644 index 0000000..58a2dad --- /dev/null +++ b/src/main/java/com/server/hispath/resume/domain/repository/ResumeRepository.java @@ -0,0 +1,14 @@ +package com.server.hispath.resume.domain.repository; + +import java.util.List; + +import com.server.hispath.resume.domain.Resume; +import com.server.hispath.student.domain.Student; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ResumeRepository extends JpaRepository { + List findByStudent(Student student); + + List findTop6ByStudentOrderByUpdatedAtDesc(Student student); +} diff --git a/src/main/java/com/server/hispath/resume/presentation/ResumeController.java b/src/main/java/com/server/hispath/resume/presentation/ResumeController.java new file mode 100644 index 0000000..d6bcdea --- /dev/null +++ b/src/main/java/com/server/hispath/resume/presentation/ResumeController.java @@ -0,0 +1,90 @@ +package com.server.hispath.resume.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.dto.ActivityParticipantDto; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.resume.application.ResumeService; +import com.server.hispath.resume.application.dto.ResumeDto; +import com.server.hispath.resume.presentation.request.ResumeCURequest; +import com.server.hispath.resume.presentation.response.ResumeResponse; +import com.server.hispath.resume.presentation.response.ResumeStudentInfo; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.application.dto.StudentDto; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ResumeController { + private final ResumeService resumeService; + private final StudentService studentService; + private final ActivityService activityService; + + @PostMapping("/resume") + @ApiOperation(value = ApiDoc.RESUME_CREATE) + @RequiredLogin + public ResponseEntity create( + @StudentLogin LoginStudent loginStudent, + @RequestBody ResumeCURequest request) { + Long response = resumeService.create(loginStudent.getId(), new ResumeDto(request)); + return ResponseEntity.ok(response); + } + + @PutMapping("/resume/{id}") + @ApiOperation(value = ApiDoc.RESUME_UPDATE) + @RequiredLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody ResumeCURequest request) { + ResumeResponse response = ResumeResponse.of(resumeService.update(new ResumeDto(id, request))); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/resume/{id}") + @ApiOperation(value = ApiDoc.RESUME_DELETE) + @RequiredLogin + public ResponseEntity delete(@PathVariable Long id) { + resumeService.delete(id); + return ResponseEntity.ok(null); + } + + @GetMapping("/resume") + @ApiOperation(value = ApiDoc.RESUME_READ) + @RequiredLogin + public ResponseEntity find(@RequestParam Long resumeId) { + return ResponseEntity.ok(ResumeResponse.of(resumeService.find(resumeId))); + } + + @GetMapping("/resumes") + @ApiOperation(value = ApiDoc.RESUME_READ_ALL) + @RequiredLogin + public ResponseEntity> findAll(@StudentLogin LoginStudent loginStudent) { + + List responses = resumeService.findAllStudentResumes(loginStudent.getId()) + .stream() + .map(ResumeResponse::of) + .collect(Collectors.toList()); + + return ResponseEntity.ok(responses); + } + + @GetMapping("/resume/info") + @ApiOperation(value = ApiDoc.RESUME_INFO) + @RequiredLogin + public ResponseEntity findStudentActivityInfo(@StudentLogin LoginStudent loginStudent) { + + StudentDto studentDto = studentService.find(loginStudent.getId()); + List activities = activityService.findAllParticipantActivites(studentDto.getId(), "ALL", "ALL"); + return ResponseEntity.ok(new ResumeStudentInfo(studentDto, activities)); + } +} diff --git a/src/main/java/com/server/hispath/resume/presentation/request/ResumeCURequest.java b/src/main/java/com/server/hispath/resume/presentation/request/ResumeCURequest.java new file mode 100644 index 0000000..5d93613 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/presentation/request/ResumeCURequest.java @@ -0,0 +1,13 @@ +package com.server.hispath.resume.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ResumeCURequest { + private String title; + private String content; +} diff --git a/src/main/java/com/server/hispath/resume/presentation/response/ResumeResponse.java b/src/main/java/com/server/hispath/resume/presentation/response/ResumeResponse.java new file mode 100644 index 0000000..be27ca8 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/presentation/response/ResumeResponse.java @@ -0,0 +1,26 @@ +package com.server.hispath.resume.presentation.response; + + +import java.time.LocalDateTime; + +import com.server.hispath.resume.application.dto.ResumeDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ResumeResponse { + private Long resumeId; + private String title; + private String content; + private LocalDateTime createdAt; + private LocalDateTime updateAt; + + public static ResumeResponse of(ResumeDto resumeDto) { + return new ResumeResponse(resumeDto.getId(), resumeDto.getTitle(), resumeDto.getContent(), + resumeDto.getCreatedAt(), resumeDto.getUpdateAt()); + } +} diff --git a/src/main/java/com/server/hispath/resume/presentation/response/ResumeStudentInfo.java b/src/main/java/com/server/hispath/resume/presentation/response/ResumeStudentInfo.java new file mode 100644 index 0000000..0275592 --- /dev/null +++ b/src/main/java/com/server/hispath/resume/presentation/response/ResumeStudentInfo.java @@ -0,0 +1,44 @@ +package com.server.hispath.resume.presentation.response; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.dto.ActivityParticipantDto; +import com.server.hispath.activity.presentation.response.ActivitySimpleResponse; +import com.server.hispath.student.application.dto.StudentDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ResumeStudentInfo { + private String studentName; + private String phone; + private String profile; + private String email; + private String departmentName; + private String major1; + private String major2; + private String blog; + private String githubId; + private List activities = new ArrayList<>(); + + public ResumeStudentInfo(StudentDto studentDto, List activityDtos){ + this.studentName = studentDto.getName(); + this.phone = studentDto.getPhone(); + this.profile = studentDto.getProfile(); + this.email = studentDto.getEmail(); + this.departmentName = studentDto.getDepartmentDto().getName(); + this.major1 = studentDto.getMajor1().getName(); + this.major2 = studentDto.getMajor2().getName(); + this.blog = studentDto.getBlog(); + this.githubId = studentDto.getGithubId(); + this.activities = activityDtos.stream() + .map(ActivitySimpleResponse::of) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/application/ScholarshipService.java b/src/main/java/com/server/hispath/scholarship/application/ScholarshipService.java new file mode 100644 index 0000000..1aa0e12 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/application/ScholarshipService.java @@ -0,0 +1,236 @@ +package com.server.hispath.scholarship.application; + +import java.util.*; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.dto.ChartDepartmentDataDto; +import com.server.hispath.activity.application.dto.ChartGradeDataDto; +import com.server.hispath.activity.application.dto.ChartSearchRequestDto; +import com.server.hispath.activity.application.dto.ChartTimelineDto; +import com.server.hispath.activity.application.dto.chart.ChartRankDto; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.activity.domain.repository.ActivityRepository; +import com.server.hispath.exception.scholarship.ScholarshipDuplicateException; +import com.server.hispath.exception.scholarship.ScholarshipNotFoundException; +import com.server.hispath.exception.scholarship.ScholarshipNotMatchException; +import com.server.hispath.exception.student.StudentNotFoundException; +import com.server.hispath.scholarship.application.dto.ScholarshipApprovalDto; +import com.server.hispath.scholarship.application.dto.ScholarshipContentDto; +import com.server.hispath.scholarship.application.dto.ScholarshipDto; +import com.server.hispath.scholarship.application.dto.SearchRequestDto; +import com.server.hispath.scholarship.domain.Scholarship; +import com.server.hispath.scholarship.domain.repository.ScholarshipRepository; +import com.server.hispath.scholarship.domain.repository.ScholarshipRepositoryCustom; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class ScholarshipService { + private final ScholarshipRepository scholarshipRepository; + private final ScholarshipRepositoryCustom scholarshipRepositoryCustom; + private final StudentService studentService; + private final ActivityRepository activityRepository; + private final StudentRepository studentRepository; + + @Transactional + public Long create(Long studentId, String semester) { + Student student = studentService.findById(studentId); + + Optional existScholarship = scholarshipRepository.findFirstByStudentAndSemester(student, semester); + existScholarship.ifPresent(scholarshipRepository::delete); + + int totalWeight = getTotalWeight(student, semester); + + Scholarship scholarship = Scholarship.builder() + .student(student) + .semester(semester) + .studentSemester(student.getSemester()) + .totalMileage(totalWeight) + .sMajor1(student.getMajor1()) + .sMajor2(student.getMajor2()) + .sDepartment(student.getDepartment()) + .build(); + + Scholarship savedScholarship = scholarshipRepository.save(scholarship); + return savedScholarship.getId(); + } + + private int getTotalWeight(Student student, String semester) { + return activityRepository.findActivitiesByStudentAndSemester(student, semester) + .stream() + .map(Activity::getWeight) + .reduce(0, Integer::sum); + } + + @Transactional(readOnly = true) + public List findAll() { + List scholarships = scholarshipRepository.findAll(); + return scholarships.stream() + .map(ScholarshipContentDto::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List findAllScholarshipStudent(boolean approved, String semester) { + List scholarships = scholarshipRepository.findAllByApprovedAndSemester(approved, semester); + return scholarships.stream() + .map(ScholarshipDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public ScholarshipDto findScholarshipStudent(Long studentId, String semester) { + Scholarship scholarship = scholarshipRepository.findStudentIdAndSemester(studentId, semester) + .orElseThrow(ScholarshipNotFoundException::new); + return ScholarshipDto.of(scholarship); + } + + @Transactional + public void approveAll(List scholarshipApprovalDtos, String semester) { + validateScholarshipDatas(scholarshipApprovalDtos, semester); + checkDuplicate(scholarshipApprovalDtos); + + scholarshipApprovalDtos.forEach(dto -> { + Student student = studentRepository.findByStudentNum(dto.getStudentNum()) + .orElseThrow(StudentNotFoundException::new); + Scholarship scholarship = scholarshipRepository.findFirstByStudentAndSemester(student, semester) + .orElseThrow(ScholarshipNotFoundException::new); + scholarship.approve(dto.getResult()); + }); + + + } + + private void checkDuplicate(List scholarshipApprovalDtos) { + Set set = scholarshipApprovalDtos.stream() + .map(ScholarshipApprovalDto::StudentInfo) + .collect(Collectors.toSet()); + + if (set.size() < scholarshipApprovalDtos.size()) { + throw new ScholarshipDuplicateException(); + } + } + + private boolean validateError(ScholarshipApprovalDto dto, String semester) { + Optional optionalStudent = studentRepository.findByStudentNum(dto.getStudentNum()); + if (optionalStudent.isEmpty()) + return true; + Student student = optionalStudent.get(); + if (!student.isNameMatch(dto.getName())) + return true; + Optional optionalScholarship = scholarshipRepository.findFirstByStudentAndSemester(student, semester); + if (optionalScholarship.isEmpty()) + return true; + Scholarship scholarship = optionalScholarship.get(); + if (!scholarship.isStudentSemesterMatch(dto.getStudentSemester())) + return true; + return scholarship.getTotalMileage() != dto.getWeight(); + } + + private void validateScholarshipDatas(List scholarshipApprovalDtos, String semester) { + List errors = scholarshipApprovalDtos.stream() + .filter(dto -> validateError(dto, semester)) + .collect(Collectors.toList()); + if (errors.size() != 0) { + String errorMsg = errors.stream() + .map(ScholarshipApprovalDto::toString) + .collect(Collectors.joining("\n")); + throw new ScholarshipNotMatchException(errorMsg); + } + } + + @Transactional(readOnly = true) + public List searchScholarshipStudent(SearchRequestDto dto) { + return scholarshipRepositoryCustom.searchScholarshipStudent(dto) + .stream() + .map(ScholarshipDto::of) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public ChartRankDto getRankChartData(Long studentId, ChartSearchRequestDto dto) { + + Student student = studentService.findById(studentId); + int myWeight = scholarshipRepository.findFirstByStudentAndSemester(student, dto.getSemester()) + .orElseGet(() -> Scholarship.builder().totalMileage(0).build()) + .getTotalMileage(); + Double avgWeight = scholarshipRepositoryCustom.getTotalMileageAvg(dto); + int maxWeight = activityRepository.sumActivityWeight(dto.getSemester()); + return new ChartRankDto(myWeight, avgWeight, maxWeight); + } + + @Transactional(readOnly = true) + public List getChartTimelines(Long studentId) { + return studentRepository.findStudentWithScholarships(studentId) + .orElseThrow(StudentNotFoundException::new) + .getScholarships() + .stream() + .filter(Scholarship::isApproved) + .map(ChartTimelineDto::of) + .sorted(Comparator.comparing(ChartTimelineDto::getSemester)) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List getChartWeightDistribution(String semester) { + List scholarships = scholarshipRepository.findAllBySemesterAndApprovedTrue(semester); + Long[] chartWeightDistribute = new Long[6]; + Arrays.fill(chartWeightDistribute, 0L); + scholarships.forEach(scholarship -> { + if (scholarship.getTotalMileage() < 20) + chartWeightDistribute[0]++; + else if (scholarship.getTotalMileage() < 40) + chartWeightDistribute[1]++; + else if (scholarship.getTotalMileage() < 60) + chartWeightDistribute[2]++; + else if (scholarship.getTotalMileage() < 80) + chartWeightDistribute[3]++; + else if (scholarship.getTotalMileage() < 100) + chartWeightDistribute[4]++; + else + chartWeightDistribute[5]++; + }); + + return Arrays.asList(chartWeightDistribute); + } + + @Transactional(readOnly = true) + public List getChartGradeDistribution(String semester) { + List chartGradeDataDtos = scholarshipRepositoryCustom.getCountByGradeAndSemester(semester); + + chartGradeDataDtos.sort(Comparator.comparing(ChartGradeDataDto::getGrade)); + ChartGradeDataDto[] chartGradeDatas = new ChartGradeDataDto[4]; + chartGradeDatas[0] = new ChartGradeDataDto(1, 0L); + chartGradeDatas[1] = new ChartGradeDataDto(2, 0L); + chartGradeDatas[2] = new ChartGradeDataDto(3, 0L); + chartGradeDatas[3] = new ChartGradeDataDto(4, 0L); + chartGradeDataDtos.forEach(chartGradeDataDto -> { + int grade = chartGradeDataDto.getGrade() / 2 + chartGradeDataDto.getGrade() % 2; + if (grade >= 4) + grade = 4; + chartGradeDatas[grade - 1].addCnt(chartGradeDataDto.getCnt()); + }); + + return List.of(chartGradeDatas); + } + + @Transactional(readOnly = true) + public List getChartDepartmentDistribution(String semester) { + return scholarshipRepositoryCustom.getCountByDepartmentAndSemester(semester); + } + + @Transactional(readOnly = true) + public List getWaitingScholarships(String semester) { + return scholarshipRepository.findWaitingScholarships(semester) + .stream() + .map(ScholarshipApprovalDto::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipApprovalDto.java b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipApprovalDto.java new file mode 100644 index 0000000..e63e752 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipApprovalDto.java @@ -0,0 +1,39 @@ +package com.server.hispath.scholarship.application.dto; + +import java.util.Arrays; +import java.util.List; + +import com.server.hispath.scholarship.domain.Scholarship; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipApprovalDto { + private String name; + private String studentNum; + private int studentSemester; + private int weight; + private String result; + + @Override + public String toString() { + return "학생명: " + name + " 학번: " + studentNum + " 학생 학기수: " + studentSemester + " 전체 가중치: " + weight + " 결과: " + result; + } + + public static ScholarshipApprovalDto from(Scholarship scholarship) { + return new ScholarshipApprovalDto(scholarship.getStudent().getName(), scholarship.getStudent().getStudentNum(), + scholarship.getStudentSemester(), scholarship.getTotalMileage(), ""); + } + + public List getStringList() { + return Arrays.asList(this.studentNum, this.name, String.valueOf(this.studentSemester), String.valueOf(this.weight), this.result); + } + + public String StudentInfo() { + return studentNum + " " + name; + } +} diff --git a/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipContentDto.java b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipContentDto.java new file mode 100644 index 0000000..4fa4846 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipContentDto.java @@ -0,0 +1,24 @@ +package com.server.hispath.scholarship.application.dto; + +import com.server.hispath.scholarship.domain.Scholarship; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipContentDto { + private Long id; + private String semester; + private int studentSemester; + private int totalMileage; + private boolean approved; + + public static ScholarshipContentDto from(Scholarship scholarship) { + return new ScholarshipContentDto(scholarship.getId(), scholarship.getSemester(), + scholarship.getStudentSemester(), scholarship.getTotalMileage(), scholarship.isApproved()); + } + +} diff --git a/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipDto.java b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipDto.java new file mode 100644 index 0000000..f182b21 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/application/dto/ScholarshipDto.java @@ -0,0 +1,36 @@ +package com.server.hispath.scholarship.application.dto; + +import com.server.hispath.scholarship.domain.Scholarship; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipDto { + private Long studentId; + private String name; + private String studentNum; + private String semester; + private int studentSemester; + private String departmentName; + private String major1Name; + private String major2Name; + private String email; + private String phone; + private String result; + private int totalWeight; + + public static ScholarshipDto of(Scholarship scholarship) { + return new ScholarshipDto(scholarship.getStudent().getId(), scholarship.getStudent().getName(), scholarship.getStudent() + .getStudentNum(), + scholarship.getSemester(), scholarship.getStudentSemester(), scholarship.getSDepartment().getName(), + scholarship.getSMajor1().getName(), scholarship.getSMajor2().getName(), scholarship.getStudent() + .getEmail(), + scholarship.getStudent().getPhone(), scholarship.getResult(), scholarship.getTotalMileage()); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/application/dto/SearchRequestDto.java b/src/main/java/com/server/hispath/scholarship/application/dto/SearchRequestDto.java new file mode 100644 index 0000000..741295d --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/application/dto/SearchRequestDto.java @@ -0,0 +1,17 @@ +package com.server.hispath.scholarship.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SearchRequestDto { + private String semester; + private String studentSemester; + private String department; + private String major1; + private String major2; +} diff --git a/src/main/java/com/server/hispath/scholarship/domain/Scholarship.java b/src/main/java/com/server/hispath/scholarship/domain/Scholarship.java new file mode 100644 index 0000000..17614b8 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/domain/Scholarship.java @@ -0,0 +1,62 @@ +package com.server.hispath.scholarship.domain; + +import javax.persistence.*; + +import com.server.hispath.common.BaseEntity; +import com.server.hispath.department.domain.Department; +import com.server.hispath.major.domain.Major; +import com.server.hispath.student.domain.Student; +import com.sun.istack.NotNull; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE scholarship SET deleted = true Where id = ?") +public class Scholarship extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Student student; + + @NotNull + private String semester; + + int studentSemester; + + private int totalMileage; + + @ManyToOne(fetch = FetchType.LAZY) + private Major sMajor1; + + @ManyToOne(fetch = FetchType.LAZY) + private Major sMajor2; + + @ManyToOne(fetch = FetchType.LAZY) + private Department sDepartment; + + private String result; + + private boolean approved = false; + + public void approve(String result) { + approved = true; + this.result = result; + } + + public boolean isStudentSemesterMatch(int studentSemester) { + return this.studentSemester == studentSemester; + } +} diff --git a/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepository.java b/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepository.java new file mode 100644 index 0000000..fb486b9 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepository.java @@ -0,0 +1,41 @@ +package com.server.hispath.scholarship.domain.repository; + +import java.util.List; +import java.util.Optional; + +import com.server.hispath.scholarship.domain.Scholarship; +import com.server.hispath.student.domain.Student; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface ScholarshipRepository extends JpaRepository { + Optional findFirstByStudentAndSemester(Student student, String semester); + + @Query("select s from Scholarship s " + + "join fetch s.student " + + "join fetch s.sDepartment " + + "join fetch s.sMajor1 " + + "join fetch s.sMajor2 " + + "where s.approved = :approved " + + "and s.semester = :semester ") + List findAllByApprovedAndSemester(boolean approved, String semester); + + @Query("select s from Scholarship s " + + "join fetch s.student " + + "join fetch s.sDepartment " + + "join fetch s.sMajor1 " + + "join fetch s.sMajor2 " + + "where s.student.id = :id " + + "and s.semester = :semester ") + Optional findStudentIdAndSemester(Long id, String semester); + + List findAllBySemesterAndApprovedTrue(String semester); + + @Query("select s from Scholarship s " + + "join fetch s.student " + + "where s.approved = false " + + "and s.semester = :semester") + List findWaitingScholarships(String semester); +} + diff --git a/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepositoryCustom.java b/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepositoryCustom.java new file mode 100644 index 0000000..113154b --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/domain/repository/ScholarshipRepositoryCustom.java @@ -0,0 +1,103 @@ +package com.server.hispath.scholarship.domain.repository; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.server.hispath.activity.application.dto.*; +import com.server.hispath.scholarship.application.dto.SearchRequestDto; +import com.server.hispath.scholarship.domain.Scholarship; + +import org.springframework.stereotype.Repository; + +import lombok.RequiredArgsConstructor; + +import static com.server.hispath.activity.domain.QActivity.activity; +import static com.server.hispath.scholarship.domain.QScholarship.scholarship; +import static com.server.hispath.student.domain.QParticipant.participant; + +@Repository +@RequiredArgsConstructor +public class ScholarshipRepositoryCustom { + private final JPAQueryFactory queryFactory; + + public List searchScholarshipStudent(SearchRequestDto dto) { + return queryFactory.select(scholarship) + .distinct() + .from(scholarship) + .leftJoin(scholarship.student).fetchJoin() + .leftJoin(scholarship.sDepartment).fetchJoin() + .leftJoin(scholarship.sMajor1).fetchJoin() + .leftJoin(scholarship.sMajor2).fetchJoin() + .where(scholarshipStudentCondition(dto)) + .fetch(); + + } + + public Double getTotalMileageAvg(ChartSearchRequestDto dto) { + return queryFactory.select(scholarship.totalMileage.avg()) + .from(scholarship) + .where(totalMileageAvgCondition(dto)) + .fetchOne(); + } + + public List getCountByGradeAndSemester(String semester) { + return queryFactory.select(new QChartGradeDataDto(scholarship.studentSemester, scholarship.count())) + .from(scholarship) + .where(scholarship.semester.eq(semester).and(scholarship.approved.eq(true))) + .groupBy(scholarship.studentSemester) + .fetch(); + } + + public List getCountByDepartmentAndSemester(String semester) { + return queryFactory.select(new QChartDepartmentDataDto(scholarship.sDepartment.name, scholarship.count())) + .from(scholarship) + .where(scholarship.semester.eq(semester).and(scholarship.approved.eq(true))) + .groupBy(scholarship.sDepartment) + .fetch(); + } + + public BooleanBuilder totalMileageAvgCondition(ChartSearchRequestDto dto) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + + if (!Objects.isNull(dto.getSemester())) { + booleanBuilder.and(scholarship.semester.eq(dto.getSemester())); + } + if (!Objects.isNull(dto.getDepartment())) { + booleanBuilder.and(scholarship.sDepartment.name.eq(dto.getDepartment())); + } + + if (!Objects.isNull(dto.getGrade())) { + int grade = (dto.getGrade() + 1) / 2 * 2; + booleanBuilder.and(scholarship.studentSemester.eq(grade - 1).or(scholarship.studentSemester.eq(grade))); + } + + return booleanBuilder; + } + + public BooleanBuilder scholarshipStudentCondition(SearchRequestDto dto) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + + if (!Objects.isNull(dto.getSemester())) { + booleanBuilder.and(scholarship.semester.in(dto.getSemester().split(","))); + } + if (!Objects.isNull(dto.getStudentSemester())) { + booleanBuilder.and(scholarship.studentSemester.in(Arrays.stream(dto.getStudentSemester().split(",")) + .map(Integer::parseInt) + .collect(Collectors.toList()))); + } + if (!Objects.isNull(dto.getDepartment())) { + booleanBuilder.and(scholarship.sDepartment.name.in(dto.getDepartment().split(","))); + } + if (!Objects.isNull(dto.getMajor1())) { + booleanBuilder.and(scholarship.sMajor1.name.in(dto.getMajor1().split(","))); + } + if (!Objects.isNull(dto.getMajor2())) { + booleanBuilder.and(scholarship.sMajor2.name.in(dto.getMajor2().split(","))); + } + return booleanBuilder; + } +} diff --git a/src/main/java/com/server/hispath/scholarship/presentation/ScholarshipController.java b/src/main/java/com/server/hispath/scholarship/presentation/ScholarshipController.java new file mode 100644 index 0000000..534da71 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/presentation/ScholarshipController.java @@ -0,0 +1,115 @@ +package com.server.hispath.scholarship.presentation; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.scholarship.application.ScholarshipService; +import com.server.hispath.scholarship.application.dto.ScholarshipDto; +import com.server.hispath.scholarship.application.dto.SearchRequestDto; +import com.server.hispath.scholarship.presentation.request.ScholarshipCURequest; +import com.server.hispath.scholarship.presentation.response.ScholarshipActivityResponse; +import com.server.hispath.scholarship.presentation.response.ScholarshipDetailResponse; +import com.server.hispath.scholarship.presentation.response.ScholarshipResponse; +import com.server.hispath.util.ExcelManager; + +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; +import org.apache.poi.ss.usermodel.Workbook; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ScholarshipController { + + private final ScholarshipService scholarshipService; + private final ActivityService activityService; + + @PostMapping("/scholarship") + @ApiOperation(value = ApiDoc.SCHOLARSHIP_CREATE) + @RequiredLogin + public ResponseEntity create(@StudentLogin LoginStudent loginStudent, + @RequestBody ScholarshipCURequest request) { + + Long response = scholarshipService.create(loginStudent.getId(), request.getSemester()); + + return ResponseEntity.ok(response); + } + + @GetMapping("/scholarships") + @ApiOperation(value = ApiDoc.SCHOLARSHIP_READ_ALL) + @RequiredManagerLogin + public ResponseEntity> getScholarshipStudents(@RequestParam boolean approved, @RequestParam String semester) { + List responses = scholarshipService.findAllScholarshipStudent(approved, semester) + .stream() + .map(ScholarshipResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/scholarship/activities") + @ApiOperation(value = ApiDoc.SCHOLARSHIP_ACTIVITIES) + @RequiredManagerLogin + public ResponseEntity getScholarshipDetailInfo(@RequestParam Long studentId, @RequestParam String semester) { + List scholarshipActivityResponses = activityService.findAllByStudentAndSemster(studentId, semester) + .stream() + .map(ScholarshipActivityResponse::of) + .collect(Collectors.toList()); + ScholarshipDto scholarshipDto = scholarshipService.findScholarshipStudent(studentId, semester); + ScholarshipDetailResponse response = ScholarshipDetailResponse.from(scholarshipDto, scholarshipActivityResponses); + return ResponseEntity.ok(response); + } + + @PutMapping("/scholarship/approval") + @ApiOperation(value = ApiDoc.APPROVE_SCHOLARSHIPS) + @RequiredManagerLogin + public ResponseEntity approveAll(@RequestPart(value = "file") MultipartFile file, + @RequestPart(value = "semester") String semester) throws Exception { + scholarshipService.approveAll(ExcelManager.getScholarshipApproveDatas(ExcelManager.extract(file)), semester); + return ResponseEntity.ok(null); + } + + @GetMapping("/scholarship/students") + @ApiOperation(value = ApiDoc.SCHOLARSHIP_SEARCH_STUDENT) + @RequiredManagerLogin + public ResponseEntity> searchScholarshipStudents( + @RequestParam(required = false) String semester, + @RequestParam(required = false) String studentSemester, + @RequestParam(required = false) String department, + @RequestParam(required = false) String major1, + @RequestParam(required = false) String major2 + ) { + SearchRequestDto searchRequestDto = new SearchRequestDto(semester, studentSemester, department, major1, major2); + List responses = scholarshipService.searchScholarshipStudent(searchRequestDto) + .stream() + .map(ScholarshipResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping(value = "/scholarship/excel", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + public ResponseEntity exportScholarshipsByExcel(@RequestParam String semester) throws IOException{ + Workbook workbook = ExcelManager.toCsv(scholarshipService.getWaitingScholarships(semester)); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + workbook.write(os); + os.close(); + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachement;filename=\"scholarships_waiting.xlsx" + "\"") + .header(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + .body(new ByteArrayResource(os.toByteArray())); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/presentation/request/ScholarshipCURequest.java b/src/main/java/com/server/hispath/scholarship/presentation/request/ScholarshipCURequest.java new file mode 100644 index 0000000..bf90d32 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/presentation/request/ScholarshipCURequest.java @@ -0,0 +1,12 @@ +package com.server.hispath.scholarship.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class ScholarshipCURequest { + private String semester; +} diff --git a/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipActivityResponse.java b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipActivityResponse.java new file mode 100644 index 0000000..9be8357 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipActivityResponse.java @@ -0,0 +1,27 @@ +package com.server.hispath.scholarship.presentation.response; + +import com.server.hispath.activity.application.dto.ActivityDto; +import com.server.hispath.scholarship.application.dto.ScholarshipDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipActivityResponse { + private Long id; + private String categoryName; + private String name; + private String remark; + private String semester; + private int weight; + + public static ScholarshipActivityResponse of(ActivityDto dto){ + return new ScholarshipActivityResponse(dto.getId(), dto.getCategoryDto().getName(), dto.getName(), + dto.getRemark(), dto.getSemester(), dto.getWeight()); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipDetailResponse.java b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipDetailResponse.java new file mode 100644 index 0000000..41b6fcb --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipDetailResponse.java @@ -0,0 +1,37 @@ +package com.server.hispath.scholarship.presentation.response; + +import java.util.ArrayList; +import java.util.List; + +import com.server.hispath.scholarship.application.dto.ScholarshipDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipDetailResponse { + private String name; + private String studentNum; + private String semester; + private int studentSemester; + private String departmentName; + private String major1Name; + private String major2Name; + private String email; + private String phone; + private int totalWeight; + private String result; + private List activities = new ArrayList<>(); + private int activityCnt; + + public static ScholarshipDetailResponse from(ScholarshipDto dto, List activities) { + return new ScholarshipDetailResponse(dto.getName(), dto.getStudentNum(), dto.getSemester(), dto.getStudentSemester(), + dto.getDepartmentName(), dto.getMajor1Name(), dto.getMajor2Name(), dto.getEmail(), + dto.getPhone(), dto.getTotalWeight(), dto.getResult(), activities, activities.size()); + } +} diff --git a/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipResponse.java b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipResponse.java new file mode 100644 index 0000000..f505672 --- /dev/null +++ b/src/main/java/com/server/hispath/scholarship/presentation/response/ScholarshipResponse.java @@ -0,0 +1,33 @@ +package com.server.hispath.scholarship.presentation.response; + +import com.server.hispath.scholarship.application.dto.ScholarshipDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class ScholarshipResponse { + private Long studentId; + private String name; + private String studentNum; + private String semester; + private int studentSemester; + private String departmentName; + private String major1Name; + private String major2Name; + private String email; + private String phone; + private String result; + private int totalWeight; + + public static ScholarshipResponse of(ScholarshipDto dto) { + return new ScholarshipResponse(dto.getStudentId(), dto.getName(), dto.getStudentNum(), + dto.getSemester(), dto.getStudentSemester(), dto.getDepartmentName(), dto.getMajor1Name(), + dto.getMajor2Name(), dto.getEmail(), dto.getPhone(), dto.getResult(), dto.getTotalWeight()); + } +} diff --git a/src/main/java/com/server/hispath/student/application/StudentService.java b/src/main/java/com/server/hispath/student/application/StudentService.java new file mode 100644 index 0000000..d55f626 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/StudentService.java @@ -0,0 +1,157 @@ +package com.server.hispath.student.application; + +import com.server.hispath.activity.application.dto.SemesterDto; +import com.server.hispath.department.application.DepartmentService; +import com.server.hispath.department.domain.Department; +import com.server.hispath.exception.activity.ParticipantNotFoundException; +import com.server.hispath.exception.student.StudentNotFoundException; +import com.server.hispath.major.application.MajorService; +import com.server.hispath.major.domain.Major; +import com.server.hispath.student.application.dto.StudentCUDto; +import com.server.hispath.student.application.dto.StudentDto; + +import java.util.List; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.MActivityService; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.exception.student.StudentDataNotMatchException; +import com.server.hispath.student.application.dto.StudentRefDto; +import com.server.hispath.student.application.dto.StudentSimpleRefDto; +import com.server.hispath.student.domain.Section; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.domain.repository.StudentRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import lombok.RequiredArgsConstructor; + +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class StudentService { + + private final StudentRepository studentRepository; + private final ActivityService activityService; + private final MActivityService mActivityService; + private final MajorService majorService; + private final DepartmentService departmentService; + + + @Transactional + public Long create(StudentCUDto dto) { + Department department = departmentService.findById(dto.getDepartmentId()); + Major major1 = majorService.findById(dto.getMajor1Id()); + Major major2 = majorService.findById(dto.getMajor2Id()); + Student savedStudent = studentRepository.save(Student.from(dto, department, major1, major2)); + return savedStudent.getId(); + } + + @Transactional + public void createAll(List dtos) { + List students = dtos.stream() + .map(dto -> { + Student student = findById(Long.valueOf(dto.getId())); + Department department = departmentService.findById(dto.getDepartmentId()); + Major major1 = majorService.findById(dto.getMajor1Id()); + Major major2 = majorService.findById(dto.getMajor2Id()); + return student.from(dto, department, major1, major2); + }).collect(Collectors.toList()); + studentRepository.saveAll(students); + } + + @Transactional + public StudentDto find(Long id) { + Student student = this.findById(id); + return StudentDto.from(student); + } + + @Transactional + public List findAll() { + List students = studentRepository.findAll(); + students.stream() + .forEach(student -> { + System.out.println("student.getName() = " + student.getName()); + }); + return students.stream() + .map(StudentDto::from) + .collect(Collectors.toList()); + } + + @Transactional + public StudentDto update(Long id, Long departmentId, Long major1Id, Long major2Id, StudentCUDto dto) { + Department department = departmentService.findById(departmentId); + Student student = studentRepository.findById(id).orElseThrow(StudentNotFoundException::new); + Major major1 = majorService.findById(major1Id); + Major major2 = majorService.findById(major2Id); + student.update(department, major1, major2, dto); + return StudentDto.from(student); + } + + @Transactional + public void delete(Long id) { + studentRepository.deleteById(id); + } + + public Student findById(Long id) { + return studentRepository.findById(id).orElseThrow(StudentNotFoundException::new); + } + + @Transactional + public void registerParticipants(Long activityId, List studentRefDtos) { + Activity activity = activityService.findById(activityId); + mActivityService.deleteAllParticipant(activity); + studentRefDtos.forEach(dto -> { + Student student = studentRepository.findByStudentNum(dto.getStudentNum()) + .orElseThrow(StudentNotFoundException::new); + validateStudent(student, dto); + activity.addParticipant(student, Section.ETC); + }); + + activity.updateStudentRegister(); + } + + @Transactional + public void registerParticipants(Long activityId, List studentRefDtos, int sectionIdx) { + Activity activity = activityService.findById(activityId); + mActivityService.deleteAllParticipant(activity); + Section[] values = Section.values(); + studentRefDtos.forEach(dto -> { + Student student = studentRepository.findByStudentNum(dto.getStudentNum()) + .orElseThrow(StudentNotFoundException::new); + validateStudent(student, dto); + activity.addParticipant(student, values[sectionIdx]); + }); + + activity.updateStudentRegister(); + } + + @Transactional + public void registerParticipant(Long activityId, StudentSimpleRefDto dto) { + Activity activity = activityService.findById(activityId); + Student student = studentRepository.findByStudentNum(dto.getStudentNum()) + .orElseThrow(StudentNotFoundException::new); + validateStudent(student, dto); + activity.addParticipant(student, Section.ETC); + } + + private void validateStudent(Student student, StudentSimpleRefDto dto) { + if (!student.isNameMatch(dto.getName())) { + throw new StudentDataNotMatchException(dto.getStudentNum(), dto.getName()); + } + } + + @Transactional(readOnly = true) + public List getStudentSemesters(Long studentId) { + Student student = studentRepository.findActivitiesByStudent(studentId) + .orElseThrow(StudentNotFoundException::new); + return student.getParticipants() + .stream() + .map(participant -> participant.getActivity().getSemester()) + .distinct() + .map(SemesterDto::new) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/server/hispath/student/application/dto/DashboardDto.java b/src/main/java/com/server/hispath/student/application/dto/DashboardDto.java new file mode 100644 index 0000000..e635263 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/DashboardDto.java @@ -0,0 +1,23 @@ +package com.server.hispath.student.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class DashboardDto { + private Long id; + private String profile; + private String name; + private String studentNum; + private String major1; + private String major2; + private int semester; + private String email; + private String phone; + private String githubId; + private String blog; + private String readme; +} diff --git a/src/main/java/com/server/hispath/student/application/dto/StudentCUDto.java b/src/main/java/com/server/hispath/student/application/dto/StudentCUDto.java new file mode 100644 index 0000000..45d4f04 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/StudentCUDto.java @@ -0,0 +1,31 @@ +package com.server.hispath.student.application.dto; + +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.presentation.request.StudentCURequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentCUDto { + private Long departmentId; + private Long major1Id; + private Long major2Id; + private String studentNum; + private int semester; + private String name; + private String phone; + private String email; + private String profile; + private String blog; + private String githubId; + private String readme; + + public static StudentCUDto of(StudentCURequest request) { + return new StudentCUDto(request.getDepartmentId(), request.getMajor1Id(), request.getMajor2Id(), + request.getStudentNum(), request.getSemester(), request.getName(), request.getPhone(), + request.getEmail(), request.getProfile(), request.getBlog(), request.getGithubId(), request.getReadme()); + } +} diff --git a/src/main/java/com/server/hispath/student/application/dto/StudentDto.java b/src/main/java/com/server/hispath/student/application/dto/StudentDto.java new file mode 100644 index 0000000..2ad8866 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/StudentDto.java @@ -0,0 +1,38 @@ +package com.server.hispath.student.application.dto; + +import com.server.hispath.category.application.dto.CategoryDto; +import com.server.hispath.department.application.dto.DepartmentDto; +import com.server.hispath.major.application.dto.MajorDto; +import com.server.hispath.student.domain.Student; +import com.server.hispath.student.presentation.request.StudentCURequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentDto { + private Long id; + private String name; + private int semester; + private String studentNum; + private String phone; + private String email; + private String profile; + private DepartmentDto departmentDto; + private MajorDto major1; + private MajorDto major2; + private long loginCnt; + private String blog; + private String githubId; + private String readme; + + public static StudentDto from (Student student) { + return new StudentDto(student.getId(), student.getName(), student.getSemester(), student.getStudentNum(), student.getPhone(), + student.getEmail(), student.getProfile(), DepartmentDto.from(student.getDepartment()), + MajorDto.from(student.getMajor1()), MajorDto.from(student.getMajor2()), + student.getLoginCnt(), student.getBlog(), student.getGithubId(), student.getReadme()); + } + +} diff --git a/src/main/java/com/server/hispath/student/application/dto/StudentRefDetailDto.java b/src/main/java/com/server/hispath/student/application/dto/StudentRefDetailDto.java new file mode 100644 index 0000000..8b58793 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/StudentRefDetailDto.java @@ -0,0 +1,21 @@ +package com.server.hispath.student.application.dto; + + +import com.server.hispath.student.domain.Student; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentRefDetailDto { + private Long id; + private String name; + private String studentNum; + + public static StudentRefDetailDto of(Student student){ + return new StudentRefDetailDto(student.getId(), student.getName(), student.getStudentNum()); + } +} diff --git a/src/main/java/com/server/hispath/student/application/dto/StudentRefDto.java b/src/main/java/com/server/hispath/student/application/dto/StudentRefDto.java new file mode 100644 index 0000000..093a241 --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/StudentRefDto.java @@ -0,0 +1,24 @@ +package com.server.hispath.student.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentRefDto { + private Long id; + private String name; + private String studentNum; + private int semester; + private Long departmentId; + private Long major1Id; + private Long major2Id; + private String phone; + private String email; + private String profile; + private String blog; + private String githubId; + private String readme; +} diff --git a/src/main/java/com/server/hispath/student/application/dto/StudentSimpleRefDto.java b/src/main/java/com/server/hispath/student/application/dto/StudentSimpleRefDto.java new file mode 100644 index 0000000..9ddbe0b --- /dev/null +++ b/src/main/java/com/server/hispath/student/application/dto/StudentSimpleRefDto.java @@ -0,0 +1,19 @@ +package com.server.hispath.student.application.dto; + +import com.server.hispath.activity.presentation.request.MStudentRegisterRequest; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class StudentSimpleRefDto { + private String studentNum; + private String name; + + public static StudentSimpleRefDto of(MStudentRegisterRequest request){ + return new StudentSimpleRefDto(request.getStudentNum(), request.getName()); + } +} diff --git a/src/main/java/com/server/hispath/student/domain/Participant.java b/src/main/java/com/server/hispath/student/domain/Participant.java new file mode 100644 index 0000000..38b4d6b --- /dev/null +++ b/src/main/java/com/server/hispath/student/domain/Participant.java @@ -0,0 +1,90 @@ +package com.server.hispath.student.domain; + +import java.util.Objects; +import javax.persistence.*; + +import com.server.hispath.activity.application.dto.ParticipantContentDto; +import com.server.hispath.activity.domain.Activity; +import com.server.hispath.common.BaseEntity; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@NoArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE participant SET deleted = true Where id = ?") +public class Participant extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Student student; + + @ManyToOne(fetch = FetchType.LAZY) + private Activity activity; + + @Enumerated(EnumType.STRING) + private Section section; + + @Column(length = 5555) + String data; + + public Participant(Student student, Activity activity, Section section) { + this.student = student; + this.activity = activity; + this.section = section; + this.data = ""; + } + + public Participant(Student student, Activity activity, ParticipantContentDto dto) { + this.student = student; + this.activity = activity; + this.section = dto.getSection(); + this.data = dto.getData(); + } + + public boolean isSameSemester(String semester) { + if (Objects.equals(semester, "ALL")) + return true; + return activity.isSameSemester(semester); + } + + public boolean isSameSection(String section) { + if (Objects.equals(section, "ALL")) + return true; + if (Objects.equals(section, "마일리지")) + return this.activity.getRequestStatus() == 1; + return Objects.equals(this.section.getName(), section); + } + + public boolean isSameCategory(String category) { + if(Objects.equals(category, "ALL")) + return true; + return activity.isSameCategory(category); + } + + public boolean isSameStudent(Student student) { + return Objects.equals(this.student, student); + } + + public void update(ParticipantContentDto participantContentDto) { + this.section = participantContentDto.getSection(); + this.data = participantContentDto.getData(); + } + + public String getActivityCategoryName(){ + return activity.getCategory().getName(); + } + + public boolean isPersonal(){ + return this.activity.isPersonal(); + } + + +} diff --git a/src/main/java/com/server/hispath/student/domain/Section.java b/src/main/java/com/server/hispath/student/domain/Section.java new file mode 100644 index 0000000..175d004 --- /dev/null +++ b/src/main/java/com/server/hispath/student/domain/Section.java @@ -0,0 +1,29 @@ +package com.server.hispath.student.domain; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.server.hispath.exception.student.SectionNotExistException; + +public enum Section { + EXPERIENCE("경험"), EDUCATION("교육"),SKILL("기술"), CERTIFICATE("자격증"),REWARD("수상"), + LANGUAGE("외국어"), LINK("링크"), ETC("기타"); + + private String name; + + Section(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + private static final Map map = Collections.unmodifiableMap(Stream.of(values()) + .collect(Collectors.toMap(Section::getName, Function.identity()))); + public static Section find(String name){ + return Optional.ofNullable(map.get(name)).orElseThrow(SectionNotExistException::new); + } +} diff --git a/src/main/java/com/server/hispath/student/domain/Student.java b/src/main/java/com/server/hispath/student/domain/Student.java new file mode 100644 index 0000000..5cfe674 --- /dev/null +++ b/src/main/java/com/server/hispath/student/domain/Student.java @@ -0,0 +1,151 @@ +package com.server.hispath.student.domain; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.persistence.*; + +import com.server.hispath.common.BaseEntity; +import com.server.hispath.department.domain.Department; +import com.server.hispath.major.domain.Major; +import com.server.hispath.resume.domain.Resume; +import com.server.hispath.scholarship.domain.Scholarship; +import com.server.hispath.student.application.dto.StudentCUDto; +import com.server.hispath.student.application.dto.StudentDto; +import com.server.hispath.student.application.dto.StudentRefDto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; + +@Entity +@Getter +@Builder +@NoArgsConstructor +@Where(clause = "deleted = false") +@SQLDelete(sql = "UPDATE student SET deleted = true Where id = ?") +@AllArgsConstructor +public class Student extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String studentNum; + + private int semester; + + private String phone; + + private String email; + + @ManyToOne(fetch = FetchType.LAZY) + private Major major1; + + @ManyToOne(fetch = FetchType.LAZY) + private Major major2; + + private Long loginCnt; + + private String profile; + + private String blog; + + private String githubId; + + private LocalDateTime lastLoginDate; + + @Column(length = 5555) + private String readme; + + @ManyToOne(fetch = FetchType.LAZY) + private Department department; + + @OneToMany(mappedBy = "student", cascade = CascadeType.PERSIST, orphanRemoval = true) + private List participants = new ArrayList<>(); + + @OneToMany(mappedBy = "student") + private List resumes = new ArrayList<>(); + + @OneToMany(mappedBy = "student") + private List scholarships = new ArrayList<>(); + + public void update(Department department, Major major1, Major major2, StudentCUDto dto) { + this.name = dto.getName(); + this.studentNum = dto.getStudentNum(); + this.semester = dto.getSemester(); + this.phone = dto.getPhone(); + this.email = dto.getEmail(); + this.profile = dto.getProfile(); + this.department = department; + this.major1 = major1; + this.major2 = major2; + this.blog = dto.getBlog(); + this.githubId = dto.getGithubId(); + this.readme = dto.getReadme(); + } + + public static Student from(StudentCUDto dto, Department department, Major major1, Major major2) { + return Student.builder() + .name(dto.getName()) + .department(department) + .studentNum(dto.getStudentNum()) + .semester(dto.getSemester()) + .major1(major1) + .major2(major2) + .phone(dto.getPhone()) + .email(dto.getEmail()) + .profile(dto.getProfile()) + .blog(dto.getBlog()) + .githubId(dto.getGithubId()) + .loginCnt(0L) + .readme(dto.getReadme()) + .build(); + } + + public static Student from(StudentRefDto dto, Department department, Major major1, Major major2) { + return Student.builder() + .name(dto.getName()) + .studentNum(dto.getStudentNum()) + .semester(dto.getSemester()) + .department(department) + .major1(major1) + .major2(major2) + .phone(dto.getPhone()) + .email(dto.getEmail()) + .profile(dto.getProfile()) + .blog(dto.getBlog()) + .githubId(dto.getGithubId()) + .loginCnt(0L) + .readme(dto.getReadme()) + .build(); + } + public static Student from(StudentDto dto) { + return Student.builder() + .name(dto.getName()) + .build(); + } + + public boolean isNameMatch(String name) { + return Objects.equals(this.name, name); + } + + public void addParticipant(Participant participant) { + this.participants.add(participant); + } + + public void addResume(Resume resume){ + this.resumes.add(resume); + } + + public void updateLogin() { + loginCnt++; + lastLoginDate = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/server/hispath/student/domain/repository/StudentRepository.java b/src/main/java/com/server/hispath/student/domain/repository/StudentRepository.java new file mode 100644 index 0000000..ba73716 --- /dev/null +++ b/src/main/java/com/server/hispath/student/domain/repository/StudentRepository.java @@ -0,0 +1,46 @@ +package com.server.hispath.student.domain.repository; + +import java.util.Optional; + +import com.server.hispath.student.domain.Student; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +public interface StudentRepository extends JpaRepository { + + Optional findByStudentNum(String studentNum); + + @Query("select a from Student a " + + "left join fetch a.participants as p " + + "left join fetch p.activity " + + "where a.id = :id") + Optional findActivitiesByStudent(Long id); + + Optional findByEmail(String email); + + @Query("select s from Student s " + + "left join fetch s.participants as p " + + "left join fetch p.activity as a " + + "where s.id = :id") + Optional findStudentWithActivities(Long id); + + @Query("select s from Student s " + + "left join fetch s.participants as p " + + "left join fetch p.activity as a " + + "left join fetch a.category " + + "where s.id = :id " + + "and a.semester = :semester") + Optional findStudentWithIdAndSemester(Long id, String semester); + + @Query("select s from Student s " + + "left join fetch s.participants as p " + + "left join fetch p.activity as a " + + "where s.id = :id and a.requestStatus = 1") + Optional findStudentWithMActivities(Long id); + + @Query("select s from Student s " + + "left join fetch s.scholarships " + + "where s.id = :id ") + Optional findStudentWithScholarships(Long id); +} diff --git a/src/main/java/com/server/hispath/student/domain/repository/StudentRepositoryCustom.java b/src/main/java/com/server/hispath/student/domain/repository/StudentRepositoryCustom.java new file mode 100644 index 0000000..da6535e --- /dev/null +++ b/src/main/java/com/server/hispath/student/domain/repository/StudentRepositoryCustom.java @@ -0,0 +1,49 @@ +package com.server.hispath.student.domain.repository; + +import java.util.Objects; +import java.util.Optional; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.server.hispath.student.domain.QStudent; +import com.server.hispath.student.domain.Student; + +import org.springframework.stereotype.Repository; + +import lombok.RequiredArgsConstructor; + +import static com.server.hispath.activity.domain.QActivity.activity; +import static com.server.hispath.student.domain.QParticipant.participant; +import static com.server.hispath.student.domain.QStudent.student; + +@Repository +@RequiredArgsConstructor +public class StudentRepositoryCustom { + private final JPAQueryFactory queryFactory; + + + public Optional findStudentWithIdAndSemester(Long id, String semester, boolean isMileage) { + Student student = queryFactory.select(QStudent.student) + .from(QStudent.student) + .leftJoin(QStudent.student.participants, participant).fetchJoin() + .leftJoin(participant.activity, activity).fetchJoin() + .leftJoin(activity.category).fetchJoin() + .where(studentSearchCondition(id, semester, isMileage)) + .fetchOne(); + return Optional.ofNullable(student); + } + + + public BooleanBuilder studentSearchCondition(Long studentId, String semester, boolean isMileage) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + + booleanBuilder.and(student.id.eq(studentId)); + if (!Objects.isNull(semester)) { + booleanBuilder.and(activity.semester.eq(semester)); + } + if (isMileage) { + booleanBuilder.and(activity.requestStatus.eq(1)); + } + return booleanBuilder; + } +} diff --git a/src/main/java/com/server/hispath/student/presentation/StudentController.java b/src/main/java/com/server/hispath/student/presentation/StudentController.java new file mode 100644 index 0000000..3166d91 --- /dev/null +++ b/src/main/java/com/server/hispath/student/presentation/StudentController.java @@ -0,0 +1,161 @@ +package com.server.hispath.student.presentation; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.ActivityService; +import com.server.hispath.activity.application.dto.ActivityParticipantDto; +import com.server.hispath.activity.presentation.response.ActivityParticipantStatusResponse; +import com.server.hispath.activity.presentation.response.SemesterResponse; +import com.server.hispath.auth.domain.LoginStudent; +import com.server.hispath.auth.domain.RequiredLogin; +import com.server.hispath.auth.domain.RequiredManagerLogin; +import com.server.hispath.auth.domain.StudentLogin; +import com.server.hispath.docs.ApiDoc; +import com.server.hispath.notice.application.NoticeService; +import com.server.hispath.notice.application.dto.DashboardNoticeDto; +import com.server.hispath.resume.application.ResumeService; +import com.server.hispath.resume.application.dto.ResumeDto; +import com.server.hispath.student.application.StudentService; +import com.server.hispath.student.application.dto.StudentCUDto; +import com.server.hispath.student.application.dto.StudentDto; +import com.server.hispath.student.presentation.request.StudentCURequest; +import com.server.hispath.student.presentation.response.DashboardResponse; +import com.server.hispath.student.presentation.response.StudentResponse; +import com.server.hispath.util.ExcelManager; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.annotations.ApiOperation; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class StudentController { + + private final StudentService studentService; + private final NoticeService noticeService; + private final ActivityService activityService; + private final ResumeService resumeService; + + @PostMapping("/student") + @ApiOperation(value = ApiDoc.STUDENT_CREATE) + @RequiredManagerLogin + public ResponseEntity create(@RequestBody StudentCURequest request) { + Long savedId = studentService.create(StudentCUDto.of(request)); + return ResponseEntity.ok(savedId); + } + + @PostMapping("/students") + @ApiOperation(value = ApiDoc.STUDENTS_CREATE) + @RequiredManagerLogin + public ResponseEntity createStudents(@RequestPart("file") MultipartFile file) throws Exception { + studentService.createAll(ExcelManager.getStudentDatas(ExcelManager.extract(file))); + return ResponseEntity.ok(null); + } + + @GetMapping("/student/{id}") + @ApiOperation(value = ApiDoc.STUDENT_READ) + @RequiredManagerLogin + public ResponseEntity find(@PathVariable Long id) { + StudentDto dto = studentService.find(id); + StudentResponse response = StudentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @GetMapping("/student") + @ApiOperation(value = ApiDoc.STUDENT_READ) + @RequiredLogin + public ResponseEntity find(@StudentLogin LoginStudent loginStudent) { + StudentDto dto = studentService.find(loginStudent.getId()); + StudentResponse response = StudentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @GetMapping("/students") + @ApiOperation(value = ApiDoc.STUDENT_READ_ALL) + @RequiredManagerLogin + public ResponseEntity> findAll() { + List dtos = studentService.findAll(); + List responses = dtos.stream() + .map(StudentResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @PutMapping("/student/{id}") + @ApiOperation(value = ApiDoc.STUDENT_UPDATE) + @RequiredManagerLogin + public ResponseEntity update(@PathVariable Long id, @RequestBody StudentCURequest request) { + StudentDto dto = studentService.update(id, request.getDepartmentId(), request.getMajor1Id(), request.getMajor2Id(), StudentCUDto.of(request)); + StudentResponse response = StudentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @PutMapping("/student") + @ApiOperation(value = ApiDoc.STUDENT_UPDATE) + @RequiredLogin + public ResponseEntity update( + @StudentLogin LoginStudent loginStudent, + @RequestBody StudentCURequest request) { + StudentDto dto = studentService.update(loginStudent.getId(), request.getDepartmentId(), + request.getMajor1Id(), request.getMajor2Id(), StudentCUDto.of(request)); + StudentResponse response = StudentResponse.from(dto); + return ResponseEntity.ok(response); + } + + @DeleteMapping("/student/{id}") + @ApiOperation(value = ApiDoc.STUDENT_DELETE) + @RequiredManagerLogin + public ResponseEntity delete(@PathVariable Long id) { + + studentService.delete(id); + return ResponseEntity.ok(id); + } + + @GetMapping("/student/dashboard") + @ApiOperation(value = ApiDoc.DASHBOARD) + @RequiredLogin + public ResponseEntity getDashboardInfo(@StudentLogin LoginStudent loginStudent) { + + StudentDto studentDto = studentService.find(loginStudent.getId()); + List dashboardNoticeDtos = noticeService.findRecentNotice(); + List resumeDtos = resumeService.findRecentResumes(loginStudent.getId()); + List activityDtos = activityService.findRecentParticipantActivities(loginStudent.getId()); + + return ResponseEntity.ok(DashboardResponse.from(studentDto, dashboardNoticeDtos, resumeDtos, activityDtos)); + } + + @GetMapping("/student-activities/status") + @ApiOperation(value = ApiDoc.STUDENT_ACTIVITY_READ_SEMESTER_SECTION_STATUS) + @RequiredLogin + public ResponseEntity> findStudentActivitiesWithStatus( + @StudentLogin LoginStudent loginStudent, + @RequestParam String semester, + @RequestParam String section) { + + List responses = activityService.findAllPersonalParticipantActivites(loginStudent.getId(), semester, section) + .stream() + .map(ActivityParticipantStatusResponse::of) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } + + @GetMapping("/student/semesters") + @ApiOperation(value = ApiDoc.STUDENT_SEMESTER) + @RequiredLogin + public ResponseEntity> getStudentSemeters( + @StudentLogin LoginStudent loginStudent + ) { + + List responses = studentService.getStudentSemesters(loginStudent.getId()) + .stream() + .map(SemesterResponse::from) + .collect(Collectors.toList()); + return ResponseEntity.ok(responses); + } +} diff --git a/src/main/java/com/server/hispath/student/presentation/request/StudentCURequest.java b/src/main/java/com/server/hispath/student/presentation/request/StudentCURequest.java new file mode 100644 index 0000000..51c6835 --- /dev/null +++ b/src/main/java/com/server/hispath/student/presentation/request/StudentCURequest.java @@ -0,0 +1,23 @@ +package com.server.hispath.student.presentation.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class StudentCURequest { + private Long departmentId; + private Long major1Id; + private Long major2Id; + private String studentNum; + private int semester; + private String name; + private String phone; + private String email; + private String profile; + private String blog; + private String githubId; + private String readme; +} diff --git a/src/main/java/com/server/hispath/student/presentation/response/DashboardResponse.java b/src/main/java/com/server/hispath/student/presentation/response/DashboardResponse.java new file mode 100644 index 0000000..534c589 --- /dev/null +++ b/src/main/java/com/server/hispath/student/presentation/response/DashboardResponse.java @@ -0,0 +1,51 @@ +package com.server.hispath.student.presentation.response; + +import java.util.List; +import java.util.stream.Collectors; + +import com.server.hispath.activity.application.dto.ActivityParticipantDto; +import com.server.hispath.department.presentation.response.DepartmentResponse; +import com.server.hispath.major.presentation.response.MajorResponse; +import com.server.hispath.notice.application.dto.DashboardNoticeDto; +import com.server.hispath.notice.presentation.response.NoticeDashboardResponse; +import com.server.hispath.resume.application.dto.ResumeDto; +import com.server.hispath.student.application.dto.StudentDto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class DashboardResponse { + private Long id; + private String profile; + private String name; + private String studentNum; + private MajorResponse major1; + private MajorResponse major2; + private DepartmentResponse department; + private int semester; + private String email; + private String phone; + private String githubId; + private String blog; + private String readme; + private List notice; + private List resumes; + private List activities; + + public static DashboardResponse from(StudentDto studentDto, + List noticeDtos, + List resumeDtos, + List activityParticipantDtos) { + + return new DashboardResponse(studentDto.getId(), studentDto.getProfile(), studentDto.getName(), studentDto.getStudentNum(), + MajorResponse.from(studentDto.getMajor1()), MajorResponse.from(studentDto.getMajor2()), DepartmentResponse.from(studentDto.getDepartmentDto()), + studentDto.getSemester(), studentDto.getEmail(), studentDto.getPhone(), studentDto.getGithubId(), studentDto.getBlog(), studentDto.getReadme(), + noticeDtos.stream() + .map(NoticeDashboardResponse::of) + .collect(Collectors.toList()), resumeDtos, activityParticipantDtos); + } +} diff --git a/src/main/java/com/server/hispath/student/presentation/response/StudentResponse.java b/src/main/java/com/server/hispath/student/presentation/response/StudentResponse.java new file mode 100644 index 0000000..f6b7121 --- /dev/null +++ b/src/main/java/com/server/hispath/student/presentation/response/StudentResponse.java @@ -0,0 +1,37 @@ +package com.server.hispath.student.presentation.response; + +import com.server.hispath.student.application.dto.StudentDto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class StudentResponse { + private Long studentId; + private String name; + private int semester; + private String studentNum; + private String phone; + private String email; + private String profile; + private Long departmentId; + private String departmentName; + private Long major1Id; + private String major1Name; + private Long major2Id; + private String major2Name; + private long loginCnt; + private String blog; + private String githubId; + private String readme; + + public static StudentResponse from (StudentDto dto) { + return new StudentResponse(dto.getId(), dto.getName(), dto.getSemester(), dto.getStudentNum(), dto.getPhone(), dto.getEmail(), + dto.getProfile(), dto.getDepartmentDto().getId(), dto.getDepartmentDto().getName(), + dto.getMajor1().getId(), dto.getMajor1().getName(), dto.getMajor2().getId(), dto.getMajor2().getName(), + dto.getLoginCnt(), + dto.getBlog(), dto.getGithubId(), dto.getReadme()); + } +} diff --git a/src/main/java/com/server/hispath/util/AuthorizationExtractor.java b/src/main/java/com/server/hispath/util/AuthorizationExtractor.java new file mode 100644 index 0000000..d5ab61b --- /dev/null +++ b/src/main/java/com/server/hispath/util/AuthorizationExtractor.java @@ -0,0 +1,26 @@ +package com.server.hispath.util; + +import java.util.Enumeration; +import java.util.Locale; +import javax.servlet.http.HttpServletRequest; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class AuthorizationExtractor { + public static final String AUTHENTICATION_TYPE = "Bearer"; + public static final String AUTHORIZATION = "Authorization"; + + public static String extractAccessToken(HttpServletRequest request) { + Enumeration headers = request.getHeaders(AUTHORIZATION); + while (headers.hasMoreElements()) { + String value = headers.nextElement(); + if (value.toLowerCase(Locale.ROOT).startsWith(AUTHENTICATION_TYPE.toLowerCase(Locale.ROOT))) { + return value.split(" ")[1]; + } + } + return ""; + } +} + diff --git a/src/main/java/com/server/hispath/util/ExcelManager.java b/src/main/java/com/server/hispath/util/ExcelManager.java new file mode 100644 index 0000000..8f3c1fd --- /dev/null +++ b/src/main/java/com/server/hispath/util/ExcelManager.java @@ -0,0 +1,150 @@ +package com.server.hispath.util; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; + +import com.server.hispath.activity.application.dto.MActivityContentDto; +import com.server.hispath.exception.common.ExcelDataFormatException; +import com.server.hispath.exception.common.ExcelFormatException; +import com.server.hispath.exception.common.NotExcelExtensionException; +import com.server.hispath.scholarship.application.dto.ScholarshipApprovalDto; +import com.server.hispath.student.application.dto.StudentRefDto; +import com.server.hispath.student.application.dto.StudentSimpleRefDto; + +import org.springframework.web.multipart.MultipartFile; + +import org.apache.commons.io.FilenameUtils; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +public class ExcelManager { + + public static Sheet extract(MultipartFile file) throws Exception { + Workbook workbook = null; + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (extension.equals("xlsx")) { + workbook = new XSSFWorkbook(file.getInputStream()); + } else if (extension.equals("xls")) { + workbook = new HSSFWorkbook(file.getInputStream()); + } else { + throw new NotExcelExtensionException(); + } + + return workbook.cloneSheet(0); + } + + public static void validate(String semester) { + String pattern = "[0-9]{4}-[0-9]"; + if (!Pattern.matches(pattern, semester)) + throw new ExcelDataFormatException(semester); + } + + public static List getMActivities(Sheet worksheet) { + List mActivityContentDtos = new ArrayList<>(); + for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { + try { + Row row = worksheet.getRow(i); + Long categoryId = Long.parseLong(row.getCell(0).toString().split("\\.")[0].toString()); + String activityName = row.getCell(1).toString(); + String remark = Objects.isNull(row.getCell(2)) ? "" : row.getCell(2).toString(); + int weight = Integer.parseInt(row.getCell(3).toString()); + String semester = row.getCell(4).toString(); + validate(semester); + mActivityContentDtos.add(new MActivityContentDto(categoryId, semester, activityName, remark, weight)); + } catch (Exception e) { + throw new ExcelFormatException(e.getMessage()); + } + + } + return mActivityContentDtos; + } + + public static List getStudentSimpleDatas(Sheet worksheet) { + List studentRefDtos = new ArrayList<>(); + + for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { + try { + Row row = worksheet.getRow(i); + String studentNum = row.getCell(0).toString(); + String studentName = row.getCell(1).toString(); + + studentRefDtos.add(new StudentSimpleRefDto(studentNum, studentName)); + } catch (Exception e) { + throw new ExcelFormatException(e.getMessage()); + } + } + return studentRefDtos; + } + + public static List getStudentDatas(Sheet worksheet) { + List studentRefDtos = new ArrayList<>(); + for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { + try { + Row row = worksheet.getRow(i); + String studentName = row.getCell(0).toString(); + String str = row.getCell(1).toString(); + int num = new BigDecimal(str).intValue(); + String studentNum = Integer.toString(num); + int studentSemester = Integer.parseInt(row.getCell(2).toString().split("\\.")[0]); + Long departmentId = Long.parseLong(row.getCell(3) + .toString() + .split("\\.")[0]);// int departmentId = 0; + Long major1Id = Long.parseLong(row.getCell(4).toString().split("\\.")[0]); + Long major2Id = Long.parseLong(row.getCell(5).toString().split("\\.")[0]); + + studentRefDtos.add(new StudentRefDto((long) i, studentName, studentNum, + studentSemester, departmentId, major1Id, major2Id, "010-1234-1234", "handong@ac.kr", + "url", "blog.com", "@github", "readme content")); + + } catch (Exception e) { + throw new ExcelFormatException(e.getMessage()); + } + } + return studentRefDtos; + } + + public static List getScholarshipApproveDatas(Sheet worksheet) { + List scholarshipDtos = new ArrayList<>(); + for (int i = 1; i < worksheet.getPhysicalNumberOfRows(); i++) { + try { + Row row = worksheet.getRow(i); + String studentNum = row.getCell(0).toString().trim(); + String name = row.getCell(1).toString().trim(); + int studentSemester = Integer.parseInt(row.getCell(2).toString().trim()); + int weight = Integer.parseInt(row.getCell(3).toString().trim()); + String result = row.getCell(4).toString().trim(); + scholarshipDtos.add(new ScholarshipApprovalDto(name, studentNum, studentSemester, weight, result)); + } catch (Exception e) { + throw new ExcelFormatException(e.getMessage()); + } + } + return scholarshipDtos; + } + + public static Workbook toCsv(List dtos) { + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet(); + + createRow(sheet, Arrays.asList("학번", "이름", "학기수", "총 가중치", "결과"), 0); + for(int i=0; i cellList, int rowNum) { + Row row = sheet.createRow(rowNum); + for (int i = 0; i < cellList.size(); i++) { + row.createCell(i).setCellValue(String.valueOf(cellList.get(i))); + } + } +} diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..4df4d25 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/src/test/java/com/server/hispath/HispathApplicationTests.java b/src/test/java/com/server/hispath/HispathApplicationTests.java new file mode 100644 index 0000000..bf384e0 --- /dev/null +++ b/src/test/java/com/server/hispath/HispathApplicationTests.java @@ -0,0 +1,13 @@ +package com.server.hispath; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class HispathApplicationTests { + + @Test + void contextLoads() { + } + +}