Skip to content

Commit

Permalink
feat: 동행글 관련 API를 구현한다. (#18)
Browse files Browse the repository at this point in the history
* feat: Region enum을 추가하고 엔티티와 enum을 분리한다.

* feat: AccompanyBoardsController와 관련 DTO를 추가한다.

* feat: AccompanyBoardsRepository, AccompanyUsersRepository를 추가한다.

* feat: AccompanyBoardsService를 추가한다.

* chore: 파일 이름 변경 및 패키지 경로 수정

* chore: 파일 이름 변경으로 인해 엔티티를 다시 추가한다.

* feat: dto와 RequestState을 추가한다.

* feat: 동행글과 관련된 예외 및 코드를 추가한다.

* feat: 동행글 관련 API를 구현하고 SecurityUtil을 추가한다.

* feat: enum 타입에 어노테이션을 추가한다.

* refactor: repository extends를 수정한다.

* refactor: dto 어노테이션을 수정한다.

* refactor: entity SoftDelete 관련 설정을 수정한다.

* feat: 데이터 처리 관련 로직을 수정한다.

* refactor: findDetailInfo 설명을 추가한다.

* refactor: AccompanyRequestRequest의 이름을 수정한다.

* refactor: dto 필드의 범위를 수정한다.

* refactor: userId를 @AuthenticationPrincipald를 사용하여 가져오도록 수정한다.

* refactor: 데이터 저장 시 saveAll을 통해 한번에 저장하도록 수정한다.

* refactor: existsByUserIdAndAccompanyBoardIdAndRole를 isHostOfBoard로 수정한다.

* refactor: board, profile을 함께 가져오는 db계층의 로직을 service로 옮긴다.

* refactor: Region을 수정한다.

* refactor: api를 AccompanyBoard로 분류하고 엔티티 PK이름을 수정한다.

* feat: AccompanyBoard delete 시 연관된 테이블 데이터도 삭제한다.

* chore: deleteByBoardId 파라미터 오타를 수정한다.
  • Loading branch information
min429 authored Aug 7, 2024
1 parent 2c44c15 commit 6c1b19a
Show file tree
Hide file tree
Showing 37 changed files with 817 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.dnd.accompany.domain.accompany.api;

import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.dnd.accompany.domain.accompany.api.dto.AccompanyBoardInfo;
import com.dnd.accompany.domain.accompany.api.dto.CreateAccompanyBoardRequest;
import com.dnd.accompany.domain.accompany.api.dto.CreateAccompanyBoardResponse;
import com.dnd.accompany.domain.accompany.api.dto.CreateAccompanyRequest;
import com.dnd.accompany.domain.accompany.api.dto.PageResponse;
import com.dnd.accompany.domain.accompany.api.dto.ReadAccompanyBoardResponse;
import com.dnd.accompany.domain.accompany.service.AccompanyBoardService;
import com.dnd.accompany.domain.accompany.service.AccompanyRequestService;
import com.dnd.accompany.domain.auth.dto.jwt.JwtAuthentication;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@Tag(name = "AccompanyBoard")
@RestController
@RequestMapping("api/v1/accompany/boards")
@RequiredArgsConstructor
public class AccompanyBoardController {

private final AccompanyBoardService accompanyBoardService;
private final AccompanyRequestService accompanyRequestService;

@Operation(summary = "동행글 생성")
@PostMapping
public ResponseEntity<CreateAccompanyBoardResponse> create(
@AuthenticationPrincipal JwtAuthentication user,
@RequestBody @Valid CreateAccompanyBoardRequest request) {
return ResponseEntity.ok(accompanyBoardService.create(user.getId(), request));
}

@Operation(summary = "동행글 목록 조회")
@GetMapping
public ResponseEntity<PageResponse<AccompanyBoardInfo>> readAll(
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size) {
return ResponseEntity.ok(accompanyBoardService.readAll(page, size));
}

@Operation(summary = "동행글 상세 조회")
@GetMapping("/{id}")
public ResponseEntity<ReadAccompanyBoardResponse> read(@PathVariable Long id) {
return ResponseEntity.ok(accompanyBoardService.read(id));
}

@Operation(summary = "동행 신청")
@PostMapping("/request")
public ResponseEntity<Void> request(
@AuthenticationPrincipal JwtAuthentication user,
@RequestBody @Valid CreateAccompanyRequest request) {
accompanyRequestService.save(user.getId(), request);
return ResponseEntity.ok().build();
}

@Operation(summary = "동행글 삭제")
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(
@AuthenticationPrincipal JwtAuthentication user,
@PathVariable Long id) {
accompanyBoardService.delete(user.getId(), id);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.dnd.accompany.domain.accompany.api.dto;

import java.time.LocalDateTime;

import com.dnd.accompany.domain.accompany.entity.enums.Category;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredAge;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredGender;
import com.dnd.accompany.domain.accompany.entity.enums.Region;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class AccompanyBoardDetailInfo {
Long boardId;
String title;
String content;
Region region;
LocalDateTime startDate;
LocalDateTime endDate;
Long headCount;
Long capacity;
Category category;
PreferredAge preferredAge;
PreferredGender preferredGender;

@Builder
public AccompanyBoardDetailInfo(Long boardId, String title, String content, Region region, LocalDateTime startDate,
LocalDateTime endDate, Long headCount, Long capacity, Category category, PreferredAge preferredAge,
PreferredGender preferredGender) {
this.boardId = boardId;
this.title = title;
this.content = content;
this.region = region;
this.startDate = startDate;
this.endDate = endDate;
this.headCount = headCount;
this.capacity = capacity;
this.category = category;
this.preferredAge = preferredAge;
this.preferredGender = preferredGender;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.dnd.accompany.domain.accompany.api.dto;

import java.time.LocalDateTime;

import com.dnd.accompany.domain.accompany.entity.enums.Region;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class AccompanyBoardInfo {
private Long boardId;
private String title;
private Region region;
private LocalDateTime startDate;
private LocalDateTime endDate;
private String nickname;

@Builder
public AccompanyBoardInfo(Long boardId, String title, Region region, LocalDateTime startDate, LocalDateTime endDate,
String nickname) {
this.boardId = boardId;
this.title = title;
this.region = region;
this.startDate = startDate;
this.endDate = endDate;
this.nickname = nickname;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.dnd.accompany.domain.accompany.api.dto;

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

import com.dnd.accompany.domain.accompany.entity.enums.Category;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredAge;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredGender;
import com.dnd.accompany.domain.accompany.entity.enums.Region;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record CreateAccompanyBoardRequest(
@NotNull String title,
@NotNull @Size(max = 2000) String content,
@NotNull Region region,
@NotNull LocalDateTime startDate,
@NotNull LocalDateTime endDate,
@NotNull Long capacity,
@NotNull Category category,
@NotNull PreferredAge preferredAge,
@NotNull PreferredGender preferredGender,
@NotNull @Size(min = 1, max = 5) List<@NotNull @Size(max = 2000) String> imageUrls,
@NotNull @Size(min = 1, max = 5) List<@NotNull @Size(max = 255) String> tagNames
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.dnd.accompany.domain.accompany.api.dto;

public record CreateAccompanyBoardResponse(
Long boardId
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dnd.accompany.domain.accompany.api.dto;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record CreateAccompanyRequest(
@NotNull Long boardId,
@NotNull @Size(max = 1500) String introduce,
@NotNull String chatLink
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.dnd.accompany.domain.accompany.api.dto;

import java.time.LocalDateTime;

import com.dnd.accompany.domain.accompany.entity.enums.Category;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredAge;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredGender;
import com.dnd.accompany.domain.accompany.entity.enums.Region;

public record FindDetailInfoResult(
Long boardId,
String title,
String content,
Region region,
LocalDateTime startDate,
LocalDateTime endDate,
Long headCount,
Long capacity,
Category category,
PreferredAge preferredAge,
PreferredGender preferredGender,
String nickname
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dnd.accompany.domain.accompany.api.dto;

import java.util.List;

public record PageResponse<T>(
boolean hasNext,
List<T> data
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dnd.accompany.domain.accompany.api.dto;

public record ReadAccompanyBoardResponse(
AccompanyBoardDetailInfo boardInfo,
UserProfileDetailInfo profileInfo
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.dnd.accompany.domain.accompany.api.dto;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserProfileDetailInfo {
private String nickname;

@Builder
public UserProfileDetailInfo(String nickname) {
this.nickname = nickname;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;

import com.dnd.accompany.domain.accompany.entity.enums.Category;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredAge;
import com.dnd.accompany.domain.accompany.entity.enums.PreferredGender;
import com.dnd.accompany.domain.accompany.entity.enums.Region;
import com.dnd.accompany.domain.common.entity.TimeBaseEntity;

import jakarta.persistence.Column;
Expand All @@ -26,11 +30,10 @@
@Table(name = "accompany_boards")
@SQLRestriction("deleted = false")
@SQLDelete(sql = "UPDATE accompany_boards SET deleted = true WHERE id = ?")
public class AccompanyBoards extends TimeBaseEntity {
public class AccompanyBoard extends TimeBaseEntity {

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

@Column(nullable = false)
Expand All @@ -42,11 +45,9 @@ public class AccompanyBoards extends TimeBaseEntity {
)
private String content;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private String region;

@Column(nullable = false)
private String district;
private Region region;

@Column(nullable = false)
private LocalDateTime startDate;
Expand All @@ -72,16 +73,16 @@ public class AccompanyBoards extends TimeBaseEntity {
@Column(nullable = false)
private PreferredGender preferredGender;

private boolean deleted = Boolean.FALSE;

@Builder
public AccompanyBoards(Long id, String title, String content, String region, String district,
LocalDateTime startDate,
public AccompanyBoard(Long id, String title, String content, Region region, LocalDateTime startDate,
LocalDateTime endDate, Long headCount, Long capacity, Category category, PreferredAge preferredAge,
PreferredGender preferredGender) {
this.id = id;
this.title = title;
this.content = content;
this.region = region;
this.district = district;
this.startDate = startDate;
this.endDate = endDate;
this.headCount = headCount;
Expand All @@ -90,16 +91,4 @@ public AccompanyBoards(Long id, String title, String content, String region, Str
this.preferredAge = preferredAge;
this.preferredGender = preferredGender;
}

public enum PreferredAge {
SAME, ANY
}

public enum Category {
FULL, PART, LODGING, TOUR, MEAL
}

public enum PreferredGender {
SAME, ANY
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,25 @@
})
@SQLRestriction("deleted = false")
@SQLDelete(sql = "UPDATE accompany_images SET deleted = true WHERE id = ?")
public class AccompanyImages {
public class AccompanyImage {

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "accompany_boards_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private AccompanyBoards accompanyBoards;
private AccompanyBoard accompanyBoard;

@Column(nullable = false, length = 2000)
private String imageUrl;

private boolean deleted = Boolean.FALSE;

@Builder
public AccompanyImages(Long id, AccompanyBoards accompanyBoards, String imageUrl) {
public AccompanyImage(Long id, AccompanyBoard accompanyBoard, String imageUrl) {
this.id = id;
this.accompanyBoards = accompanyBoards;
this.accompanyBoard = accompanyBoard;
this.imageUrl = imageUrl;
}
}
Loading

0 comments on commit 6c1b19a

Please sign in to comment.