Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #58

Merged
merged 13 commits into from
Jan 5, 2024
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dependencies {
implementation 'org.apache.httpcomponents:httpclient:4.5.13'
implementation 'org.apache.httpcomponents:httpmime:4.5.13'
implementation 'com.google.code.gson:gson:2.8.9'

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ public ResponseEntity<List<CalendarAndTodoAllByRoleDto>> calendarTodoAll(
return ResponseEntity.ok(calendarService.calendarAndtodoAll(projectId, localDate));
}

}
}
3 changes: 0 additions & 3 deletions src/main/java/mvc/promiseme/calendar/entity/Calendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

import jakarta.persistence.*;
import lombok.*;

import mvc.promiseme.project.entity.Member;
import mvc.promiseme.project.entity.Project;
import mvc.promiseme.project.entity.Role;
import mvc.promiseme.todo.entity.Todo;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import java.util.List;
import java.util.Optional;


public interface CalendarRepository extends JpaRepository<Calendar, Long> {
// @Query("SELECT NEW mvc.promiseme.calendar.dto.CalendarResponseDTO(c.content, c.startDate, c.finishDate, u.nickname) from Calendar c join c.member m join m.users u where c.project = :project")
// List<CalendarResponseDTO> findByProject(Project project);
List<Calendar> findByProjectAndStartDateLessThanEqualAndFinishDateGreaterThanEqual(Project project, LocalDate startDate, LocalDate finishDate);
List<Calendar> findByProjectAndStartDateLessThanEqualAndFinishDateGreaterThanEqual(Project project, LocalDate startDate, LocalDate finishDate);
}
7 changes: 6 additions & 1 deletion src/main/java/mvc/promiseme/common/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ public enum ErrorCode implements EnumModel{
INVALID_User_Password(401, "U002", "비밀번호가 일치하지 않습니다."),

//중복여부 체크
DUPLICATE_USER(400,"D001","중복된 이메일입니다.");
DUPLICATE_USER(400,"D001","중복된 이메일입니다."),

//조회시 발생 가능 예외
RPOJECT_NOT_FOUND(401,"P001","프로젝트를 찾을 수 없습니다."),
CATEGORY_SERVER_ERROR(500,"P002","카테고리 불러오는 것을 실패하였습니다."),
MEMBER_NOT_FOUND(401,"M001","해당하는 멤버를 찾을 수 없습니다."),
CALENDER_NOT_FOUND(401,"C001","해당하는 일정을 찾을 수 없습니다.");

private int status;
private String code;
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/mvc/promiseme/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package mvc.promiseme.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@OpenAPIDefinition(
info = @Info(title = "PromiseMe",
description = "약속해줘 api명세",
version = "v1"))
@RequiredArgsConstructor
@Configuration
public class SwaggerConfig {

@Bean
public GroupedOpenApi PromiseMeAPI() {
String[] paths = {"/**"};

return GroupedOpenApi.builder()
.group("PromiseMe v1")
.pathsToMatch(paths)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package mvc.promiseme.meeting.dto;

import lombok.*;
import org.springframework.web.bind.annotation.RequestParam;
@NoArgsConstructor
@AllArgsConstructor
@Getter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package mvc.promiseme.project.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mvc.promiseme.calendar.dto.CalendarResponseDTO;
import mvc.promiseme.common.exception.ErrorCode;
import mvc.promiseme.common.exception.ErrorResponse;
import mvc.promiseme.project.dto.ProjectRequestDTO;
import mvc.promiseme.project.dto.ProjectResponseDTO;
import mvc.promiseme.project.dto.RecommendMemberRequestDTO;
Expand All @@ -18,24 +26,45 @@

@Slf4j
@RestController
@Tag(name = "Project", description = "프로젝트 API")
@RequiredArgsConstructor
@CrossOrigin(origins ="*", allowedHeaders = "*")
@RequestMapping("/project")
public class ProjectController {
private final ProjectService projectService;
private final RecommendService recommendService;
@GetMapping("/")
public ResponseEntity<List<ProjectResponseDTO>>calendarAll(@RequestParam("userId") Long userId){
@Operation(summary = "전체 프로젝트조회", description = "user가 포함된 모든 프로젝트를 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = ProjectResponseDTO.class))),
@ApiResponse(responseCode = "401", description = "프로젝트를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
public ResponseEntity<List<ProjectResponseDTO>> projectAll(@Parameter(description = "유저ID", required = true) @RequestParam("userId") Long userId){
return ResponseEntity.ok(projectService.projectAll(userId));

}
@GetMapping("/category")
@Operation(summary = "상위 카테고리 조회", description = "현재 존재하는 프로젝트 카테고리중 많은 순으로 6개 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = List.class))),
@ApiResponse(responseCode = "501", description = "존재하는 프로젝트가 없어서 카테고리를 가져올 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
public ResponseEntity<List<String>> categoryRanking(){
// if(projectService.categoryRanking()==null)
// return ResponseEntity.status(ErrorCode.CATEGORY_SERVER_ERROR.getStatus()).body(ErrorCode.CATEGORY_SERVER_ERROR.getMessage());

return ResponseEntity.ok(projectService.categoryRanking());

}

@Operation(summary = "프로젝트 생성", description = "새로운 프로젝트 생성")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = Map.class))),
@ApiResponse(responseCode = "501", description = "프로젝트 생성 중 알 수 없는 에러가 발생하였습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
@PostMapping("/create")
public ResponseEntity<Map<String, Long>> insert(@RequestBody ProjectRequestDTO projectRequestDTO){
Map<String, Long> result = new HashMap<>();
Expand All @@ -44,25 +73,49 @@ public ResponseEntity<Map<String, Long>> insert(@RequestBody ProjectRequestDTO p
result.put("projectId",projectService.insert(projectRequestDTO));
return ResponseEntity.ok(result);
}
@Operation(summary = "프로젝트 진행척도", description = "현재 프로젝트가 얼마나 진행되었는지 퍼센트로 확인할 수 있다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = Map.class))),
@ApiResponse(responseCode = "401", description = "해당 프로젝트를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
@GetMapping("/progress")
public ResponseEntity<Map<String, Integer>> progress(@RequestParam("projectId")Long projectId){
Map<String,Integer> progressResult = new HashMap<>();
progressResult.put("progress", projectService.progress(projectId));
return ResponseEntity.ok(progressResult);
}
@Operation(summary = "프로젝트 디데이", description = "해당하는 프로젝트의 디데이를 계산한다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = Map.class))),
@ApiResponse(responseCode = "401", description = "프로젝트를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
@GetMapping("/dday")
public ResponseEntity <Map<String,Integer>> dday(@RequestParam("projectId") Long projectId){
Map<String,Integer> ddayResult = new HashMap<>();
ddayResult.put("Dday", projectService.dday(projectId));

return ResponseEntity.ok(ddayResult);
}

@Operation(summary = "멤버 추천", description = "입력한 값에 맞는 프로젝트 역할과 할일을 보여준다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = Map.class))),
@ApiResponse(responseCode = "401", description = "프로젝트를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
@PostMapping("/recommend/member")
public ResponseEntity<Map<String,String>> recommendMember(@RequestBody RecommendMemberRequestDTO recommendMemberRequestDTO){
return ResponseEntity.ok(recommendService.recommendMember(recommendMemberRequestDTO));
}

@Operation(summary = "프로젝트 일정 추천", description = "입력한 값에 맞는 프로젝트 역할과 할일을 보여준다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", content = @Content(schema = @Schema(implementation = ProjectResponseDTO.class))),
@ApiResponse(responseCode = "401", description = "프로젝트를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))

})
@PostMapping("/recommend/schedule")
public ResponseEntity<List<Map<String, String>>> recommendSchedule(@RequestBody RecommendScheduleRequestDTO recommendScheduleRequestDTO){
return ResponseEntity.ok(recommendService.recommendSchedule(recommendScheduleRequestDTO));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import mvc.promiseme.users.entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;
import java.util.List;
import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByUsersAndProject(Users users, Project project);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package mvc.promiseme.project.repository;

import mvc.promiseme.project.dto.ProjectResponseDTO;
import mvc.promiseme.project.entity.Member;
import mvc.promiseme.project.entity.Project;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.RequiredArgsConstructor;
import mvc.promiseme.common.exception.ErrorCode;
import mvc.promiseme.common.exception.UserException;
import mvc.promiseme.project.dto.MemberDTO;
import mvc.promiseme.project.dto.MemberRequestDTO;
import mvc.promiseme.project.dto.ProjectRequestDTO;
import mvc.promiseme.project.dto.ProjectResponseDTO;
Expand All @@ -14,15 +13,16 @@
import mvc.promiseme.project.repository.MemberRepository;
import mvc.promiseme.project.repository.ProjectRepository;
import mvc.promiseme.project.repository.RoleRepository;
import mvc.promiseme.todo.dto.TodoRequestDTO;
import mvc.promiseme.todo.entity.Todo;
import mvc.promiseme.todo.repository.TodoRepository;
import mvc.promiseme.users.entity.Users;
import mvc.promiseme.users.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

@Service
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package mvc.promiseme.project.service;

import lombok.RequiredArgsConstructor;
import mvc.promiseme.project.dto.RecommendMemberRequestDTO;
import mvc.promiseme.project.dto.RecommendScheduleRequestDTO;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ public class RecommendServiceImpl implements RecommendService{
private final RoleRepository roleRepository;
@Override
public Map<String, String> recommendMember(RecommendMemberRequestDTO recommendMemberRequestDTO) {
String url = clovaStudioRecommend.getUrl();
String apiKeyClovaStudio = clovaStudioRecommend.getApiKeyClovaStudio();

String requestId = clovaStudioRecommend.getRequestMemberId();

List<Message> messages = new ArrayList<>();

Expand All @@ -52,27 +50,7 @@ public Map<String, String> recommendMember(RecommendMemberRequestDTO recommendMe

Message requestMessage = new Message("user", "나는" + recommendMemberRequestDTO.getCategory() + "프로젝트를 진행할예정입니다. 시작날짜는" + recommendMemberRequestDTO.getStart() + ", 마감날짜는" + recommendMemberRequestDTO.getDeadline() + "입니다. 이때 필요한 팀의 구성원 역할을 알려주세요. 다른 말 필요없이\n\"역할\" : \"역할이 해야할일\"\n로만 대답해주세요. 다른 말 없이 역할과 역할이 해야할일만 작성해주세요.");
messages.add(requestMessage);

HttpHeaders headers = new HttpHeaders();
headers.set("X-NCP-CLOVASTUDIO-API-KEY", apiKeyClovaStudio);
headers.set("X-NCP-APIGW-API-KEY", clovaStudioRecommend.getApiGateWayKey());
headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", clovaStudioRecommend.getRequestMemberId());
headers.set("Content-Type", "application/json");

Map<String, Object> requestBody = new HashMap<>();
requestBody.put("messages", messages);
requestBody.put("topP", 0.8);
requestBody.put("topK", 0);
requestBody.put("maxTokens", 256);
requestBody.put("temperature", 0.5);
requestBody.put("repeatPenalty", 5.0);
requestBody.put("includeAiFilters", "True");

HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);

ResponseEntity<String> responseEntity = fetchClovaAPI(messages,requestId);
JsonObject jsonObject = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject();
JsonObject messageObject = jsonObject.getAsJsonObject("result").getAsJsonObject("message");
String content = messageObject.get("content").getAsString();
Expand All @@ -93,10 +71,8 @@ public Map<String, String> recommendMember(RecommendMemberRequestDTO recommendMe
}
@Transactional
public List<Map<String, String>> recommendSchedule(RecommendScheduleRequestDTO recommendScheduleRequestDTO) {
String url = clovaStudioRecommend.getUrl();
String apiKeyClovaStudio = clovaStudioRecommend.getApiKeyClovaStudio();


String requestId = clovaStudioRecommend.getRequestScheduleId();

List<Message> messages = new ArrayList<>();

// 첫 번째 메시지
Expand Down Expand Up @@ -138,26 +114,8 @@ public List<Map<String, String>> recommendSchedule(RecommendScheduleRequestDTO r
"\"해야할 업무\" (시작날짜 ~ 마감날짜)로만 대답해주세요. 다른 말 없이 역할과 해야할 업무, 시작날짜, 마감날짜만 작성해주세요. 역할 앞에 숫자를 넣지 말고, 업무 앞에 -를 넣지 마세요. ");
messages.add(requestMessage);

HttpHeaders headers = new HttpHeaders();
headers.set("X-NCP-CLOVASTUDIO-API-KEY", apiKeyClovaStudio);
headers.set("X-NCP-APIGW-API-KEY", clovaStudioRecommend.getApiGateWayKey());
headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", clovaStudioRecommend.getRequestScheduleId());
headers.set("Content-Type", "application/json");

Map<String, Object> requestBody = new HashMap<>();
requestBody.put("messages", messages);
requestBody.put("topP", 0.8);
requestBody.put("topK", 0);
requestBody.put("maxTokens", 256);
requestBody.put("temperature", 0.5);
requestBody.put("repeatPenalty", 5.0);
requestBody.put("includeAiFilters", "True");

HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);

ResponseEntity<String> responseEntity = fetchClovaAPI(messages,requestId);

JsonObject jsonObject = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject();
JsonObject messageObject = jsonObject.getAsJsonObject("result").getAsJsonObject("message");
String content = messageObject.get("content").getAsString();
Expand All @@ -178,7 +136,6 @@ public List<Map<String, String>> recommendSchedule(RecommendScheduleRequestDTO r
Matcher roleMatcher = roleRegex.matcher(role);

if (roleMatcher.matches()) {
String roleNumber = roleMatcher.group(1); // 1.
role = roleMatcher.group(2); // 기획자

// 숫자와 점을 제거한 role
Expand Down Expand Up @@ -259,6 +216,7 @@ public List<Map<String, String>> recommendSchedule(RecommendScheduleRequestDTO r

@Transactional
public void insertCalender(Long projectId, List<Map<String, String>> roleScheduleList) {

Project project = projectRepository.findById(projectId).orElseThrow(()->new NoSuchElementException("[ERROR] 해당하는 프로젝트가 존재하지 않습니다."));
for(Map<String,String> map : roleScheduleList){
Role r = new Role();
Expand All @@ -274,4 +232,31 @@ public void insertCalender(Long projectId, List<Map<String, String>> roleSchedul
}
}

public ResponseEntity<String> fetchClovaAPI(List<Message> messages, String requestId){
String url = clovaStudioRecommend.getUrl();
String apiKeyClovaStudio = clovaStudioRecommend.getApiKeyClovaStudio();
String apiGateWayKey = clovaStudioRecommend.getApiGateWayKey();

HttpHeaders headers = new HttpHeaders();
headers.set("X-NCP-CLOVASTUDIO-API-KEY", apiKeyClovaStudio);
headers.set("X-NCP-APIGW-API-KEY", apiGateWayKey);
headers.set("X-NCP-CLOVASTUDIO-REQUEST-ID", requestId);
headers.set("Content-Type", "application/json");

Map<java.lang.String, Object> requestBody = new HashMap<>();
requestBody.put("messages", messages);
requestBody.put("topP", 0.8);
requestBody.put("topK", 0);
requestBody.put("maxTokens", 256);
requestBody.put("temperature", 0.5);
requestBody.put("repeatPenalty", 5.0);
requestBody.put("includeAiFilters", "True");

HttpEntity<Map<java.lang.String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);

}

}
Loading