Skip to content

Commit 92ec960

Browse files
authored
[Merge] Dev에서 Main 병합
Dev에서 Main 병합
2 parents 74bda55 + 2434c5c commit 92ec960

File tree

15 files changed

+296
-27
lines changed

15 files changed

+296
-27
lines changed

src/main/java/hs/kr/backend/devpals/domain/project/controller/ProjectCommentController.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hs.kr.backend.devpals.domain.project.controller;
22

33
import hs.kr.backend.devpals.domain.project.dto.CommentDTO;
4+
import hs.kr.backend.devpals.domain.project.dto.RecommentDTO;
45
import hs.kr.backend.devpals.domain.project.service.ProjectCommentService;
56
import hs.kr.backend.devpals.global.common.ApiResponse;
67
import io.swagger.v3.oas.annotations.Operation;
@@ -96,4 +97,77 @@ public ResponseEntity<ApiResponse<String>> deleteComment(
9697
@PathVariable Long commentId) {
9798
return projectCommentService.deleteComment(token, projectId, commentId);
9899
}
100+
101+
@PostMapping("/{projectId}/comment/{commentId}/recomment")
102+
@Operation(summary = "대댓글 작성", description = "특정 댓글에 대댓글을 작성합니다.")
103+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "대댓글 작성 성공")
104+
@io.swagger.v3.oas.annotations.responses.ApiResponse(
105+
responseCode = "400",
106+
description = "대댓글 작성 실패 - 잘못된 요청 또는 인증 오류",
107+
content = @Content(
108+
mediaType = "application/json",
109+
schema = @Schema(implementation = ApiResponse.class),
110+
examples = @ExampleObject(value = "{\"success\": false, \"message\": \"대댓글 내용이 없습니다.\", \"data\": null}")
111+
)
112+
)
113+
public ResponseEntity<ApiResponse<String>> writeRecomment(
114+
@RequestHeader("Authorization") String token,
115+
@PathVariable Long projectId,
116+
@PathVariable Long commentId,
117+
@RequestBody RecommentDTO dto) {
118+
return projectCommentService.writeRecomment(token, projectId, commentId, dto);
119+
}
120+
121+
@GetMapping("/{projectId}/comment/{commentId}/recomment")
122+
@Operation(summary = "대댓글 목록 조회", description = "특정 댓글에 달린 대댓글들을 조회합니다.")
123+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "대댓글 목록 조회 성공")
124+
@io.swagger.v3.oas.annotations.responses.ApiResponse(
125+
responseCode = "400",
126+
description = "대댓글 목록 조회 실패 - 존재하지 않는 댓글",
127+
content = @Content(
128+
mediaType = "application/json",
129+
schema = @Schema(implementation = ApiResponse.class),
130+
examples = @ExampleObject(value = "{\"success\": false, \"message\": \"존재하지 않는 댓글입니다.\", \"data\": null}")
131+
)
132+
)
133+
public ResponseEntity<ApiResponse<List<RecommentDTO>>> getRecomments(@PathVariable Long commentId) {
134+
return projectCommentService.getRecomments(commentId);
135+
}
136+
137+
@PatchMapping("/{projectId}/recomment/{recommentId}")
138+
@Operation(summary = "대댓글 수정", description = "작성한 대댓글을 수정합니다.")
139+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "대댓글 수정 성공")
140+
@io.swagger.v3.oas.annotations.responses.ApiResponse(
141+
responseCode = "400",
142+
description = "대댓글 수정 실패 - 권한 없음 또는 대댓글 없음",
143+
content = @Content(
144+
mediaType = "application/json",
145+
schema = @Schema(implementation = ApiResponse.class),
146+
examples = @ExampleObject(value = "{\"success\": false, \"message\": \"수정 권한이 없습니다.\", \"data\": null}")
147+
)
148+
)
149+
public ResponseEntity<ApiResponse<String>> updateRecomment(
150+
@RequestHeader("Authorization") String token,
151+
@PathVariable Long recommentId,
152+
@RequestBody RecommentDTO dto) {
153+
return projectCommentService.updateRecomment(token, recommentId, dto);
154+
}
155+
156+
@DeleteMapping("/{projectId}/recomment/{recommentId}")
157+
@Operation(summary = "대댓글 삭제", description = "작성한 대댓글을 삭제합니다.")
158+
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "대댓글 삭제 성공")
159+
@io.swagger.v3.oas.annotations.responses.ApiResponse(
160+
responseCode = "400",
161+
description = "대댓글 삭제 실패 - 권한 없음 또는 대댓글 없음",
162+
content = @Content(
163+
mediaType = "application/json",
164+
schema = @Schema(implementation = ApiResponse.class),
165+
examples = @ExampleObject(value = "{\"success\": false, \"message\": \"삭제 권한이 없습니다.\", \"data\": null}")
166+
)
167+
)
168+
public ResponseEntity<ApiResponse<String>> deleteRecomment(
169+
@RequestHeader("Authorization") String token,
170+
@PathVariable Long recommentId) {
171+
return projectCommentService.deleteRecomment(token, recommentId);
172+
}
99173
}

src/main/java/hs/kr/backend/devpals/domain/project/dto/ProjectAuthoredResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public static ProjectAuthoredResponse fromEntity(ProjectEntity project, List<Pos
4949
.totalMember(project.getTotalMember())
5050
.startDate(project.getStartDate())
5151
.estimatedPeriod(project.getEstimatedPeriod())
52-
.authorId(project.getAuthorId()) // Author 엔티티의 ID
52+
.authorId(project.getUserId())
5353
.views(project.getViews())
5454
.isBeginner(project.isBeginner())
5555
.isDone(project.isDone())

src/main/java/hs/kr/backend/devpals/domain/project/dto/ProjectCloseResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static ProjectCloseResponse fromEntity(ProjectEntity project, MethodTypeR
3838
.startDate(project.getStartDate())
3939
.estimatedPeriod(project.getEstimatedPeriod())
4040
.methodType(methodTypeResponse)
41-
.authorId(project.getAuthorId())
41+
.authorId(project.getUserId())
4242
.views(project.getViews())
4343
.isBeginner(project.isBeginner())
4444
.isDone(project.isDone())
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package hs.kr.backend.devpals.domain.project.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import hs.kr.backend.devpals.domain.project.entity.CommentEntity;
5+
import hs.kr.backend.devpals.domain.project.entity.RecommentEntity;
6+
import io.swagger.v3.oas.annotations.media.Schema;
7+
import lombok.AllArgsConstructor;
8+
import lombok.Builder;
9+
import lombok.Getter;
10+
import lombok.NoArgsConstructor;
11+
12+
@Getter
13+
@Builder
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
@Schema(description = "대댓글 DTO")
17+
public class RecommentDTO {
18+
19+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
20+
@Schema(description = "대댓글 ID", example = "12", accessMode = Schema.AccessMode.READ_ONLY)
21+
private Long id;
22+
23+
@Schema(description = "대댓글 내용", example = "이 프로젝트 정말 기대돼요!")
24+
private String content;
25+
26+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
27+
@Schema(description = "대댓글 작성자 정보", accessMode = Schema.AccessMode.READ_ONLY)
28+
private ProjectUserResponse user;
29+
30+
public static RecommentDTO fromEntity(RecommentEntity recomment) {
31+
return RecommentDTO.builder()
32+
.id(recomment.getId())
33+
.content(recomment.getContent())
34+
.user(ProjectUserResponse.fromEntity(recomment.getUser()))
35+
.build();
36+
}
37+
}

src/main/java/hs/kr/backend/devpals/domain/project/entity/CommentEntity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ public class CommentEntity {
2222
private Long id;
2323

2424
@ManyToOne(fetch = FetchType.LAZY)
25-
@JoinColumn(name = "project_id", nullable = false)
25+
@JoinColumn(name = "projectId", nullable = false)
2626
private ProjectEntity project;
2727

2828
@ManyToOne(fetch = FetchType.LAZY)
29-
@JoinColumn(name = "user_id", nullable = false)
29+
@JoinColumn(name = "userId", nullable = false)
3030
private UserEntity user;
3131

3232
@Column(nullable = false, length = 255)

src/main/java/hs/kr/backend/devpals/domain/project/entity/ProjectEntity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class ProjectEntity {
4141
// private MethodType method;
4242

4343
@Column(nullable = false)
44-
private Long authorId;
44+
private Long userId;
4545

4646
@Column(nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE")
4747
private boolean isBeginner;
@@ -83,7 +83,7 @@ public static ProjectEntity fromRequest(ProjectAllDto request, Long userId) {
8383
.startDate(request.getStartDate())
8484
.estimatedPeriod(request.getEstimatedPeriod())
8585
.views(0)
86-
.authorId(userId)
86+
.userId(userId)
8787
.isBeginner(request.getIsBeginner() != null ? request.getIsBeginner() : false)
8888
.isDone(request.getIsDone() != null ? request.getIsDone() : false)
8989
.recruitmentStartDate(request.getRecruitmentStartDate())
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package hs.kr.backend.devpals.domain.project.entity;
2+
3+
import hs.kr.backend.devpals.domain.project.dto.RecommentDTO;
4+
import hs.kr.backend.devpals.domain.user.entity.UserEntity;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.Table;
7+
8+
import jakarta.persistence.*;
9+
import lombok.AllArgsConstructor;
10+
import lombok.Builder;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
14+
import java.time.LocalDateTime;
15+
16+
@Entity
17+
@Getter
18+
@Builder
19+
@NoArgsConstructor
20+
@AllArgsConstructor
21+
@Table(name="Recomment")
22+
public class RecommentEntity {
23+
24+
@Id
25+
@GeneratedValue(strategy = GenerationType.IDENTITY)
26+
private Long id;
27+
28+
@ManyToOne(fetch = FetchType.LAZY)
29+
@JoinColumn(name = "projectId", nullable = false)
30+
private ProjectEntity project;
31+
32+
@ManyToOne(fetch = FetchType.LAZY)
33+
@JoinColumn(name = "userId", nullable = false)
34+
private UserEntity user;
35+
36+
@ManyToOne(fetch = FetchType.LAZY)
37+
@JoinColumn(name = "commentId", nullable = false)
38+
private CommentEntity comment;
39+
40+
@Column(nullable = false, length = 255)
41+
private String content;
42+
43+
@Column(nullable = false, updatable = false)
44+
private LocalDateTime createdAt = LocalDateTime.now();
45+
46+
@Column(nullable = false)
47+
private LocalDateTime updatedAt = LocalDateTime.now();
48+
49+
public void updateContent(String content) {
50+
this.content = content;
51+
this.updatedAt = LocalDateTime.now();
52+
}
53+
54+
public static RecommentEntity from(RecommentDTO dto, ProjectEntity project, UserEntity user, CommentEntity comment) {
55+
return RecommentEntity.builder()
56+
.project(project)
57+
.user(user)
58+
.comment(comment)
59+
.content(dto.getContent())
60+
.createdAt(LocalDateTime.now())
61+
.updatedAt(LocalDateTime.now())
62+
.build();
63+
}
64+
}

src/main/java/hs/kr/backend/devpals/domain/project/repository/ProjectRepository.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public interface ProjectRepository extends JpaRepository<ProjectEntity, Long> {
1414
@Query("SELECT p FROM ProjectEntity p WHERE p.recruitmentEndDate = :tomorrow AND p.isDone = false")
1515
List<ProjectEntity> findProjectsEndingTomorrow(@Param("tomorrow") LocalDate tomorrow);
1616

17-
@Query("SELECT p FROM ProjectEntity p WHERE p.authorId = :authorId")
18-
List<ProjectEntity> findProjectsByAuthorId(@Param("authorId") Long AuthorId);
17+
@Query("SELECT p FROM ProjectEntity p WHERE p.userId = :userId")
18+
List<ProjectEntity> findProjectsByUserId(@Param("userId") Long userId);
1919
long count();
2020
long countByIsDoneFalse();
2121
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package hs.kr.backend.devpals.domain.project.repository;
2+
3+
import hs.kr.backend.devpals.domain.project.entity.RecommentEntity;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
import java.util.List;
7+
8+
public interface RecommentRepository extends JpaRepository<RecommentEntity, Long> {
9+
List<RecommentEntity> findAllByCommentId(Long commentId);
10+
}

src/main/java/hs/kr/backend/devpals/domain/project/service/ApplyService.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public ResponseEntity<ApiResponse<List<ProjectApplicantResponse>>> getProjectApp
6464
ProjectEntity project = projectRepository.findById(projectId)
6565
.orElseThrow(() -> new CustomException(ErrorException.PROJECT_NOT_FOUND));
6666

67-
if(!Objects.equals(project.getAuthorId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
67+
if(!Objects.equals(project.getUserId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
6868

6969

7070
List<ApplicantEntity> applicants = applicantRepository.findByProject(project);
@@ -84,7 +84,7 @@ public ResponseEntity<ApiResponse<ProjectApplyDTO>> getProjectApplicantContent(L
8484
ProjectEntity project = projectRepository.findById(projectId)
8585
.orElseThrow(() -> new CustomException(ErrorException.PROJECT_NOT_FOUND));
8686

87-
if (!Objects.equals(project.getAuthorId(), userId)) {
87+
if (!Objects.equals(project.getUserId(), userId)) {
8888
throw new CustomException(ErrorException.AUTHOR_ONLY);
8989
}
9090

@@ -108,7 +108,7 @@ public ResponseEntity<ApiResponse<ProjectApplicantResultResponse>> getProjectApp
108108
ProjectEntity project = projectRepository.findById(projectId)
109109
.orElseThrow(() -> new CustomException(ErrorException.PROJECT_NOT_FOUND));
110110

111-
if(!Objects.equals(project.getAuthorId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
111+
if(!Objects.equals(project.getUserId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
112112

113113

114114
List<ApplicantEntity> applicants = applicantRepository.findByProject(project);
@@ -132,7 +132,7 @@ public ResponseEntity<ApiResponse<ApplicantStatusUpdateResponse>> modifyApplican
132132
//프로젝트 모집을 마감했을 경우 변경불가
133133
if(project.isDone()) throw new CustomException(ErrorException.PROJECT_DONE);
134134
//해당 공고의 기획자가 아닐 경우 조회 불가
135-
if(!Objects.equals(project.getAuthorId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
135+
if(!Objects.equals(project.getUserId(), userId)) throw new CustomException(ErrorException.AUTHOR_ONLY);
136136
//변경하려는 상태와 현재 상태가 동일할 경우 상태 변경 불가
137137
if(applicant.getStatus().toString().equals(status))
138138
throw new CustomException(ErrorException.EQUAL_STATUS);

0 commit comments

Comments
 (0)