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

Feat : 내 커리어 활동 CRUD 기능 추가 #11

Merged
merged 12 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ out/

### VS Code ###
.vscode/

.DS_Store
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'mysql:mysql-connector-java:8.0.32'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'org.openapitools:jackson-databind-nullable:0.2.1'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/umc/kkijuk/server/ServerApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class ServerApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package umc.kkijuk.server.career.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import umc.kkijuk.server.career.controller.response.CareerGroupedByResponse;
import umc.kkijuk.server.career.controller.response.CareerResponse;
import umc.kkijuk.server.career.controller.response.CareerResponseMessage;
import umc.kkijuk.server.career.domain.Career;
import umc.kkijuk.server.career.dto.CareerRequestDto;
import umc.kkijuk.server.career.dto.CareerResponseDto;
import umc.kkijuk.server.career.dto.converter.CareerConverter;
import umc.kkijuk.server.career.service.CareerService;
import umc.kkijuk.server.common.LoginUser;

import java.util.List;

@Tag(name="career",description = "내커리어 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/career")
public class CareerController {

private final CareerService careerService;

@PostMapping("")
@Operation(summary = "활동 추가 API", description = "내 커리어 - 활동을 추가하는 API")
public CareerResponse<CareerResponseDto.CareerResultDto> create(@RequestBody @Valid CareerRequestDto.CreateCareerDto request){
LoginUser loginUser = LoginUser.get();
Career career = careerService.createCareer(request);
return CareerResponse.success(HttpStatus.CREATED,
CareerResponseMessage.CAREER_CREATE_SUCCESS,
CareerConverter.toCareerResultDto(career));
}

@DeleteMapping("/{careerId}")
@Operation(summary = "활동 삭제 API", description = "내 커리어 - 활동을 삭제하는 API")
@Parameter(name="careerId", description = "활동 Id, path variable 입니다.",example = "1")
public CareerResponse<Object> delete(@PathVariable Long careerId){
LoginUser loginUser = LoginUser.get();
careerService.deleteCareer(careerId);
return CareerResponse.success(HttpStatus.OK,
CareerResponseMessage.CAREER_DELETE_SUCCESS,null);
}

@PatchMapping("/{careerId}")
@Operation(summary = "활동 수정 API", description = "내 커리어 - 활동을 수정하는 API")
@Parameter(name="careerId", description = "활동 Id, path variable 입니다.",example = "1")
public CareerResponse<Object> update(@RequestBody @Valid CareerRequestDto.UpdateCareerDto request,
@PathVariable Long careerId) {
LoginUser loginUser = LoginUser.get();
Career updateCareer = careerService.updateCareer(careerId, request);
return CareerResponse.success(HttpStatus.OK,
CareerResponseMessage.CAREER_UPDATE_SUCCESS,
CareerConverter.toCareerDto(updateCareer));
}

@GetMapping("")
@Operation(
summary = "활동 조회 API - category(카테고리 기준) , year(연도 기준) ",
description = "내 커리어 - 활동을 카테고리 별로 조회하는 API입니다. query 값으로 category 나 year 값을 주세요. " )
public CareerResponse<List<? extends CareerGroupedByResponse>> read(@RequestParam(name="status") String value){
return CareerResponse.success(HttpStatus.OK,
CareerResponseMessage.CAREER_FINDALL_SUCCESS,
careerService.getCareerGroupedBy(value));
}



}










Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exception을 핸들링하는 advice와 exception를 정의한 클래스를 common 패키지로 옮겨서 한눈에 관리하죠!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 advice랑 exception 클래스만 common으로 옮기고 기존에 있던 exception 패키지는 지우면 되나요??

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 그렇게 하시고 테스트 통과만 확인하면 될것같아요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package umc.kkijuk.server.career.controller.exception;


import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import umc.kkijuk.server.career.controller.response.CareerResponse;
import umc.kkijuk.server.career.controller.response.CareerResponseMessage;


@RestControllerAdvice(assignableTypes = {umc.kkijuk.server.career.controller.CareerController.class})
public class CareerExceptionControllerAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<CareerResponse<?>> handleValidationExceptions(BindingResult bindingResult) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(CareerResponse.createFail(bindingResult));
}

@ExceptionHandler(InvalidFormatException.class)
public ResponseEntity<CareerResponse<?>> handleInvalidFormatExceptions(InvalidFormatException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(CareerResponse.createError(CareerResponseMessage.CAREER_FOTMAT_INVALID));
}

@ExceptionHandler(CareerValidationException.class)
public ResponseEntity<CareerResponse<?>> handleCareerValidationException(CareerValidationException e){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(CareerResponse.createError(e.getMessage()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package umc.kkijuk.server.career.controller.exception;

public class CareerValidationException extends RuntimeException{

public CareerValidationException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package umc.kkijuk.server.career.controller.response;

public abstract class CareerGroupedByResponse {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package umc.kkijuk.server.career.controller.response;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import org.hibernate.annotations.AnyKeyJavaClass;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Builder
@Getter
public class CareerResponse<T> {
private int status;
private String message;
@JsonInclude(JsonInclude.Include.NON_NULL)
private T data;

public CareerResponse(final int status,final String message,T data){
this.status = status;
this.message = message;
this.data = data;
}
public static <T> CareerResponse<T> success(HttpStatus status, String message, T data){
return new CareerResponse<>(status.value(),message,data);
}
public static CareerResponse<?> createFail (BindingResult bindingResult){
Map<String, String> errors = new HashMap<>();
List<ObjectError> allErrors = bindingResult.getAllErrors();
for ( ObjectError error: allErrors ) {
if( error instanceof FieldError) {
errors.put(((FieldError)error).getField(),error.getDefaultMessage());
}else{
errors.put(error.getObjectName(),error.getDefaultMessage());
}
}
return new CareerResponse<>(HttpStatus.BAD_REQUEST.value(), CareerResponseMessage.CAREER_CREATE_FAIL,errors);
}
public static CareerResponse<?> createError(String message){
return new CareerResponse<>(HttpStatus.BAD_REQUEST.value(), message, null);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package umc.kkijuk.server.career.controller.response;

public class CareerResponseMessage {
public static final String CAREER_CREATE_SUCCESS = "활동 추가가 정상적으로 이루어졌습니다.";
public static final String CAREER_UPDATE_SUCCESS = "활동 수정이 정상적으로 이루어졌습니다.";
public static final String CAREER_DELETE_SUCCESS = "활동 삭제가 정상적으로 이루어졌습니다.";
public static final String CAREER_FINDALL_SUCCESS = "활동 조회가 정상적으로 이루어졌습니다.";


public static final String CAREER_NOT_FOUND ="존재하는 활동 Id가 아닙니다.";
public static final String CAREER_CREATE_FAIL = "활동 추가를 실패했습니다.";


public static final String CAREER_FOTMAT_INVALID = "올바른 날짜 형식이 아닙니다. YYYY-MM-DD 형식으로 입력해야 합니다.";
public static final String CAREER_ENDDATE = "현재 진행중이 아니라면, 활동 종료 날짜를 입력해야 합니다.";
public static final String CAREER_PERIOD_FAIL = "시작 날짜는 종료 날짜보다 앞에 있어야 합니다.";


public static final String CATEGORY_NOT_FOUND = "존재하는 카테고리 Id가 아닙니다.";
public static final String CAREER_FINDALL_FAIL = "올바른 요청이 아닙니다. category, year 요청을 주세요";









}
74 changes: 74 additions & 0 deletions src/main/java/umc/kkijuk/server/career/domain/Career.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package umc.kkijuk.server.career.domain;

import jakarta.persistence.*;
import lombok.*;
import umc.kkijuk.server.career.domain.base.BaseEntity;

import java.time.LocalDate;

@Entity
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Career extends BaseEntity {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="career_id")
private Long id;

@Column(name="career_name", length = 20)
private String name;

@Column(name="career_alias", length = 20)
private String alias;

@Column(name="career_current")
private Boolean current;

@Column(name="career_summary",length = 50)
private String summary;

@Column(name="career_year")
private int year;

@Column(name="career_startdate")
private LocalDate startdate;

@Column(name="career_enddate")
private LocalDate enddate;

@ManyToOne
@JoinColumn(name = "category_id")
private Category category;

public void setName(String name) {
this.name = name;
}

public void setAlias(String alias) {
this.alias = alias;
}

public void setCurrent(Boolean current) {
this.current = current;
}

public void setSummary(String summary) {
this.summary = summary;
}

public void setStartdate(LocalDate startdate) {
this.startdate = startdate;
}

public void setEnddate(LocalDate enddate) {
this.enddate = enddate;
}

public void setCategory(Category category) {
this.category = category;
}
public void setYear(int dayOfYear) {
this.year = dayOfYear;
}
}
25 changes: 25 additions & 0 deletions src/main/java/umc/kkijuk/server/career/domain/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package umc.kkijuk.server.career.domain;


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

import java.util.List;

@Entity
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class Category {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="category_id")
private Long id;

@Column(name="category_name", nullable = false, length = 20)
private String name;

@OneToMany(mappedBy = "category")
private List<Career> careers;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package umc.kkijuk.server.career.domain.base;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@CreatedDate
@Column(length = 6)
private LocalDateTime createdAt;

@LastModifiedDate
@Column(length = 6)
private LocalDateTime updatedAt;
}
Loading