> 프로젝트 생성(교수 담당) / 조회(교수Id로)
> 팀 생성(학생 담당) / 조회(교수는 프로젝트id로, 학생은 학생Id로)
> 학생이 팀에 들어온 경우 프로젝트, 팀 인원 추가 + teamMembers table에 추가
교수
(1) 프로젝트 생성 (2) professorId로 모든 프로젝트 조회 (3) professorId와 projectId로 모든 팀 조회
학생
(1) 팀 생성 (2) studentId로 모든 팀 조회 (3) 팀 멤버 추가
📢 예외처리와 Response code 출력할 것
>사용자의 HttpRequest에 대한 응답 데이터를 상속받은 클래스로 HttpStatus
, HttpHeaders
, HttpBody
포함해 response로 반환
>사용법
java/com.example.graduation/controller/CalendarController
//Response로 반환할 데이터 => status, message, data. 이때 data는 Object형식으로 모든 결과값(Entity)을 그대로 반환해 보여줌
private class ResponseData {
private int status;
private String message;
private Object data;
public ResponseData(int status, String message, Object data) {
this.status = status;
this.message = message;
this.data = data;
}
public int getStatus() {
return status;
}
public String getMessage() {
return message;
}
public Object getData() {
return data;
}
}
@PostMapping("/calendars/minutes")
public ResponseEntity<ResponseData> createMinutes(@RequestBody MinutesForm form) {
//1. 원하는 정보가 모두 들어오지 않았을 경우 오류 발생
boolean formcheck = minutesService.checkForm(form);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
//2. teamId가 존재하는지 + 해당 team member에 사용자가 존재하는지
boolean teamcheck = dashboardService.checkTeam(form.getTeamId());
if (teamcheck == false) {
throw new TeamNotFoundException("Team Not Found");
}
boolean teamMembercheck = dashboardService.checkTeamMember(form.getTeamId(), form.getUserId());
if (teamMembercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
//3. DB에 해당 date의 회의록이 존재하는지 여부에 따라 다르게 처리
boolean check = minutesService.checkDate(form.getDate()); //check==true일 경우 DB에 해당 date 존재
if (check == false) { //Minutes DB에 해당 date 존재하지 않을 경우, 해당 정보로 minutes 생성
Minutes target = minutesService.create(form);
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", target);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
else { //Minutes DB에 해당 date 존재할 경우, 기존의 minutes 보여줌
Minutes original = minutesService.getExistingMinutes(form.getDate());
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", original);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
}
사용자가 존재하지 않는 프로젝트에서 팀을 생성할 경우 404 오류(Not Found)
가 발생해야하는데 5xx 오류(서버오류)
발생하므로 예외처리 필요
📢 5xx 오류는 절대 반환하지 않도록 설계할 것
⚡️ 구현사항에 맞게 프로젝트, 팀 생성 / 조회 + teamMember 테이블 추가
⚡️ 이전 게시글의 회의록 생성/조회/수정/삭제도 예외처리 필요해 코드 수정
⚡️ 모든 코드 ResponseEntity로 반환 완료
(추후업데이트)
Controller
CalendarController
DTO
MembersForm / MinutesForm / ProjectsForm / TeamMembersForm / TeamsForm
Entity
Members / Minutes / Projects / TeamMembers / Teams
Exception
AlreadyExistException / DateNotFoundException / FormatBadRequestException / MemberNotFoundException / ProjectNotFoundException / TeamNotFoundException /
Repository
MembersRepository / MinutesRepository / ProjectsRepository / TeamMembersRepository / TeamsRepository
Service
DashboardService
MinutesService는 삭제 예정
java/com.example.graduation/controller/CalendarController
package com.example.graduation.controller;
import com.example.graduation.Exception.*;
import com.example.graduation.dto.*;
import com.example.graduation.entity.*;
import com.example.graduation.service.DashboardService;
import com.example.graduation.service.MinutesService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j //log
@RequiredArgsConstructor
public class CalendarController {
// private final MinutesService minutesService;
private final DashboardService dashboardService;
private class ResponseData {
private int status;
private String message;
private Object data;
public ResponseData(int status, String message, Object data) {
this.status = status;
this.message = message;
this.data = data;
}
public int getStatus() {
return status;
}
public String getMessage() {
return message;
}
public Object getData() {
return data;
}
}
//회의록에서는 팀멤버임을 확인했다고 가정한 후의 API: team member임을 확인하는 과정 X
//1: Calendar Minutes
//1-1. 회의록 생성: 해당 날짜의 회의록이 존재할 경우 해당 회의록 보여주기
@PostMapping("/calendars/minutes")
public ResponseEntity<ResponseData> createMinutes(@RequestBody MinutesForm form) {
//1. 원하는 정보가 모두 들어오지 않았을 경우 오류 발생
boolean formcheck = dashboardService.checkMinutesForm(form);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
//2. teamId가 존재하는지 + 해당 team member에 사용자가 존재하는지
boolean teamcheck = dashboardService.checkTeam(form.getTeamId());
if (teamcheck == false) {
throw new TeamNotFoundException("Team Not Found");
}
boolean teamMembercheck = dashboardService.checkTeamMember(form.getTeamId(), form.getUserId());
if (teamMembercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
//3. DB에 해당 date의 회의록이 존재하는지 여부에 따라 다르게 처리
boolean check = dashboardService.checkDate(form.getDate()); //check==true일 경우 DB에 해당 date 존재
if (check == false) { //Minutes DB에 해당 date 존재하지 않을 경우, 해당 정보로 minutes 생성
Minutes target = dashboardService.createMinutes(form);
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", target);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
else { //Minutes DB에 해당 date 존재할 경우, 기존의 minutes 보여줌
Minutes original = dashboardService.getExistingMinutes(form.getDate());
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", original);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
}
//1-2(1). 회의록 조회(전체)
//조회할 것이 없을 경우 null 출력
@GetMapping("/calendars/minutes/all/{teamId}/{userId}")
public ResponseEntity<ResponseData> getAllMinutes(@PathVariable Long teamId, @PathVariable Long userId) {
//userId가 해당팀의 멤버인지 확인
//전체 조회
List<Minutes> minutesList = dashboardService.watchAll(teamId);
if (minutesList.isEmpty()) {
return null;
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", minutesList);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//1-2(2). 회의록 부분 조회(특정 년도, 월)
//조회할 것이 없을 경우 null 출력
@GetMapping("/calendars/minutes/all/{teamId}/{yearMonth}/{userId}")
public ResponseEntity<ResponseData> getAllMinutes(@PathVariable Long teamId,@PathVariable String yearMonth, @PathVariable Long userId) {
//userId가 해당팀의 멤버인지 확인
// 부분 조회
List<Minutes> minutesList = dashboardService.watchDates(teamId, yearMonth);
if (minutesList == null) {
return null;
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", minutesList);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//1-2(3). 회의록 조회(세부)
//조회할 것이 없을 경우 null 출력
@GetMapping("/calendars/minutes/{teamId}/{date}/{userId}")
public ResponseEntity<ResponseData> getMinutes(@PathVariable Long teamId, @PathVariable String date, @PathVariable Long userId) {
//userId가 해당팀의 멤버인지 확인
//세부 조회
Minutes minutes = dashboardService.watchDate(date);
if (minutes == null) {
return null;
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", minutes);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//1-3. 회의록 수정 => 수정할때
//해당 날짜가 존재하지 않을 경우 오류 발생
@PatchMapping("/calendars/minutes")
public ResponseEntity<ResponseData> editMinutes(@RequestBody MinutesForm form) {
//수정이므로 아래 과정은 없어도 될듯
// //1. 원하는 정보가 모두 들어오지 않았을 경우 오류 발생
// boolean formcheck = dashboardService.checkMinutesForm(form);
// if (formcheck == false) {
// throw new FormatBadRequestException("Fill In All");
// }
//1. teamId가 존재하는지 + 해당 team member에 사용자가 존재하는지
boolean teamcheck = dashboardService.checkTeam(form.getTeamId());
if (teamcheck == false) {
throw new TeamNotFoundException("Team Not Found");
}
boolean teamMembercheck = dashboardService.checkTeamMember(form.getTeamId(), form.getUserId());
if (teamMembercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
//2. 그에 맞게 처리
boolean check = dashboardService.checkDate(form.getDate()); //check==true일 경우 DB에 해당 date 존재
if (check != true) {
throw new DateNotFoundException("Date Not Found");
}
MinutesForm minutes = dashboardService.editMinutes(form.getDate(), form);
//3. 수정한 회의록에 not null이 존재할 경우 오류 발생
boolean formcheck = dashboardService.checkMinutesForm(minutes);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", minutes);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//1-4. 회의록 삭제
//해당 날짜가 존재하지 않을 경우 오류 발생
@DeleteMapping("/calendars/minutes")
public ResponseEntity<ResponseData> deleteMinutes(@RequestBody MinutesForm form) {
//1. 원하는 정보가 모두 들어오지 않았을 경우 오류 발생
boolean formcheck = dashboardService.checkMinutesForm(form);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
//2. teamId가 존재하는지 + 해당 team member에 사용자가 존재하는지
boolean teamcheck = dashboardService.checkTeam(form.getTeamId());
if (teamcheck == false) {
throw new TeamNotFoundException("Team Not Found");
}
boolean teamMembercheck = dashboardService.checkTeamMember(form.getTeamId(), form.getUserId());
if (teamMembercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
//3. 처리
boolean check = dashboardService.checkDate(form.getDate()); //check==true일 경우 DB에 해당 date 존재
if (check != true) {
throw new DateNotFoundException(String.format("Date[%s] Not Found", form.getDate()));
}
dashboardService.deleteMinutes(form.getDate());
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", null);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//2: dashboard
//2-1. project 생성
@PostMapping("/dashboard/projects")
public ResponseEntity<ResponseData> createProjects(@RequestBody ProjectsForm form) {
//1. 원하는 정보가 모두 들어오지 않았을 경우 오류 발생
boolean formcheck = dashboardService.checkProjectsForm(form);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
//2. member table에 해당 id가 있는지 확인 + 교수가 맞는지 확인
boolean membercheck = dashboardService.checkMember(form.getProfessorId());
if (membercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
String professorcheck = dashboardService.checkRole(form.getProfessorId());
if (!professorcheck.equals("professor")) { //자바에서 문자열의 경우 ==이 아니라 equals 사용
throw new MemberNotFoundException("Not Professor");
}
//3. 동일한 projectName 존재 확인
boolean check = dashboardService.checkProjectName(form.getProjectName());
//(1)동일한 projectName이 존재하지 않을 경우, project 생성
if (check == false) {
Projects projects = dashboardService.createProjects(form);
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", projects);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//(2).Projects DB에 해당 projectName 존재할 경우, 기존의 Projects 보여줌
else {
Projects original = dashboardService.getExistingProjects(form.getProjectName());
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", original);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
}
//2-2. project 조회: 교수별로 => Dashboard:교수 기본 화면
@GetMapping("/dashboard/projects/{professorId}")
public ResponseEntity<ResponseData> watchProjects(@PathVariable Long professorId) {
//1. member table에 해당 id가 있는지 확인 + 교수가 맞는지 확인
boolean membercheck = dashboardService.checkMember(professorId);
if (membercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
String professorcheck = dashboardService.checkRole(professorId);
if (!professorcheck.equals("professor")) {
throw new MemberNotFoundException("Not Professor");
}
//2. 조회
List<Projects> projectsList = dashboardService.watchProjects(professorId);
if (projectsList.isEmpty()) {
return null;
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", projectsList);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//2-3. team 생성 => 학생. Dashboard에서 생성할 것
@PostMapping("/dashboard/teams")
public ResponseEntity<ResponseData> createTeams(@RequestBody TeamsForm form, @RequestParam Long userId) throws AlreadyExistException {
//1. Team form의 not null이 모두 들어왔는지 확인
boolean formcheck = dashboardService.checkTeamsForm(form);
if (formcheck == false) {
throw new FormatBadRequestException("Fill In All");
}
//2. Members 테이블에 존재하는지 + role이 학생인지 확인
boolean membercheck = dashboardService.checkMember(userId);
if (membercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
String professorcheck = dashboardService.checkRole(userId);
if (!professorcheck.equals("student")) {
throw new MemberNotFoundException("Not Student");
}
//3. 해당 projectId가 project table에 존재하는지 확인. 없으면 오류 발생 => ProjectNotFoundException
boolean check = dashboardService.checkProjectId(form.getProjectId()); //check==true일 경우 DB에 해당 date 존재
if (check == false) {
throw new ProjectNotFoundException("Project Not Found");
}
//4. teamRepository에서 teamName이 겹치지 않는지 확인
boolean checkTeamName = dashboardService.checkTeamName(form.getTeamName());
if (checkTeamName == true) {
throw new AlreadyExistException("Team Already Exist");
}
//1. 팀생성
Teams teams = dashboardService.createTeams(form);
//2. 팀멤버 테이블 추가
dashboardService.createTeamsMembers(teams.getTeamId(), userId);
//3. 프로젝트와 팀 count 1씩
Teams target = dashboardService.countNums(teams.getTeamId(), teams.getProjectId());
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", target);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//2-5. 1) 학생이 보낸 URL(team으로 직접 들어올 경우) => team_number 1 증가 + project_number 1 증가
@PatchMapping("/dashboard/{projectId}/{teamId}/{userId}")
public ResponseEntity<ResponseData> countNumbers(@PathVariable Long projectId, @PathVariable Long teamId, @PathVariable Long userId) {
//1. Members 테이블에 존재하는지 + role이 학생인지 확인
boolean membercheck = dashboardService.checkMember(userId);
if (membercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
String professorcheck = dashboardService.checkRole(userId);
if (!professorcheck.equals("student")) {
throw new MemberNotFoundException("Not Student");
}
//2. 해당 projectId가 project table에 존재하는지 확인. 없으면 오류 발생 => ProjectNotFoundException
boolean checkProject = dashboardService.checkProjectId(projectId); //check==true일 경우 DB에 해당 date 존재
if (checkProject == false) {
throw new ProjectNotFoundException("Project Not Found");
}
//3. 해당 team이 존재하는지
boolean checkTeam = dashboardService.checkTeam(teamId);
if (checkTeam == false) {
throw new TeamNotFoundException("Team Not Found");
}
//4. 이미 멤버 테이블에 존재하는지 확인
boolean checkMember = dashboardService.checkTeamMember(teamId, userId);
if (checkMember == false) { //팀멤버 테이블에 존재하지 않는경우
//1. 팀멤버 테이블에 추가
dashboardService.createTeamsMembers(teamId, userId);
//2. teamnumber, projectnumber 1씩 증가
Teams target = dashboardService.countNums(teamId, projectId); //team_number 1 증가 + project_number 1 증가
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", target);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
else {
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", null);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
}
//2-4. team 조회: project 별로 모든 팀 조회=> 교수, Dashboard에서 프로젝트 클릭시
@GetMapping("/dashboard/teamsByPro/{professorId}/{projectId}")
public ResponseEntity<ResponseData> watchTeamsByPro(@PathVariable Long professorId, @PathVariable Long projectId) {
//1. 교수인지 권한 확인
boolean membercheck = dashboardService.checkMember(professorId);
if (membercheck == false) {
throw new MemberNotFoundException("Member Not Found");
}
String professorcheck = dashboardService.checkRole(professorId);
if (!professorcheck.equals("professor")) {
throw new MemberNotFoundException("Not Professor");
}
//2. 해당 프로젝트 생성자가 해당 professorId인지 확인
boolean match = dashboardService.matchProfessorAndProject(professorId, projectId);
if (match == false) {
throw new ProjectNotFoundException("Matching Project Not Found");
}
//3. 처리
List<Teams> teamsList = dashboardService.watchTeamsByPro(projectId);
if (teamsList.isEmpty()) {
return null;
}
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", teamsList);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
//2-4. team 조회: 학생Id 별로 해당하는 모든 팀 조회 => 학생 기본 화면
@GetMapping("/dashboard/teamsByStu/{id}")
public ResponseEntity<ResponseData> watchTeamsByStu(@PathVariable Long id) {
//1. 해당 id가 member table에 존재하는지
boolean check = dashboardService.checkMember(id);
if (check == false) {
throw new MemberNotFoundException("Member Not Found");
}
//2. 학생인지 권한 확인
String professorcheck = dashboardService.checkRole(id);
if (!professorcheck.equals("student")) {
throw new MemberNotFoundException("Not Professor");
}
//3. 처리
List<Teams> teamsList = dashboardService.watchTeamsByStu(id);
ResponseData responseData = new ResponseData(HttpStatus.OK.value(), "Success", teamsList);
return new ResponseEntity<>(responseData, HttpStatus.OK);
}
}
Service
Repository
DTO
Domain(=Entity)
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
//thymeleaf
//implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
//UserDto 생성 시 필요
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-web'
//runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//mysql 추가
runtimeOnly ('com.mysql:mysql-connector-j') //mysql8
implementation ('org.springframework.boot:spring-boot-starter-jdbc')
}
tasks.named('test') {
useJUnitPlatform()
}
application.properties
spring.h2.console.enabled=true
spring.jpa.defer-datasource-initialization = true
#mysql connection
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://serverdb.cafcib2vatvt.us-east-1.rds.amazonaws.com/co_work?autoReconnect=true&setTimezone=Asia/Seoul
spring.datasource.username=admin
spring.datasource.password=dbsgpp00!
spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.ddl-auto = none
server.port = 80
📢 현재 Members 테이블
프로젝트 생성
⭐️ not null로 설정된 professorId, projectName, semester, projectNumber이 모두 입력되어야함 => 그렇지 않을 경우 오류 발생
⭐️ Members 테이블에서 role이 professor인 Id 사용해야함
DataGrip
교수님이 보는 화면: 해당 professorId가 만든 모든 project 조회
⭐️ PathVariable로 받는 Id의 role은 반드시 professor이어야 함
팀 생성
⭐️ not null로 설정된 projectId와 teamName이 모두 입력되어야 함 => 그렇지 않을 경우 오류 발생
⭐️ RequestParam으로 받는 userId의 role은 반드시 student이어야 함
DataGrip
Projects : projectNumber 1 증가
Teams
TeamMembers
📢 동일한 teamName일 경우 409 오류 발생
URL을 통해 새로운 회원이 들어오는 경우
⭐️ PathVariable로 받은 Project와 Team이 매칭되어야함
⭐️ userId가 해당 팀의 기존 멤버가 아니어야함 => 오류는 발생하지 않음
DataGrip
Projects : projectNumber 1 증가
Teams: 1 증가
TeamMembers: userId 8이 해당 팀에 추가
📢 해당 팀에 이미 존재하는 회원의 경우 아래와 같이 반환하며 projectNumber과 teamNumber 증가 X
교수님이 하나의 프로젝트에 해당하는 모든 팀 보기
⭐️ PathVariable로 professorId와 projectId 입력
⭐️ professorId에 해당하는 사용자가 만든 projectId여야, 즉 본인이 만든 것이 인증되어야 볼 수 있음
DataGrip
📢 professorId와 projectId가 맞지 않는 경우 404 오류 발생
학생이 자신이 속한 모든 팀 보기
⭐️ PathVariable로 id 입력
DataGrip
Teams
TeamMembers
회의록 생성
⭐️ not null인 teamId, userId, date는 반드시 존재해야함
⭐️ userId와 teamId가 매칭되어야함
DataGrip
📢 팀의 해당 날짜에 회의록이 이미 존재할 경우 해당 회의록 반환
DataGrip도 그대로
📢 해당 팀원이 아닌 사용자가 생성할 경우 404 오류 발생
teamId에 존재하는 회의록 모두 조회
DataGrip
teamId에 존재하는 회의록 중 특정 달에 존재하는 회의록만 조회
DataGrip
- React
https://sundries-in-myidea.tistory.com/71
https://dev-novel.tistory.com/117