Skip to content

Commit

Permalink
Merge pull request #57 from CSID-DGU/back
Browse files Browse the repository at this point in the history
11월 1일 배포
  • Loading branch information
proysm authored Nov 1, 2024
2 parents d9c1d70 + ed479cf commit 74e59da
Show file tree
Hide file tree
Showing 43 changed files with 1,244 additions and 121 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ out/
*.xml
!crawling_data.zip
!data-importer-2023-12-20.zip
back/src/test/java/com/thered/stocksignal/test/TokenTest.java
2 changes: 1 addition & 1 deletion back/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' // JSON 파싱을 위해 Jackson 사용
implementation 'org.springframework.boot:spring-boot-starter-security'

//scrapping
// scrapping
implementation 'org.jsoup:jsoup:1.14.3'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ public static <T> ApiResponse<T> onSuccess(Status status, T data){
public static <T> ApiResponse<T> onFailure(Status status){
return new ApiResponse<>(status.getCode(), status.getResult(), status.getMessage(), null);
}

// 실패한 경우 응답 생성
public static <T> ApiResponse<T> onFailure(Status status, T data){
return new ApiResponse<>(status.getCode(), status.getResult(), status.getMessage(), data);
}
}
28 changes: 22 additions & 6 deletions back/src/main/java/com/thered/stocksignal/apiPayload/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public enum Status {
*/
INGA_SUCCESS("200", "SUCCESS", "카카오 인가코드입니다."),
LOGIN_SUCCESS("200", "SUCCESS", "로그인이 완료되었습니다."),
TOKEN_INVALID("201", "SUCCESS", "유효하지 않은 토큰입니다."),
TOKEN_INVALID("401", "SUCCESS", "유효하지 않은 토큰입니다."),

QUESTION_FOUND("200", "SUCCESS", "답변 정보를 찾았습니다."),

Expand All @@ -49,26 +49,42 @@ public enum Status {
GET_USERINFO_SUCCESS("200", "SUCCESS", "회원 정보가 조회되었습니다."),
SET_USERINFO_SUCCESS("200", "SUCCESS", "회원 정보가 수정되었습니다."),
NICKNAME_SUCCESS("200", "SUCCESS", "사용 가능한 닉네임입니다."),
NICKNAME_INVALID("201", "SUCCESS", "이미 존재하는 닉네임입니다."),
NICKNAME_INVALID("409", "SUCCESS", "이미 존재하는 닉네임입니다."),

KIS_CONNECT_SUCCESS("200", "SUCCESS", "한국투자증권 계좌를 연동했습니다."),
KIS_CONNECT_FAILED("201", "SUCCESS", "한국투자증권 계좌를 연동할 수 없습니다."),
KIS_CONNECT_FAILED("401", "SUCCESS", "한국투자증권 계좌를 연동할 수 없습니다."),

TRADE_BUY_SUCCESS("200", "SUCCESS", "매수를 성공했습니다."),
TRADE_BUY_FAILED("400", "FAILED", "매수를 실패했습니다."),
TRADE_SELL_SUCCESS("200", "SUCCESS", "매도를 성공했습니다."),

TRADE_SELL_FAILED("400", "FAILED", "매도를 실패했습니다."),

MYSTOCK_SUCCESS("200", "SUCCESS", "나의 전체 주식현황을 읽는데 성공했습니다."),
MYSTOCK_SHORT_SUCCESS("200", "SUCCESS", "나의 주식현황 요약을 읽는데 성공했습니다."),

SCENARIO_FOUND("200", "SUCCESS", "시나리오 조회에 성공했습니다."),
SCENARIO_CREATED("200", "SUCCESS", "시나리오 생성에 성공했습니다."),
SCENARIO_DELETED("200", "SUCCESS", "시나리오가 삭제되었습니다."),

CONDITION_FOUND("200", "SUCCESS", "조건 조회에 성공하였습니다."),
CONDITION_ADDED("200", "SUCCESS", "조건 추가에 성공했습니다."),
CONDITION_DELETED("200", "SUCCESS", "조건 삭제에 성공했습니다."),

//실패
USER_NOT_FOUND("404", "FAILURE", "사용자를 찾을 수 없습니다"),

COMPANY_NOT_FOUND("404", "FAILURE", "회사 정보를 찾을 수 없습니다"),
COMPANY_RANKING_FAILURE("400", "FAILURE", "인기 종목 조회에 실패했습니다."),
COMPANY_RANKING_FAILED("400", "FAILURE", "인기 종목 조회에 실패했습니다."),

MY_BALANCE_NOT_FOUND("404", "FAILURE", "잔고 정보를 찾을 수 없습니다"),

NEWS_NOT_FOUND("404", "FAILURE", "뉴스 정보를 찾을 수 없습니다");
NEWS_NOT_FOUND("404", "FAILURE", "뉴스 정보를 찾을 수 없습니다"),

SCENARIO_CREATION_FAILED("400", "FAILURE", "시나리오 생성에 실패하였습니다."),
SCENARIO_DELETION_FAILED("400", "FAILURE", "시나리오 삭제에 실패하였습니다."),

ADDING_CONDITION_FAILED("400", "FAILURE", "조건 추가에 실패했습니다."),
DELETING_CONDITION_FAILED("400", "FAILURE", "조건 삭제에 실패했습니다.");

private final String code;
private final String result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public class CompanyController {
private final CompanyService companyService;
private final UserAccountService userAccountService;

@GetMapping("/code/{companyName}")
@Operation(summary = "종목 코드 조회", description = "회사명으로 종목 코드를 가져옵니다.")
@GetMapping("/{companyName}/code")
@Operation(summary = "종목 코드 조회", description = "종목명으로 종목 코드를 가져옵니다.")
public ApiResponse<CompanyCodeResponseDto> getCompanyCode(@PathVariable String companyName) {

Optional<CompanyCodeResponseDto> responseDto = companyService.findCodeByName(companyName);
Expand All @@ -35,8 +35,8 @@ public ApiResponse<CompanyCodeResponseDto> getCompanyCode(@PathVariable String c
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_NOT_FOUND));
}

@GetMapping("/logo/{companyName}")
@Operation(summary = "로고 이미지 URL 조회", description = "회사명으로 로고 이미지 URL을 가져옵니다.")
@GetMapping("/{companyName}/logo")
@Operation(summary = "로고 이미지 URL 조회", description = "종목명으로 로고 이미지 경로를 불러옵니다.")
public ApiResponse<CompanyLogoResponseDto> getCompanyLogo(@PathVariable String companyName) {

Optional<CompanyLogoResponseDto> responseDto = companyService.findLogoByName(companyName);
Expand All @@ -45,77 +45,72 @@ public ApiResponse<CompanyLogoResponseDto> getCompanyLogo(@PathVariable String c
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_NOT_FOUND));
}

@GetMapping("/{companyCode}")
@Operation(summary = "회사 정보 조회(분석 탭)", description = "종목 코드로 회사 정보 조회")
@GetMapping("/{companyName}")
@Operation(summary = "회사 정보 조회(분석 탭)", description = "종목명으로 회사 정보를 조회합니다.")
public ApiResponse<CompanyInfoResponseDto> getCompanyInfo(
@PathVariable String companyCode,
@PathVariable String companyName,
@RequestHeader("Authorization") String token
) {
Optional<CompanyCodeResponseDto> companyCode = companyService.findCodeByName(companyName);
if(companyCode.isEmpty()) return ApiResponse.onFailure(Status.COMPANY_NOT_FOUND);

Long userId = userAccountService.getUserIdFromToken(token);
if(userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

Optional<User> user = userAccountService.findById(userId);
if (user.isEmpty()) return ApiResponse.onFailure(Status.USER_NOT_FOUND);

Optional<CompanyInfoResponseDto> responseDto = companyService.findCompanyInfoByCode(
companyCode,
user.get().getKisToken(),
user.get().getAppKey(),
user.get().getSecretKey()
companyCode.get().getCompanyCode(),
userId
);

return responseDto
.map(dto -> ApiResponse.onSuccess(Status.COMPANY_INFO_SUCCESS, dto))
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_NOT_FOUND));
}

@GetMapping("/current-price/{companyCode}")
@Operation(summary = "현재가 조회", description = "종목 코드로 현재가 조회")
@GetMapping("/{companyName}/current-price")
@Operation(summary = "현재가 조회", description = "종목명으로 현재가를 조회합니다.")
public ApiResponse<CurrentPriceResponseDto> getCurrentPrice(
@PathVariable String companyCode,
@PathVariable String companyName,
@RequestHeader("Authorization") String token
){
Optional<CompanyCodeResponseDto> companyCode = companyService.findCodeByName(companyName);
if(companyCode.isEmpty()) return ApiResponse.onFailure(Status.COMPANY_NOT_FOUND);

Long userId = userAccountService.getUserIdFromToken(token);
if(userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

Optional<User> user = userAccountService.findById(userId);
if (user.isEmpty()) return ApiResponse.onFailure(Status.USER_NOT_FOUND);

Optional<CurrentPriceResponseDto> responseDto = companyService.findCurrentPriceByCode(
companyCode,
user.get().getKisToken(),
user.get().getAppKey(),
user.get().getSecretKey()
companyCode.get().getCompanyCode(),
userId
);

return responseDto
.map(dto -> ApiResponse.onSuccess(Status.CURRENT_PRICE_SUCCESS, dto))
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_NOT_FOUND));
}

@GetMapping("/period-price")
@Operation(summary = "일봉 조회", description = "종목 코드로 일봉 조회")
@GetMapping("/{companyName}/period-price")
@Operation(summary = "일봉 조회", description = "종목명으로 일봉을 조회합니다.")
public ApiResponse<PeriodPriceResponseDto> getPeriodPrice(
@RequestParam String companyCode,
@PathVariable String companyName,
@RequestParam String startDate,
@RequestParam String endDate,
@RequestHeader("Authorization") String token
){
Optional<CompanyCodeResponseDto> companyCode = companyService.findCodeByName(companyName);
if(companyCode.isEmpty()) return ApiResponse.onFailure(Status.COMPANY_NOT_FOUND);

Long userId = userAccountService.getUserIdFromToken(token);
if(userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

Optional<User> user = userAccountService.findById(userId);
if (user.isEmpty()) return ApiResponse.onFailure(Status.USER_NOT_FOUND);

Optional<PeriodPriceResponseDto> responseDto = companyService.findPeriodPriceByCode(
companyCode,
companyCode.get().getCompanyCode(),
startDate,
endDate,
user.get().getKisToken(),
user.get().getAppKey(),
user.get().getSecretKey()
userId
);

return responseDto
Expand All @@ -131,6 +126,6 @@ public ApiResponse<List<popularStockResponseDto>> getPopularStocks() {

return responseDto
.map(dto -> ApiResponse.onSuccess(Status.COMPANY_RANKING_SUCCESS, dto))
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_RANKING_FAILURE));
.orElseGet(() -> ApiResponse.onFailure(Status.COMPANY_RANKING_FAILED));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
import com.thered.stocksignal.service.user.UserAccountService;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Operation;
import java.util.Optional;

Expand All @@ -27,7 +24,7 @@ public class KakaoLoginController {

@Operation(summary = "프론트로부터 카카오 인가코드 전달받기")
@Parameter(name = "code", description = "카카오에서 받은 인카코드, RequestParam")
@GetMapping("/login")
@PostMapping("/login")
public ApiResponse<?> kakaoLoginCode(@RequestParam("code") String code){

String token = kakaoLoginService.getKakaoToken(code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.thered.stocksignal.apiPayload.ApiResponse;
import com.thered.stocksignal.apiPayload.Status;
import com.thered.stocksignal.domain.entity.User;
import com.thered.stocksignal.service.myBalance.MyBalanceService;
import com.thered.stocksignal.service.user.UserAccountService;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -32,14 +31,8 @@ public ApiResponse<MyBalanceResponseDto> getMyBalance(
Long userId = userAccountService.getUserIdFromToken(token);
if(userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

Optional<User> user = userAccountService.findById(userId);
if (user.isEmpty()) return ApiResponse.onFailure(Status.USER_NOT_FOUND);

Optional<MyBalanceResponseDto> responseDto = myBalanceService.getMyBalance(
user.get().getAccountNumber(),
user.get().getKisToken(),
user.get().getAppKey(),
user.get().getSecretKey()
userId
);

return responseDto.map(dto -> ApiResponse.onSuccess(Status.MY_BALANCE_SUCCESS, dto))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.thered.stocksignal.app.controller;

import com.thered.stocksignal.apiPayload.ApiResponse;
import com.thered.stocksignal.apiPayload.Status;
import com.thered.stocksignal.app.dto.ScenarioDto.ConditionRequestDto;
import com.thered.stocksignal.app.dto.ScenarioDto.ConditionResponseDto;
import com.thered.stocksignal.app.dto.ScenarioDto.ScenarioRequestDto;
import com.thered.stocksignal.app.dto.ScenarioDto.ScenarioResponseDto;
import com.thered.stocksignal.service.scenario.ScenarioService;
import com.thered.stocksignal.service.user.UserAccountService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/scenario")
public class ScenarioController {

private final ScenarioService scenarioService;
private final UserAccountService userAccountService;

@GetMapping()
@Operation(summary = "시나리오 조회", description = "시나리오를 조회합니다.")
public ApiResponse<List<ScenarioResponseDto>> getScenario(@RequestHeader("Authorization") String token) {

Long userId = userAccountService.getUserIdFromToken(token);
if(userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

List<ScenarioResponseDto> responseDto = scenarioService.getScenario(
userId
);

return ApiResponse.onSuccess(Status.SCENARIO_FOUND, responseDto);
}

@PostMapping("/create")
@Operation(summary = "시나리오 생성", description = "새로운 시나리오를 생성합니다.")
public ApiResponse<Void> createScenario(
@RequestHeader("Authorization") String token,
@RequestBody ScenarioRequestDto newScenario) {

Long userId = userAccountService.getUserIdFromToken(token);
if (userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

boolean isCreated = scenarioService.createScenario(userId, newScenario);
if(!isCreated){
return ApiResponse.onFailure(Status.SCENARIO_CREATION_FAILED, null);
}
return ApiResponse.onSuccess(Status.SCENARIO_CREATED, null);
}

@DeleteMapping("/{scenarioId}/delete")
@Operation(summary = "시나리오 삭제", description = "특정 시나리오를 삭제합니다.")
public ApiResponse<Void> deleteScenario(
@RequestHeader("Authorization") String token,
@PathVariable Long scenarioId) {

Long userId = userAccountService.getUserIdFromToken(token);
if (userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

boolean isDeleted = scenarioService.deleteScenario(userId, scenarioId);
if (!isDeleted) {
return ApiResponse.onFailure(Status.SCENARIO_DELETION_FAILED, null);
}
return ApiResponse.onSuccess(Status.SCENARIO_DELETED, null);
}

@GetMapping("/{scenarioId}/conditions")
@Operation(summary = "시나리오 조건 조회", description = "특정 시나리오의 조건을 조회합니다.")
public ApiResponse<List<ConditionResponseDto>> getConditions(
@RequestHeader("Authorization") String token,
@PathVariable Long scenarioId) {

Long userId = userAccountService.getUserIdFromToken(token);
if (userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

List<ConditionResponseDto> responseDto = scenarioService.getConditions(userId, scenarioId);

return ApiResponse.onSuccess(Status.CONDITION_FOUND, responseDto);
}

@PostMapping("/conditions/create")
@Operation(summary = "시나리오 조건 추가", description = "특정 시나리오에 새 조건을 추가합니다.")
public ApiResponse<Void> addCondition(
@RequestHeader("Authorization") String token,
@RequestBody ConditionRequestDto newCondition) {

Long userId = userAccountService.getUserIdFromToken(token);
if (userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

boolean isCreated = scenarioService.addCondition(userId, newCondition);

if(!isCreated){
return ApiResponse.onFailure(Status.ADDING_CONDITION_FAILED, null);
}
return ApiResponse.onSuccess(Status.CONDITION_ADDED, null);
}

@DeleteMapping("/conditions/{conditionId}/delete")
@Operation(summary = "조건 삭제", description = "시나리오 내 특정 조건을 삭제합니다.")
public ApiResponse<Void> deleteCondition(
@RequestHeader("Authorization") String token,
@PathVariable Long conditionId) {

Long userId = userAccountService.getUserIdFromToken(token);
if (userId == -1) return ApiResponse.onFailure(Status.TOKEN_INVALID);

boolean isDeleted = scenarioService.deleteCondition(userId, conditionId);
if (!isDeleted) {
return ApiResponse.onFailure(Status.DELETING_CONDITION_FAILED, null);
}
return ApiResponse.onSuccess(Status.CONDITION_DELETED, null);
}

}
Loading

0 comments on commit 74e59da

Please sign in to comment.