Browse Source

SW중심대학사업단 OSS 업로드

master
김태원 5 years ago
commit
752889ad80
  1. 38
      .gitignore
  2. 2
      README.md
  3. 51
      build.gradle
  4. BIN
      gradle/wrapper/gradle-wrapper.jar
  5. 5
      gradle/wrapper/gradle-wrapper.properties
  6. 185
      gradlew
  7. 89
      gradlew.bat
  8. 1
      settings.gradle
  9. 90
      src/main/java/com/maveProject/mave/InitDb.java
  10. 15
      src/main/java/com/maveProject/mave/MaveApplication.java
  11. 81
      src/main/java/com/maveProject/mave/controller/FileController.java
  12. 14
      src/main/java/com/maveProject/mave/controller/HelloController.java
  13. 60
      src/main/java/com/maveProject/mave/domain/Answer.java
  14. 26
      src/main/java/com/maveProject/mave/domain/BaseTimeEntity.java
  15. 31
      src/main/java/com/maveProject/mave/domain/CustomQuestion.java
  16. 39
      src/main/java/com/maveProject/mave/domain/File.java
  17. 21
      src/main/java/com/maveProject/mave/domain/Flower.java
  18. 150
      src/main/java/com/maveProject/mave/domain/Group.java
  19. 5
      src/main/java/com/maveProject/mave/domain/IsFinish.java
  20. 69
      src/main/java/com/maveProject/mave/domain/Member.java
  21. 49
      src/main/java/com/maveProject/mave/domain/Question.java
  22. 28
      src/main/java/com/maveProject/mave/domain/QuestionBank.java
  23. 33
      src/main/java/com/maveProject/mave/dto/FileDto.java
  24. 65
      src/main/java/com/maveProject/mave/repository/AnswerRepository.java
  25. 14
      src/main/java/com/maveProject/mave/repository/CustomRepository.java
  26. 7
      src/main/java/com/maveProject/mave/repository/FileRepository.java
  27. 36
      src/main/java/com/maveProject/mave/repository/GroupRepository.java
  28. 36
      src/main/java/com/maveProject/mave/repository/MemberRepository.java
  29. 28
      src/main/java/com/maveProject/mave/repository/QuestionBankRepository.java
  30. 82
      src/main/java/com/maveProject/mave/repository/QuestionRepository.java
  31. 98
      src/main/java/com/maveProject/mave/restController/AnswerApiController.java
  32. 97
      src/main/java/com/maveProject/mave/restController/CustomApiController.java
  33. 73
      src/main/java/com/maveProject/mave/restController/FileApiController.java
  34. 137
      src/main/java/com/maveProject/mave/restController/GroupApiController.java
  35. 76
      src/main/java/com/maveProject/mave/restController/MemberApiController.java
  36. 86
      src/main/java/com/maveProject/mave/restController/QuestionApiController.java
  37. 45
      src/main/java/com/maveProject/mave/service/AnswerService.java
  38. 35
      src/main/java/com/maveProject/mave/service/FileService.java
  39. 61
      src/main/java/com/maveProject/mave/service/GroupService.java
  40. 57
      src/main/java/com/maveProject/mave/service/MemberService.java
  41. 21
      src/main/java/com/maveProject/mave/service/QuestionBankService.java
  42. 39
      src/main/java/com/maveProject/mave/service/QuestionService.java
  43. 30
      src/main/java/com/maveProject/mave/util/MD5Generator.java
  44. 17
      src/main/resources/application.properties
  45. 22
      src/main/resources/templates/home.html
  46. 14
      src/main/resources/templates/result.html
  47. 13
      src/test/java/com/maveProject/mave/MaveApplicationTests.java
  48. 44
      src/test/java/com/maveProject/mave/Testststst.java
  49. 27
      src/test/java/com/maveProject/mave/controller/FileControllerTest.java
  50. 17
      src/test/resources/application.properties

38
.gitignore

@ -0,0 +1,38 @@
HELP.md
.gradle
build/
mave-photoBook
!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/

2
README.md

@ -0,0 +1,2 @@
# 2021학년도 1학기 기업연계프로젝트 <br />Mave 서버 API

51
build.gradle

@ -0,0 +1,51 @@
plugins {
id 'org.springframework.boot' version '2.4.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
id 'java'
}
group = 'com.maveProject'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
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 'com.querydsl:querydsl-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}

BIN
gradle/wrapper/gradle-wrapper.jar

5
gradle/wrapper/gradle-wrapper.properties

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or 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 UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$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 "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# 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
;;
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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat

@ -0,0 +1,89 @@
@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%" == "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%"=="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!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle

@ -0,0 +1 @@
rootProject.name = 'mave'

90
src/main/java/com/maveProject/mave/InitDb.java

@ -0,0 +1,90 @@
package com.maveProject.mave;
import com.maveProject.mave.domain.*;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 임시로 DB에 시작 데이터 넣음
*/
@Profile("local")
@RequiredArgsConstructor
@Component
public class InitDb {
private final InitService initService;
@PostConstruct
public void init(){
initService.dbInit();
}
@Transactional
@RequiredArgsConstructor
@Component
static class InitService{
private final EntityManager em;
public void dbInit(){
QuestionBank questionBank1 = new QuestionBank();
questionBank1.setQuestionNumber(1l);
questionBank1.setContent("1. 자신의 좋은 추억 장소는? ");
QuestionBank questionBank2 = new QuestionBank();
questionBank2.setQuestionNumber(2l);
questionBank2.setContent("2. 가장 행복했던 기억은? ");
QuestionBank questionBank3 = new QuestionBank();
questionBank3.setQuestionNumber(3l);
questionBank3.setContent("3. 아들의 꿈은? ");
QuestionBank questionBank4 = new QuestionBank();
questionBank4.setQuestionNumber(4l);
questionBank4.setContent("4. 어머니의 어릴 적 꿈은? ");
QuestionBank questionBank5 = new QuestionBank();
questionBank5.setQuestionNumber(5l);
questionBank5.setContent("5. 아버지가 좋아하는 음식은? ");
em.persist(questionBank1);
em.persist(questionBank2);
em.persist(questionBank3);
em.persist(questionBank4);
em.persist(questionBank5);
Member member = new Member("hello","48690","hello");
em.persist(member);
Group group = new Group("그루비룸", LocalDateTime.now(), IsFinish.NO, Flower.ZERO, 1l,1l);
member.SetGroup(group);
em.persist(group);
Question question = new Question(group,questionBank1.getContent(),questionBank1.getQuestionNumber());
group.setCount();
em.persist(question);
Answer answer = new Answer("미리 한 답변입니다!");
answer.registMember(member);
answer.addAnswer(question);
answer.registGroup(group);
group.minusCount();
group.compareState();
em.persist(answer);
}
}
}

15
src/main/java/com/maveProject/mave/MaveApplication.java

@ -0,0 +1,15 @@
package com.maveProject.mave;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@EnableJpaAuditing
@SpringBootApplication
public class MaveApplication {
public static void main(String[] args) {
SpringApplication.run(MaveApplication.class, args);
}
}

81
src/main/java/com/maveProject/mave/controller/FileController.java

@ -0,0 +1,81 @@
package com.maveProject.mave.controller;
import com.maveProject.mave.dto.FileDto;
import com.maveProject.mave.service.FileService;
import com.maveProject.mave.util.MD5Generator;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RequiredArgsConstructor
@Controller
public class FileController {
private final FileService fileService;
@PostMapping("/post")
public String write(@RequestParam("file") MultipartFile files, Model model) {
try {
if (files.isEmpty()) {
return "redirect:/home";
}
String originalFilename = files.getOriginalFilename();
// 파일 이름 가져오기
String filename = new MD5Generator(originalFilename).toString(); // 파일 이름 기반 hash값 생성?
String savePath = System.getProperty("user.dir") + "\\mave-photoBook"; // mave-photoBook 폴더에 파일 저장
/* mave-photoBook 폴더가 없다면 생성 */
if (!new File(savePath).exists()) {
try {
new File(savePath).mkdir();
} catch (Exception e) {
e.printStackTrace();
}
}
String filePath = savePath + "\\" + filename; // 파일 저장될 위치
files.transferTo(new File(filePath)); // files로 넘어온 파일을 filePath 위치에 넘긴다.
FileDto fileDto = new FileDto(); // 넘어온 file을 dto로 바꿔주는 작업
fileDto.setOrigFilename(originalFilename);
fileDto.setFilename(filename);
fileDto.setFilePath(filePath);
Long fileId = fileService.saveFile(fileDto); // fileDto를 DB에 저장한다.
model.addAttribute("file", fileDto); // fileDto를 result.html에 넘긴다.
model.addAttribute("fileId", fileId); // 저장한 fileId를 result.html에 넘긴다.
} catch (Exception e) {
e.printStackTrace();
}
return "result";
}
@GetMapping("/download/{fileId}")
public ResponseEntity<InputStreamResource> fileDownload(@PathVariable("fileId") Long fileId) throws IOException {
FileDto fileDto = fileService.getFile(fileId); // DB에 저장된 정보 가져온다.
Path path = Paths.get(fileDto.getFilePath()); // 가져온 정보에 저장된 path 가져온다.
InputStreamResource resource = new InputStreamResource(Files.newInputStream(path));
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileDto.getOrigFilename() + "\"")
.body(resource);
}
}

14
src/main/java/com/maveProject/mave/controller/HelloController.java

@ -0,0 +1,14 @@
package com.maveProject.mave.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/home")
public String home() {
return "home";
}
}

60
src/main/java/com/maveProject/mave/domain/Answer.java

@ -0,0 +1,60 @@
package com.maveProject.mave.domain;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Answer extends BaseTimeEntity {
@Id
@GeneratedValue
@Column(name = "answer_id")
private Long id;
private String answerContent;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "question_id")
private Question question;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "group_id")
private Group group;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "member_id")
private Member member;
//====== 생성 메서드=====//
public Answer(String answerContent) {
this.answerContent = answerContent;
}
//====== 연관관계 메서드 ======//
public void addAnswer(Question question) {
this.question = question;
question.getAnswers().add(this);
}
public void registGroup(Group group) {
this.group = group;
group.getAnswers().add(this);
}
public void registMember(Member member) {
this.member = member;
member.getAnswers().add(this);
}
}

26
src/main/java/com/maveProject/mave/domain/BaseTimeEntity.java

@ -0,0 +1,26 @@
package com.maveProject.mave.domain;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Getter
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}

31
src/main/java/com/maveProject/mave/domain/CustomQuestion.java

@ -0,0 +1,31 @@
package com.maveProject.mave.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Getter
@RequiredArgsConstructor
@Entity
public class CustomQuestion {
@Id @GeneratedValue
@Column(name="customQuestion")
private Long id;
private String questionContent;
private Long diaryDate;
private Long groupId;
public CustomQuestion(String questionContent, Long diaryDate, Long groupId) {
this.questionContent = questionContent;
this.diaryDate = diaryDate;
this.groupId = groupId;
}
}

39
src/main/java/com/maveProject/mave/domain/File.java

@ -0,0 +1,39 @@
package com.maveProject.mave.domain;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class File {
@Id
@GeneratedValue
@Column(name = "file_id")
private Long id; // 파일 고유 Id
@Column(nullable = false)
private String origFilename; // 원본 파일
@Column(nullable = false)
private String filename; // server에 저장되는 파일명
@Column(nullable = false)
private String filePath; // server에 저장되는 경로
@Builder
public File(Long id, String origFilename, String filename, String filePath) {
this.id = id;
this.origFilename = origFilename;
this.filename = filename;
this.filePath = filePath;
}
}

21
src/main/java/com/maveProject/mave/domain/Flower.java

@ -0,0 +1,21 @@
package com.maveProject.mave.domain;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
public enum Flower {
ZERO(0),ONE(1),TWO(2),THREE(3),FOUR(4),FIVE(5);
private int status;
Flower(int status){
this.status = status;
}
public int flowerStatus(){
return status;
}
}

150
src/main/java/com/maveProject/mave/domain/Group.java

@ -0,0 +1,150 @@
package com.maveProject.mave.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "groups")
public class Group {
@Id
@GeneratedValue
@Column(name = "group_id")
private Long id;
private String groupName;
private int flowerCount;
private int remainAnswerCount;
private LocalDateTime questionTime;
private Long diaryDate;
private Long completeDate;
@Enumerated(EnumType.STRING)
private IsFinish status;
@Enumerated(EnumType.STRING)
private Flower flower;
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<Member> members = new ArrayList<>();
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<Question> questions = new ArrayList<>();
@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<Answer> answers = new ArrayList<>();
//===== 생성 메서드 =====//
public Group(String groupName, LocalDateTime questionTime, IsFinish status, Flower flower, Long diaryDate, Long completeDate) {
this.groupName = groupName;
this.questionTime = questionTime;
this.status = status;
this.flower = flower;
this.diaryDate = diaryDate;
this.completeDate = completeDate;
}
//===== 연관관계 메서드 =====//
//====== 비즈니스 메서드 =====//
public Boolean isDateChanged(Long prevDate, Long nextDate){
if(prevDate < nextDate){
return true;
}
return false;
}
public void setCompleteDate(Long completeDate){
this.completeDate = completeDate;
}
public Long changeDiaryDate(){
LocalDate startDate = LocalDate.of(
this.questionTime.getYear(),
this.questionTime.getMonth(),
this.questionTime.getDayOfMonth());
Long between = ChronoUnit.DAYS.between(startDate, LocalDate.now());
this.diaryDate = between + 1;
return diaryDate;
}
public void minusCount() {
if (this.getRemainAnswerCount() == 0) {
return;
}
this.remainAnswerCount--;
}
public int setCount() {
remainAnswerCount = this.getMembers().size();
return remainAnswerCount;
}
public void changeIsFinish() {
status = IsFinish.NO;
}
public Boolean compareState() {
if (remainAnswerCount == 0) {
status = IsFinish.YES;
plusFlowerCount();
return true;
}
return false;
}
public void plusFlowerCount() {
flowerCount++;
}
public void flowerStatusCheck() {
switch (flowerCount) {
case 1:
flower = flower.ONE;
break;
case 2:
flower = flower.TWO;
break;
case 3:
flower = flower.THREE;
break;
case 4:
flower = flower.FOUR;
break;
case 5:
flower = flower.FIVE;
break;
default:
flower = flower.ZERO;
break;
}
if(flowerCount > 5){
flower = flower.FIVE;
}
}
}

5
src/main/java/com/maveProject/mave/domain/IsFinish.java

@ -0,0 +1,5 @@
package com.maveProject.mave.domain;
public enum IsFinish {
YES, NO
}

69
src/main/java/com/maveProject/mave/domain/Member.java

@ -0,0 +1,69 @@
package com.maveProject.mave.domain;
import com.maveProject.mave.util.MD5Generator;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
private String userId;
private String password;
private String userName;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "group_id")
private Group group;
@OneToMany(mappedBy = "member")
private List<Answer> answers = new ArrayList<>();
//======= 생성자 ========//
public Member(String userId) {
this.userId = userId;
}
public Member(String userId, String password, String userName) {
this.userId = userId;
this.password = password;
this.userName = userName;
}
//====== Setter =======//
public void setPassword(String password) {
this.password = password;
}
//======= 연관관계 매서드 ========//
public void SetGroup(Group group) {
this.group = group;
group.getMembers().add(this);
}
//====== 비즈니스 로직 ======//
public void changePasswordToHash() {
password = Integer.toString(password.hashCode());
}
}

49
src/main/java/com/maveProject/mave/domain/Question.java

@ -0,0 +1,49 @@
package com.maveProject.mave.domain;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Question extends BaseTimeEntity {
@Id
@GeneratedValue
@Column(name = "question_id")
private Long id;
private String questionContent;
private Long questionNumber;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "group_id")
private Group group;
@OneToMany(mappedBy = "question", cascade = CascadeType.ALL)
private List<Answer> answers = new ArrayList<>();
//===== 생성 메서드 =====//
public Question(Group group, String questionContent, Long questionNumber) {
this.group = group;
this.questionContent = questionContent;
this.questionNumber = questionNumber;
}
//===== 연관관계 메서드 =====//
public void addQuestion(Group group) {
this.group = group;
group.getQuestions().add(this);
}
}

28
src/main/java/com/maveProject/mave/domain/QuestionBank.java

@ -0,0 +1,28 @@
package com.maveProject.mave.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* 임시로 만든 질문 은행
*/
@Getter
@Setter
@Entity
public class QuestionBank {
@Id
@GeneratedValue
@Column(name = "questionBank_id")
private Long id;
private Long questionNumber;
private String content;
}

33
src/main/java/com/maveProject/mave/dto/FileDto.java

@ -0,0 +1,33 @@
package com.maveProject.mave.dto;
import com.maveProject.mave.domain.File;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class FileDto {
private Long id;
private String origFilename;
private String filename;
private String filePath;
public File toEntity() {
File build = File.builder()
.id(id)
.origFilename(origFilename)
.filename(filename)
.filePath(filePath)
.build();
return build;
}
@Builder
public FileDto(Long id, String origFilename, String filename, String filePath) {
this.id = id;
this.origFilename = origFilename;
this.filename = filename;
this.filePath = filePath;
}
}

65
src/main/java/com/maveProject/mave/repository/AnswerRepository.java

@ -0,0 +1,65 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.Answer;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.Getter;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
import static com.maveProject.mave.domain.QAnswer.answer;
import static com.maveProject.mave.domain.QGroup.group;
import static com.maveProject.mave.domain.QMember.member;
import static com.maveProject.mave.domain.QQuestion.question;
import static com.maveProject.mave.restController.AnswerApiController.AllAnswerResponse;
@Getter
@Repository
public class AnswerRepository {
private final EntityManager em;
private final JPAQueryFactory queryFactory;
public AnswerRepository(EntityManager em) {
this.em = em;
this.queryFactory = new JPAQueryFactory(em);
}
public Long save(Answer answer) {
em.persist(answer);
return answer.getId();
}
// public List<Answer> findAllAnswer(Long groupId, Long questionNumber){
// return em.createQuery("select a from Answer a " +
// " join fetch a.group g" +
// " join fetch a.member m" +
// " join fetch a.question q" +
// " where g.id = :groupId" +
// " and q.questionNumber = :questionNumber", Answer.class)
// .setParameter("groupId", groupId)
// .setParameter("questionNumber", questionNumber)
// .getResultList();
// }
public List<AllAnswerResponse> findAllAnswerQuery(Long groupId, Long questionNumber){
return queryFactory.select(Projections.constructor(AllAnswerResponse.class,
answer.member.userId,
answer.answerContent))
.from(answer)
.join(answer.group,group)
.join(answer.member,member)
.join(answer.question,question)
.where(
group.id.eq(groupId),
question.questionNumber.eq(questionNumber)
)
.fetch();
}
}

14
src/main/java/com/maveProject/mave/repository/CustomRepository.java

@ -0,0 +1,14 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.CustomQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface CustomRepository extends JpaRepository<CustomQuestion,Long> {
@Query("SELECT C.questionContent FROM CustomQuestion C WHERE C.groupId = ?1 and C.diaryDate = ?2")
String findCustomQuestion(Long groupId,Long diaryDate);
}

7
src/main/java/com/maveProject/mave/repository/FileRepository.java

@ -0,0 +1,7 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.File;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FileRepository extends JpaRepository<File, Long> {
}

36
src/main/java/com/maveProject/mave/repository/GroupRepository.java

@ -0,0 +1,36 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.Group;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
@Getter
@RequiredArgsConstructor
@Repository
public class GroupRepository {
private final EntityManager em;
public Long save(Group group){
em.persist(group);
return group.getId();
}
public Group findById(Long groupId){
Group group = em.find(Group.class, groupId);
return group;
}
public List<Group> findByName(String name){
return em.createQuery("select g from Group g where g.groupName = :name",
Group.class)
.setParameter("name", name)
.getResultList();
}
}

36
src/main/java/com/maveProject/mave/repository/MemberRepository.java

@ -0,0 +1,36 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.Member;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
@Getter
@RequiredArgsConstructor
@Repository
public class MemberRepository {
private final EntityManager em;
public Long save(Member member) {
em.persist(member);
return member.getId();
}
public Member findById(Long memberId) {
Member member = em.find(Member.class, memberId);
return member;
}
public List<Member> findByUserId(String userId) {
return em.createQuery("select m from Member m where m.userId = :userId",
Member.class)
.setParameter("userId", userId)
.getResultList();
}
}

28
src/main/java/com/maveProject/mave/repository/QuestionBankRepository.java

@ -0,0 +1,28 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.QuestionBank;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
@Getter
@RequiredArgsConstructor
@Repository
public class QuestionBankRepository {
private final EntityManager em;
public QuestionBank findById(Long questionBankId){
QuestionBank questionBank = em.find(QuestionBank.class, questionBankId);
return questionBank;
}
public List<QuestionBank> findByNumber(Long questionNumber){
return em.createQuery("select q from QuestionBank q where q.questionNumber = :number",QuestionBank.class)
.setParameter("number",questionNumber)
.getResultList();
}
}

82
src/main/java/com/maveProject/mave/repository/QuestionRepository.java

@ -0,0 +1,82 @@
package com.maveProject.mave.repository;
import com.maveProject.mave.domain.QGroup;
import com.maveProject.mave.domain.QQuestion;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.restController.AnswerApiController;
import com.maveProject.mave.restController.QuestionApiController;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;
import static com.maveProject.mave.domain.QGroup.group;
import static com.maveProject.mave.domain.QQuestion.question;
@Repository
public class QuestionRepository {
private final EntityManager em;
private final JPAQueryFactory queryFactory;
public QuestionRepository(EntityManager em) {
this.em = em;
this.queryFactory = new JPAQueryFactory(em);
}
public Long save(Question question){
em.persist(question);
return question.getId();
}
public Question findById(Long questionId){
Question question = em.find(Question.class, questionId);
return question;
}
public List<Question> findByNumber(Long questionNumber){
return em.createQuery("select q from Question q where q.questionNumber = :questionNumber",
Question.class)
.setParameter("questionNumber", questionNumber)
.getResultList();
}
// public Optional<List<Question>> findByNumberForGroup(Long groupId, Long questionNumber){
// return Optional.ofNullable(em.createQuery("select q from Question q join q.group g " +
// "where q.questionNumber = :questionNumber and g.id = :groupId",Question.class)
// .setParameter("questionNumber",questionNumber)
// .setParameter("groupId",groupId)
// .getResultList());
// }
public List<Question> findByNumberForGroupQuery(Long groupId, Long questionNumber){
return queryFactory
.selectFrom(question)
.join(question.group,group).fetchJoin()
.where( group.id.eq(groupId),
question.questionNumber.eq(questionNumber)
)
.fetch();
}
public List<QuestionApiController.GiveAllQuestionResponse> findAllQuestionForGroup(Long groupId, Long questionNumber) {
return queryFactory
.select(Projections.constructor(QuestionApiController.GiveAllQuestionResponse.class,
question.questionContent))
.from(question)
.join(question.group,group)
.where(group.id.eq(groupId),
question.questionNumber.loe(questionNumber))
.orderBy(question.questionNumber.desc())
.fetch();
}
}

98
src/main/java/com/maveProject/mave/restController/AnswerApiController.java

@ -0,0 +1,98 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.domain.Answer;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Member;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.service.AnswerService;
import com.maveProject.mave.service.GroupService;
import com.maveProject.mave.service.MemberService;
import com.maveProject.mave.service.QuestionService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class AnswerApiController {
private final QuestionService questionService;
private final AnswerService answerService;
private final GroupService groupService;
private final MemberService memberService;
/**
* 어떤 그룹의 어떤 멤버가 어떤 질문에 대한 답을 했는지 등록합니다.
*/
@PostMapping("/api/answer/{questionNumber}")
public RegistAnswerResponse registAnswer(@PathVariable(value = "questionNumber") Long questionNumber,
@RequestBody RegistAnswerRequest request){
Member member = memberService.findMemberByName(request.getUserId());
Group group = groupService.findGroup(request.getGroupId());
Question question = questionService.findQuestion(group,questionNumber);
Answer answer = new Answer(request.getAnswer());
answerService.createAnswer(member,group,question,answer);
groupService.minusCount(group);
Boolean state = groupService.compareState(group);
return new RegistAnswerResponse(state ,"답변이 등록되었습니다.");
}
/**
* 모두 답변을 했을 , 해당 질문에 대한 답변을 List에 담아 반환합니다.
*/
@PostMapping("/api/allAnswer/{questionNumber}")
public List<AllAnswerResponse> allAnswer(@PathVariable(value = "questionNumber") Long questionNumber,
@RequestBody AllAnswerRequest request){
List<AllAnswerResponse> result = answerService.findAllAnswer(request.getGroupId(), questionNumber);
return result;
}
//==== DTO =====//
@Data
static class RegistAnswerRequest{
private String userId;
private Long groupId;
private String answer;
}
@Data
static class RegistAnswerResponse{
private String answer;
private Boolean isFinish;
public RegistAnswerResponse(Boolean isFinish, String answer) {
this.isFinish = isFinish;
this.answer = answer;
}
}
@Data
static class AllAnswerRequest{
private Long groupId;
}
@Data
public static class AllAnswerResponse{
private String userId;
private String answerContent;
public AllAnswerResponse(String userId, String answerContent) {
this.userId = userId;
this.answerContent = answerContent;
}
}
}

97
src/main/java/com/maveProject/mave/restController/CustomApiController.java

@ -0,0 +1,97 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.domain.CustomQuestion;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.repository.CustomRepository;
import com.maveProject.mave.service.GroupService;
import com.maveProject.mave.service.QuestionService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class CustomApiController {
private final CustomRepository customRepository;
private final GroupService groupService;
private final QuestionService questionService;
@PostMapping("/api/custom")
public createCustomQuestionResponse createCustomQuestion(@RequestBody createCustomQuestionRequest request){
CustomQuestion customQuestion = new CustomQuestion(request.getQuestionContent(), request.getDiaryDate(),request.getGroupId());
customRepository.save(customQuestion);
return new createCustomQuestionResponse("questionNumber");
}
@PostMapping("/api/custom/search")
public checkCustomResponse checkCustom(@RequestBody checkCustomRequest request){
String customQuestion = customRepository.findCustomQuestion(request.groupId, request.diaryDate);
return new checkCustomResponse(customQuestion);
}
@PostMapping("/api/custom/{questionNumber}")
public UseCustomQuestionResponse useCustomQuestion(@PathVariable(value = "questionNumber") Long questionNumber,
@RequestBody UseCustomQuestionRequest request){
String customQuestion = customRepository.findCustomQuestion(request.groupId, questionNumber);
Group group = groupService.findGroup(request.groupId);
Question todayQuestion = new Question(group, customQuestion, questionNumber + 1);
questionService.createQuestion(todayQuestion);
groupService.setCompleteDate(group,questionNumber);
groupService.setCount(group);
groupService.changeIsFinish(group);
return new UseCustomQuestionResponse(customQuestion);
}
@Data
static class createCustomQuestionRequest{
private Long groupId;
private Long diaryDate;
private String questionContent;
}
@Data
static class createCustomQuestionResponse{
private String questionContent;
public createCustomQuestionResponse(String questionContent) {
this.questionContent = questionContent;
}
}
@Data
static class UseCustomQuestionRequest{
private Long groupId;
}
@Data
static class UseCustomQuestionResponse{
private String questionContent;
public UseCustomQuestionResponse(String questionContent) {
this.questionContent = questionContent;
}
}
@Data
static class checkCustomRequest{
private Long groupId;
private Long diaryDate;
}
@Data
static class checkCustomResponse{
private String questionContent;
public checkCustomResponse(String questionContent) {
this.questionContent = questionContent;
}
}
}

73
src/main/java/com/maveProject/mave/restController/FileApiController.java

@ -0,0 +1,73 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.dto.FileDto;
import com.maveProject.mave.service.FileService;
import com.maveProject.mave.util.MD5Generator;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RequiredArgsConstructor
@RestController
public class FileApiController {
private final FileService fileService;
@PostMapping("/api/file")
public void write(@RequestParam("file") MultipartFile files) {
try {
if (files.isEmpty()) {
return;
}
String originalFilename = files.getOriginalFilename();
// 파일 이름 가져오기
String filename = new MD5Generator(originalFilename).toString(); // 파일 이름 기반 hash값 생성?
String savePath = System.getProperty("user.dir") + "\\mave-photoBook"; // mave-photoBook 폴더에 파일 저장
/* mave-photoBook 폴더가 없다면 생성 */
if (!new File(savePath).exists()) {
try {
new File(savePath).mkdir();
} catch (Exception e) {
e.printStackTrace();
}
}
String filePath = savePath + "\\" + filename; // 파일 저장될 위치
files.transferTo(new File(filePath)); // files로 넘어온 파일을 filePath 위치에 넘긴다.
FileDto fileDto = new FileDto(); // 넘어온 file을 dto로 바꿔주는 작업
fileDto.setOrigFilename(originalFilename);
fileDto.setFilename(filename);
fileDto.setFilePath(filePath);
Long fileId = fileService.saveFile(fileDto); // fileDto를 DB에 저장한다.
} catch (Exception e) {
e.printStackTrace();
}
}
@GetMapping("/api/download/{fileId}")
public ResponseEntity<InputStreamResource> fileDownload(@PathVariable("fileId") Long fileId) throws IOException {
FileDto fileDto = fileService.getFile(fileId); // DB에 저장된 정보 가져온다.
Path path = Paths.get(fileDto.getFilePath()); // 가져온 정보에 저장된 path 가져온다.
InputStreamResource resource = new InputStreamResource(Files.newInputStream(path));
return ResponseEntity.ok()
.contentType(MediaType.MULTIPART_FORM_DATA)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileDto.getOrigFilename() + "\"")
.body(resource);
}
}

137
src/main/java/com/maveProject/mave/restController/GroupApiController.java

@ -0,0 +1,137 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.domain.Flower;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.IsFinish;
import com.maveProject.mave.domain.Member;
import com.maveProject.mave.service.GroupService;
import com.maveProject.mave.service.MemberService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Stream;
@RequiredArgsConstructor
@RestController
public class GroupApiController {
private final MemberService memberService;
private final GroupService groupService;
/**
* 그룹을 생성한 DB에 저장하는 그룹 생성 api 입니다.
*/
@PostMapping("/api/groups")
public CreateGroupResponse createGroup(@RequestBody CreateGroupRequest request) {
LocalDateTime questionTime = LocalDateTime.parse(request.getQuestionTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Group group = new Group(request.getGroupName(),questionTime,IsFinish.NO,Flower.ZERO,1l,1l); // 요청이 들어온 이름으로 그룹 생성
groupService.saveGroup(group); // DB에 그룹 저장
Member member = memberService.findMemberByName(request.getUserId()); // 그룹에 들어갈 멤버 찾아오기
Long groupId = memberService.joinGroup(member, group); // 그룹 가입
return new CreateGroupResponse(groupId,group.getDiaryDate());
}
/**
* 기존에 있는 그룹에 가입하는 api 입니다.
*/
@PostMapping("/api/groups/{groupId}")
public JoinGroupResponse joinGroup(@PathVariable(value = "groupId") Long groupId,
@RequestBody JoinGroupRequest request) {
Member member = memberService.findMemberByName(request.getUserId()); // 그룹에 들어갈 멤버 찾아오기
Group group = groupService.findGroup(groupId); // 들어갈 그룹 찾아오기
Long joinGroupId = memberService.joinGroup(member, group); // 그룹 가입
groupService.setCount(group);
groupService.changeIsFinish(group);
return new JoinGroupResponse(joinGroupId);
}
/**
* 자신이 속한 그룹을 찾는 api 입니다.
*/
@PostMapping("/api/findGroups")
public FindGroupResponse findGroup(@RequestBody JoinGroupRequest request) {
Member member = memberService.findMemberByName(request.getUserId());
Group group = groupService.findGroup(member.getGroup().getId());
Boolean isDateChanged = groupService.compareDate(group);
group.flowerStatusCheck();
String format = group.getQuestionTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new FindGroupResponse(group.getId(),group.getGroupName(),group.getFlowerCount(),group.getFlower().flowerStatus(),format,group.getDiaryDate(),group.getCompleteDate(),isDateChanged);
}
//====== DTO ======//
@Data
static class JoinGroupRequest {
private String userId;
}
@Data
static class JoinGroupResponse {
private Long groupId;
public JoinGroupResponse(Long groupId) {
this.groupId = groupId;
}
}
@Data
static class CreateGroupRequest {
private String userId;
private String groupName;
private String questionTime;
}
@Data
static class CreateGroupResponse {
private Long groupId;
private Long diaryDate;
public CreateGroupResponse(Long groupId, Long diaryDate) {
this.groupId = groupId;
this.diaryDate = diaryDate;
}
}
@Data
static class FindGroupResponse{
private Long groupId;
private String groupName;
private int flowerCount;
private int flowerStatus;
private String questionTime;
private Long diaryDate;
private Long completeDate;
private Boolean isDateChanged;
public FindGroupResponse(Long groupId, String groupName, int flowerCount, int flowerStatus, String questionTime, Long diaryDate,Long completeDate, Boolean isDateChanged) {
this.groupId = groupId;
this.groupName = groupName;
this.flowerCount = flowerCount;
this.flowerStatus = flowerStatus;
this.questionTime = questionTime;
this.diaryDate = diaryDate;
this.completeDate = completeDate;
this.isDateChanged = isDateChanged;
}
}
}

76
src/main/java/com/maveProject/mave/restController/MemberApiController.java

@ -0,0 +1,76 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.domain.Member;
import com.maveProject.mave.service.MemberService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class MemberApiController {
private final MemberService memberService;
/**
* 회원가입시 들어오는 정보를 DB에 저장하는 회원가입 api 입니다.
*/
@PostMapping("/api/members")
public JoinMemberResponse saveMember(@RequestBody JoinMemberRequest request) {
Member member = new Member(request.getUserId(),request.getPassword(),request.getUserName());
// 안드로이드에서 넘어온 회원 정보를 이용해 객체 생성
member.changePasswordToHash();
// 비밀번호를 해쉬코드로 변환한다.
Long joinedMemberId = memberService.joinMember(member);
// DB에 비밀번호를 저장한다.
return new JoinMemberResponse(joinedMemberId);
}
@PostMapping("/api/members/login")
public LoginResponse loginCheck(@RequestBody LoginRequest request){
Member findMember = memberService.findMemberByName(request.getUserId());
// DB에서 로그인을 시도하는 멤버를 가져온다
Boolean isOk = memberService.passwordCheck(Integer.toString(request.getPassword().hashCode()), findMember.getPassword());
// 요청으로 들어온 비밀번호와 DB에 있는 비밀번호가 일치하는지 확인한다.
return new LoginResponse(isOk);
}
//====== DTO ======//
@Data
static class JoinMemberRequest {
private String userId; // 어플에서 유저가 사용하는 ID값
private String password; // 어플에서 유저가 사용하는 비밀번호값
private String userName; // 어플에서 유저가 사용하는 이름값
}
@Data
static class JoinMemberResponse {
private Long userId; // DB에 저장된 user의 PK값
public JoinMemberResponse(Long userId) {
this.userId = userId;
}
}
@Data
static class LoginRequest {
private String userId;
private String password;
}
@Data
static class LoginResponse {
private Boolean isLoginOk;
public LoginResponse(Boolean isLoginOk) {
this.isLoginOk = isLoginOk;
}
}
}

86
src/main/java/com/maveProject/mave/restController/QuestionApiController.java

@ -0,0 +1,86 @@
package com.maveProject.mave.restController;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.domain.QuestionBank;
import com.maveProject.mave.service.GroupService;
import com.maveProject.mave.service.QuestionBankService;
import com.maveProject.mave.service.QuestionService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class QuestionApiController {
private final QuestionBankService questionBankService;
private final QuestionService questionService;
private final GroupService groupService;
/**
* 오늘의 질문을 보내줍니다.
*/
@PostMapping("/api/question/{questionNumber}")
public GiveQuestionResponse giveQuestion(
@PathVariable(value = "questionNumber")
Long questionNumber,
@RequestBody
GiveQuestionRequest request) {
QuestionBank question = questionBankService.findQuestion(questionNumber);
Group group = groupService.findGroup(request.groupId);
Question todayQuestion = new Question(group, question.getContent(), question.getQuestionNumber());
questionService.createQuestion(todayQuestion);
groupService.setCompleteDate(group,questionNumber);
groupService.setCount(group);
groupService.changeIsFinish(group);
return new GiveQuestionResponse(question.getContent());
}
/**
* 지난 질문들을 List에 담아 반환해줍니다.
*/
@PostMapping("/api/allQuestion/{questionNumber}")
public List<GiveAllQuestionResponse> giveAllQuestion(@PathVariable(value = "questionNumber") Long questionNumber,
@RequestBody GiveAllQuestionRequest request) {
Group group = groupService.findGroup(request.groupId);
List<GiveAllQuestionResponse> result = questionService.findAllQuestion(group, questionNumber);
return result;
}
//===== DTO =====/
@Data
static class GiveQuestionRequest {
private Long groupId;
}
@Data
static class GiveQuestionResponse {
private String questionContent;
public GiveQuestionResponse(String questionContent) {
this.questionContent = questionContent;
}
}
@Data
static class GiveAllQuestionRequest {
private Long groupId;
}
@Data
public static class GiveAllQuestionResponse {
private String questionContent;
public GiveAllQuestionResponse(String questionContent) {
this.questionContent = questionContent;
}
}
}

45
src/main/java/com/maveProject/mave/service/AnswerService.java

@ -0,0 +1,45 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.Answer;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Member;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.repository.AnswerRepository;
import com.maveProject.mave.restController.AnswerApiController;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class AnswerService {
private final AnswerRepository answerRepository;
@Transactional
public void createAnswer(Member member, Group group, Question question, Answer answer){
answer.registMember(member);
answer.addAnswer(question);
answer.registGroup(group);
answerRepository.save(answer);
}
public List<AnswerApiController.AllAnswerResponse> findAllAnswer(Long groupId, Long questionNumber){
return answerRepository.findAllAnswerQuery(groupId, questionNumber);
}
}

35
src/main/java/com/maveProject/mave/service/FileService.java

@ -0,0 +1,35 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.File;
import com.maveProject.mave.dto.FileDto;
import com.maveProject.mave.repository.FileRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class FileService {
private final FileRepository fileRepository;
@Transactional
public Long saveFile(FileDto fileDto){
return fileRepository.save(fileDto.toEntity()).getId();
}
@Transactional
public FileDto getFile(Long id){
File file = fileRepository.findById(id).get();
FileDto fileDto = FileDto.builder()
.id(id)
.origFilename(file.getOrigFilename())
.filename(file.getFilename())
.filePath(file.getFilePath())
.build();
return fileDto;
}
}

61
src/main/java/com/maveProject/mave/service/GroupService.java

@ -0,0 +1,61 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.repository.GroupRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class GroupService {
private final GroupRepository groupRepository;
@Transactional
public Long saveGroup(Group group){
return groupRepository.save(group);
}
@Transactional
public Group findGroup(Long groupId){
return groupRepository.findById(groupId);
}
@Transactional
public int setCount(Group group){
return group.setCount();
}
@Transactional
public void setCompleteDate(Group group,Long questionNumber){
group.setCompleteDate(questionNumber);
}
@Transactional
public void changeIsFinish(Group group){
group.changeIsFinish();
}
@Transactional
public void minusCount(Group group){
group.minusCount();
}
@Transactional
public Boolean compareState(Group group){
return group.compareState();
}
@Transactional
public Boolean compareDate(Group group){
Long prevDate = group.getDiaryDate();
Long changedDate = group.changeDiaryDate();
// Long changedDate = 3l; 테스트용!
return group.isDateChanged(prevDate, changedDate);
}
}

57
src/main/java/com/maveProject/mave/service/MemberService.java

@ -0,0 +1,57 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Member;
import com.maveProject.mave.repository.GroupRepository;
import com.maveProject.mave.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class MemberService {
private final MemberRepository memberRepository;
private final GroupRepository groupRepository;
@Transactional
public Long joinMember(Member member){
return memberRepository.save(member);
}
@Transactional
public Long joinGroup(Member member,Group group){
member.SetGroup(group);
return member.getGroup().getId();
}
public Member findMember(Long memberId){
return memberRepository.findById(memberId);
}
public Member findMemberByName(String userId){
return memberRepository.findByUserId(userId).get(0);
}
public Boolean passwordCheck(String userPassword, String inDbPassword){
if(userPassword.equals(inDbPassword)){
return true;
}else {
return false;
}
}
}

21
src/main/java/com/maveProject/mave/service/QuestionBankService.java

@ -0,0 +1,21 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.QuestionBank;
import com.maveProject.mave.repository.QuestionBankRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class QuestionBankService {
private final QuestionBankRepository questionBankRepository;
public QuestionBank findQuestion(Long questionNumber){
return questionBankRepository.findByNumber(questionNumber).get(0);
}
}

39
src/main/java/com/maveProject/mave/service/QuestionService.java

@ -0,0 +1,39 @@
package com.maveProject.mave.service;
import com.maveProject.mave.domain.Group;
import com.maveProject.mave.domain.Question;
import com.maveProject.mave.repository.QuestionRepository;
import com.maveProject.mave.restController.QuestionApiController;
import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class QuestionService {
private final QuestionRepository questionRepository;
@Transactional
public Long createQuestion(Question question) {
return questionRepository.save(question);
}
public Question findQuestion(Group group, Long questionNumber) {
return questionRepository.findByNumberForGroupQuery(group.getId(), questionNumber).get(0);
}
public List<QuestionApiController.GiveAllQuestionResponse> findAllQuestion(Group group, Long questionNumber) {
return questionRepository.findAllQuestionForGroup(group.getId(), questionNumber);
}
}

30
src/main/java/com/maveProject/mave/util/MD5Generator.java

@ -0,0 +1,30 @@
package com.maveProject.mave.util;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
public class MD5Generator {
private String result;
public MD5Generator(String input) throws UnsupportedEncodingException, NoSuchAlgorithmException {
LocalDateTime now = LocalDateTime.now();
String fileName = input + now.toString();
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(fileName.getBytes(StandardCharsets.UTF_8));
byte[] md5Hash = md5.digest();
StringBuilder hexMD5Hash = new StringBuilder();
for (byte b : md5Hash) {
String hexString = String.format("%02x", b);
hexMD5Hash.append(hexString);
}
result = hexMD5Hash.toString();
}
public String toString(){
return result;
}
}

17
src/main/resources/application.properties

@ -0,0 +1,17 @@
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.profiles.active=local
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.default_batch_fetch_size = 500
logging.level.org.hibernate.sql=debug

22
src/main/resources/templates/home.html

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>게시판 - 글쓰기</title>
</head>
<body>
<form action="/post" method="post" enctype="multipart/form-data">
<label for="inputFile" class="col-sm-2 col-form-label"><strong>첨부 파일</strong></label>
<div class="custom-file" id="inputFile">
<input name="file" type="file" class="custom-file-input" id="customFile">
<label class="custom-file-label" for="customFile">파일을 선택해 주세요.</label>
</div>
<div class="row">
<div class="col-auto mr-auto"></div>
<div class="col-auto">
<input class="btn btn-primary" type="submit" role="button" value="글쓰기">
</div>
</div>
</form>
</body>
</html>

14
src/main/resources/templates/result.html

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>결과</title>
</head>
<body>
<h1>목록</h1>
<li>
<span th:text="${file.filename}"></span>
<a href="#" th:href="${'download/'+fileId}">[download]</a>
</li>

13
src/test/java/com/maveProject/mave/MaveApplicationTests.java

@ -0,0 +1,13 @@
package com.maveProject.mave;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MaveApplicationTests {
@Test
void contextLoads() {
}
}

44
src/test/java/com/maveProject/mave/Testststst.java

@ -0,0 +1,44 @@
package com.maveProject.mave;
import com.maveProject.mave.domain.Flower;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
public class Testststst {
@Test
void teststst(){
LocalTime localTime = LocalTime.of(23, 10);
System.out.println("localTime = " + localTime);
LocalTime now = LocalTime.now();
System.out.println("now = " + now);
boolean before = localTime.isBefore(now);
System.out.println("before = " + before);
}
@Test
void testststDSFDSF(){
LocalDate startDate = LocalDate.of(
2021,
5,
31);
LocalDate endDate = LocalDate.of(
2021,
6,
1);
long between = ChronoUnit.DAYS.between(startDate, endDate);
System.out.println("between = " + between);
}
}

27
src/test/java/com/maveProject/mave/controller/FileControllerTest.java

@ -0,0 +1,27 @@
package com.maveProject.mave.controller;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class FileControllerTest {
@Test
public void localDateTimeTest() throws InterruptedException {
LocalDateTime now = LocalDateTime.now();
//given
Thread.sleep(100);
LocalDateTime now1 = LocalDateTime.now();
System.out.println("now = " + now);
System.out.println("now1 = " + now1);
//when
//then
}
}

17
src/test/resources/application.properties

@ -0,0 +1,17 @@
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.profiles.active=test
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.default_batch_fetch_size = 500
logging.level.org.hibernate.sql=debug
Loading…
Cancel
Save