Skip to content

Commit

Permalink
Merge pull request #40 from 29sungdong/feat/course
Browse files Browse the repository at this point in the history
[feat] 산책코스 관련 기능 구현
  • Loading branch information
suhhyun524 authored Mar 18, 2024
2 parents 1e8c453 + 57bd7d8 commit c80af56
Show file tree
Hide file tree
Showing 15 changed files with 456 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package sungdong29.backend.domain.course;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import sungdong29.backend.domain.course.dto.request.CourseCreateRequestDTO;
import sungdong29.backend.domain.course.dto.response.CourseIdResponseDTO;
import sungdong29.backend.domain.course.service.CourseService;
import sungdong29.backend.global.config.user.UserDetails;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/courses")
@Tag(name = "Course")
public class CourseController {

private final CourseService courseService;

@Operation(summary = "코스 생성")
@PostMapping()
public ResponseEntity<CourseIdResponseDTO> createCourse(
@AuthenticationPrincipal UserDetails userDetails,
@RequestBody CourseCreateRequestDTO courseCreateRequestDTO) {
log.info("코스 생성");
CourseIdResponseDTO courseIdResponseDTO = courseService.createCourse(userDetails, courseCreateRequestDTO);
return ResponseEntity.ok(courseIdResponseDTO);
}

@Operation(summary = "내 코스 수정")
@PatchMapping("/{courseId}")
public ResponseEntity<CourseIdResponseDTO> updateCourse(
@AuthenticationPrincipal UserDetails userDetails,
@PathVariable Long courseId,
@RequestBody CourseCreateRequestDTO courseInfoRequestDTO
) {
log.info("코스 수정");
CourseIdResponseDTO courseIdResponseDTO = courseService.updateCourse(userDetails, courseId, courseInfoRequestDTO);
return ResponseEntity.ok(courseIdResponseDTO);
}

@Operation(summary = "내 코스 삭제")
@DeleteMapping("/{courseId}")
public ResponseEntity<Void> deleteCourse(
@AuthenticationPrincipal UserDetails userDetails,
@PathVariable Long courseId
) {
log.info("코스 삭제");
courseService.deleteCourse(userDetails, courseId);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

@Operation(summary = "코스 좋아요 상태 변경")
@PostMapping("/{courseId}/like")
public ResponseEntity<Void> likeCourse(
@AuthenticationPrincipal UserDetails userDetails,
@PathVariable Long courseId
) {
log.info("코스 좋아요 상태 변성");
courseService.changeCourseLike(userDetails, courseId);
return ResponseEntity.status(HttpStatus.OK).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package sungdong29.backend.domain.course.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum Category {

C1("카테고리1"),
C2("키테고리2");

private final String category;
}
50 changes: 50 additions & 0 deletions src/main/java/sungdong29/backend/domain/course/domain/Course.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package sungdong29.backend.domain.course.domain;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import sungdong29.backend.domain.course.dto.request.CourseCreateRequestDTO;
import sungdong29.backend.domain.user.domain.User;


@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Course {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

@Column
private String name;

@Column
private Category category;

@Column
private String description;

@Builder
private Course(User user, String name, Category category, String description) {
this.user = user;
this.name = name;
this.category = category;
this.description = description;
}

public static Course of(User user, CourseCreateRequestDTO courseCreateRequestDTO) {
return Course.builder()
.user(user)
.name(courseCreateRequestDTO.getTitle())
.category(courseCreateRequestDTO.getCategory())
.description(courseCreateRequestDTO.getDescription())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package sungdong29.backend.domain.course.domain;

import jakarta.persistence.*;
import lombok.Builder;
import sungdong29.backend.domain.user.domain.User;

public class CourseLike {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "course_id")
private Course course;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

@Builder
public CourseLike(Course course, User user) {
this.course = course;
this.user = user;
}

public static CourseLike of(Course course, User user) {
return CourseLike.builder()
.course(course)
.user(user)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package sungdong29.backend.domain.course.domain;

import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import sungdong29.backend.domain.place.domain.Place;

@Entity
@Getter
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class CoursePlace {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "course_id")
private Course course;

@ManyToOne
@JoinColumn(name = "place_id", nullable = true)
private Place place;

@Column
private int orderNumber;

@Builder
private CoursePlace(Course course, Place place, int orderNumber) {
this.course = course;
this.place = place;
this.orderNumber = orderNumber;
}

public static CoursePlace of(Course course, Place place, int orderNumber) {
return CoursePlace.builder()
.course(course)
.place(place)
.orderNumber(orderNumber)
.build();
}

public void updateOrderNumber(int orderNumber) {
this.orderNumber = orderNumber;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sungdong29.backend.domain.course.dto.request;

import lombok.Builder;
import lombok.Getter;
import sungdong29.backend.domain.course.domain.Category;

import java.util.List;

@Getter
public class CourseCreateRequestDTO {

private String title;

private Category category;

private String description;

private List<Long> placeIds;

@Builder
private CourseCreateRequestDTO(String title, Category category, String description, List<Long> placeIds) {
this.title = title;
this.category = category;
this.description = description;
this.placeIds = placeIds;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sungdong29.backend.domain.course.dto.request;

import lombok.Builder;
import lombok.Getter;
import sungdong29.backend.domain.course.domain.Category;

import java.util.List;

@Getter
public class CourseInfoRequestDTO {

private String title;

private Category category;

private String description;

private List<Long> coursePlaceIds;

@Builder
private CourseInfoRequestDTO(String title, Category category, String description, List<Long> coursePlaceIds) {
this.title = title;
this.category = category;
this.description = description;
this.coursePlaceIds = coursePlaceIds;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sungdong29.backend.domain.course.dto.response;

import lombok.Builder;
import lombok.Getter;

@Getter
public class CourseIdResponseDTO {

private Long id;

@Builder
private CourseIdResponseDTO(Long id) {
this.id = id;
}

public static CourseIdResponseDTO from(Long id) {
return CourseIdResponseDTO.builder()
.id(id)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package sungdong29.backend.domain.course.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import sungdong29.backend.global.common.dto.ErrorReason;
import sungdong29.backend.global.error.BaseErrorCode;

import static org.springframework.http.HttpStatus.NOT_FOUND;

@Getter
@AllArgsConstructor
public enum CourseErrorCode implements BaseErrorCode {

COURSE_NOT_FOUND(NOT_FOUND, "COURSE_404_1", "코스가 존재하지 않습니다."),
COURSE_PLACE_NOT_FOUND(NOT_FOUND, "COURSEPLACE_404_1", "코스장소가 존재하지 않습니다.");
private HttpStatus status;
private String code;
private String reason;

@Override
public ErrorReason getErrorReason() {
return ErrorReason.of(status.value(), code, reason);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package sungdong29.backend.domain.course.exception;

import sungdong29.backend.global.error.BaseErrorException;

public class CourseNotFound extends BaseErrorException {

public static final CourseNotFound EXCEPTION = new CourseNotFound();

private CourseNotFound() {
super(CourseErrorCode.COURSE_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package sungdong29.backend.domain.course.exception;

import sungdong29.backend.global.error.BaseErrorException;

public class CoursePlaceNotFound extends BaseErrorException {

public static final CoursePlaceNotFound EXCEPTION = new CoursePlaceNotFound();

private CoursePlaceNotFound() {
super(CourseErrorCode.COURSE_PLACE_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package sungdong29.backend.domain.course.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import sungdong29.backend.domain.course.domain.Course;
import sungdong29.backend.domain.course.domain.CourseLike;
import sungdong29.backend.domain.user.domain.User;

public interface CourseLikeRepository extends JpaRepository<CourseLike, Long> {

boolean existsByCourseAndUser(Course course, User user);

void deleteByCourseAndUser(Course course, User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package sungdong29.backend.domain.course.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import sungdong29.backend.domain.course.domain.Course;
import sungdong29.backend.domain.course.domain.CoursePlace;

import java.util.List;

public interface CoursePlaceRepository extends JpaRepository<CoursePlace, Long> {
List<CoursePlace> findByCourse(Course course);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sungdong29.backend.domain.course.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import sungdong29.backend.domain.course.domain.Course;

public interface CourseRepository extends JpaRepository<Course, Long> {
}
Loading

0 comments on commit c80af56

Please sign in to comment.