Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d628f24
feat: notice 도메인 엔터티 생성 및 글 작성 api 개발
jwooo002 Aug 24, 2025
737e0b1
feat: 글 조회하기 api 개발
jwooo002 Aug 24, 2025
7516614
feat: 글 수정 api 개발
jwooo002 Aug 25, 2025
96dff53
feat: 글 삭제 api 개발
jwooo002 Aug 25, 2025
d1e12b6
feat: 글 상세보기 api 개발, 글 목록 조회 dto 수정
jwooo002 Aug 25, 2025
b9ba9da
fix: room 엔터티에 hostUserNo 저장되지 않는 문제 해결
jwooo002 Aug 25, 2025
e9d16c9
refactor: user 엔터티 room 필드 타입 변경
jwooo002 Aug 29, 2025
0ed0bba
feat: 댓글 작성 api 기능 개발
jwooo002 Sep 6, 2025
25cff7e
refactor: Notice 엔터티 필드 타입 변경에 따른 수정
jwooo002 Sep 6, 2025
0de56ce
Merge branch 'develop' into feat/#14/notice-기능-개발
jwooo002 Dec 24, 2025
8038500
Merge remote-tracking branch 'origin/develop' into feat/#14/notice-기능-개발
jwooo002 Dec 27, 2025
03ccee4
Merge remote-tracking branch 'origin/feat/#14/notice-기능-개발' into feat…
jwooo002 Dec 27, 2025
37f38f1
build: add s3 dependency
jwooo002 Dec 27, 2025
70862de
feat: add s3 config
jwooo002 Dec 27, 2025
1ed8068
feat: add generating s3 presigned url
jwooo002 Dec 27, 2025
9f90f91
feat: add image entity, repository, service
jwooo002 Dec 27, 2025
b997b81
feat: add image to notice create, update, delete, load
jwooo002 Dec 27, 2025
752077f
docs: add api spec
jwooo002 Dec 27, 2025
3999856
feat: add load comment
jwooo002 Dec 27, 2025
709336c
feat: develop update comment api
jwooo002 Dec 27, 2025
8453068
feat: develop delete comment api
jwooo002 Dec 27, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.project.dorumdorum.domain.notice.application.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record UpdateNoticeRequest(
@NotNull Long roomNo,
@NotNull Long noticeNo,
@NotBlank String title,
@NotBlank String content
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.project.dorumdorum.domain.notice.application.dto.request;

public record WriteCommentRequest(
Long noticeNo,
String content
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.project.dorumdorum.domain.notice.application.dto.request;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record WriteNoticeRequest(
@NotNull Long roomNo,
@NotBlank String title,
@NotBlank String content
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.project.dorumdorum.domain.notice.application.dto.response;

import com.project.dorumdorum.domain.notice.domain.entity.Comment;
import lombok.Builder;

import java.time.LocalDateTime;

@Builder
public record CommentResponse(
Long noticeNo,
Long userNo,
LocalDateTime updated_at,
String content
) {
public static CommentResponse create(Comment comment) {
return CommentResponse.builder()
.noticeNo(comment.getNoticeNo())
.userNo(comment.getUserNo())
.updated_at(comment.getUpdatedAt())
.content(comment.getContent())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.project.dorumdorum.domain.notice.application.dto.response;

import com.project.dorumdorum.domain.notice.domain.entity.Notice;

import lombok.Builder;
import java.time.LocalDateTime;

@Builder
public record NoticeResponse(
Long noticeNo,
Long userNo,
LocalDateTime createdAt,
LocalDateTime updatedAt,
String title,
String content
) {
public static NoticeResponse create(Notice notice) {
return NoticeResponse.builder()
.noticeNo(notice.getNoticeNo())
.userNo(notice.getUserNo())
.createdAt(notice.getCreatedAt())
.updatedAt(notice.getUpdatedAt())
.title(notice.getTitle())
.content(notice.getContent())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.project.dorumdorum.domain.notice.application.dto.response;

import com.project.dorumdorum.domain.notice.domain.entity.Notice;
import lombok.Builder;

import java.time.LocalDateTime;

@Builder
public record NoticesResponse(
Long noticeNo,
Long userNo,
LocalDateTime updatedAt,
String title
) {
public static NoticesResponse create(Notice notice) {
return NoticesResponse.builder()
.noticeNo(notice.getNoticeNo())
.userNo(notice.getUserNo())
.updatedAt(notice.getUpdatedAt())
.title(notice.getTitle())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.project.dorumdorum.domain.notice.application.usecase;

import com.project.dorumdorum.domain.notice.domain.entity.Notice;
import com.project.dorumdorum.domain.notice.service.NoticeService;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import com.project.dorumdorum.global.exception.code.status.GlobalErrorStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class DeleteNoticeUseCase {

private final UserService userService;
private final NoticeService noticeService;

public void execute(Long userNo, Long noticeNo) {
userService.validateExistsById(userNo);

Notice notice = noticeService.findById(noticeNo);

if(notice.isDeleted())
throw new RestApiException(GlobalErrorStatus.NOTICE_ALREADY_DELETED);
if(!notice.isWriter(userNo))
throw new RestApiException(GlobalErrorStatus.NO_PERMISSION_ON_NOTICE);

noticeService.deleteNotice(noticeNo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.project.dorumdorum.domain.notice.application.usecase;

import com.project.dorumdorum.domain.notice.application.dto.response.NoticeResponse;
import com.project.dorumdorum.domain.notice.application.dto.response.NoticesResponse;
import com.project.dorumdorum.domain.notice.service.NoticeService;
import com.project.dorumdorum.domain.room.domain.entity.Room;
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.room.domain.service.RoommateService;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import com.project.dorumdorum.global.exception.code.status.GlobalErrorStatus;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
@RequiredArgsConstructor
public class LoadNoticesUseCase {

private final UserService userService;
private final RoommateService roommateService;
private final RoomService roomService;
private final NoticeService noticeService;

public List<NoticesResponse> loadNotices(Long userNo, Long roomNo) {
userService.validateExistsById(userNo);

Room room = roomService.findById(roomNo);
if(!roommateService.isUserInRoom(userNo, room))
throw new RestApiException(GlobalErrorStatus.USER_NOT_IN_ROOM);

return noticeService.loadNoticeList(room.getRoomNo());
}

public NoticeResponse loadNotice(Long userNo, Long noticeNo) {
userService.validateExistsById(userNo);

return noticeService.loadNotice(noticeNo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.project.dorumdorum.domain.notice.application.usecase;

import com.project.dorumdorum.domain.notice.application.dto.request.UpdateNoticeRequest;
import com.project.dorumdorum.domain.notice.application.dto.response.NoticeResponse;
import com.project.dorumdorum.domain.notice.domain.entity.Notice;
import com.project.dorumdorum.domain.notice.service.NoticeService;
import com.project.dorumdorum.domain.room.domain.entity.Room;
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import com.project.dorumdorum.global.exception.code.status.GlobalErrorStatus;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class UpdateNoticeUseCase {

private final UserService userService;
private final RoomService roomService;
private final NoticeService noticeService;

@Transactional
public NoticeResponse execute(Long userNo, UpdateNoticeRequest request) {
userService.validateExistsById(userNo);

Room room = roomService.findById(request.roomNo());

// 방장이 아닌 구성원도 작성가능 할 경우 삭제
if(!room.isHost(userNo))
throw new RestApiException(GlobalErrorStatus.NO_PERMISSION_ON_NOTICE);

Notice notice = noticeService.findById(request.noticeNo());

if(!notice.isWriter(userNo))
throw new RestApiException(GlobalErrorStatus.NO_PERMISSION_ON_NOTICE);

return noticeService.updateNotice(notice, request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.project.dorumdorum.domain.notice.application.usecase;


import com.project.dorumdorum.domain.notice.application.dto.request.WriteCommentRequest;
import com.project.dorumdorum.domain.notice.application.dto.response.CommentResponse;
import com.project.dorumdorum.domain.notice.domain.entity.Comment;
import com.project.dorumdorum.domain.notice.domain.entity.Notice;
import com.project.dorumdorum.domain.notice.service.CommentService;
import com.project.dorumdorum.domain.notice.service.NoticeService;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import com.project.dorumdorum.global.exception.code.status.GlobalErrorStatus;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class WriteCommentUseCase {

private final UserService userService;
private final NoticeService noticeService;
private final CommentService commentService;

public CommentResponse execute(Long userNo, WriteCommentRequest request) {
userService.validateExistsById(userNo);

Notice notice = noticeService.findById(request.noticeNo());

if(request.content().isEmpty())
throw new RestApiException(GlobalErrorStatus.CONTENT_IS_EMPTY);
Comment comment = commentService.saveComment(userNo, notice.getNoticeNo(), request.content());

return CommentResponse.create(comment);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.project.dorumdorum.domain.notice.application.usecase;

import com.project.dorumdorum.domain.notice.application.dto.request.WriteNoticeRequest;
import com.project.dorumdorum.domain.notice.application.dto.response.NoticeResponse;
import com.project.dorumdorum.domain.notice.service.NoticeService;
import com.project.dorumdorum.domain.room.domain.entity.Room;
import com.project.dorumdorum.domain.room.domain.service.RoomService;
import com.project.dorumdorum.domain.user.domain.service.UserService;
import com.project.dorumdorum.global.exception.RestApiException;
import com.project.dorumdorum.global.exception.code.status.GlobalErrorStatus;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class WriteNoticeUseCase {

private final UserService userService;
private final NoticeService noticeService;
private final RoomService roomService;

@Transactional
public NoticeResponse execute(Long userNo, WriteNoticeRequest request) {
userService.validateExistsById(userNo);

if(request.title().isEmpty())
throw new RestApiException(GlobalErrorStatus.TITLE_IS_EMPTY);
if(request.content().isEmpty())
throw new RestApiException(GlobalErrorStatus.CONTENT_IS_EMPTY);

Room room = roomService.findById(request.roomNo());
if(!room.isHost(userNo))
throw new RestApiException(GlobalErrorStatus.NO_PERMISSION_ON_NOTICE);


return NoticeResponse.create(noticeService.writeNotice(userNo, room.getRoomNo(), request));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.project.dorumdorum.domain.notice.domain.entity;

import com.project.dorumdorum.global.common.BaseEntity;
import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.*;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Builder
public class Comment extends BaseEntity {

@Id @Tsid
private Long commentNo;

@Column(nullable = false)
private Long userNo;

@Column(nullable = false)
private Long noticeNo;

@Column(nullable = false)
private String content;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.project.dorumdorum.domain.notice.domain.entity;

import com.project.dorumdorum.global.common.BaseEntity;

import io.hypersistence.utils.hibernate.id.Tsid;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import lombok.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
public class Notice extends BaseEntity {
@Id @Tsid
private Long noticeNo;

@Column(nullable = false)
private Long roomNo;

@Column(nullable = false)
private Long userNo;

@Column(nullable = false)
private String title;

@Column(nullable = false)
private String content;

public void update(@NotBlank String title, @NotBlank String content) {
this.title = title;
this.content = content;
}

public boolean isWriter(Long userNo) {
return this.userNo.equals(userNo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.project.dorumdorum.domain.notice.domain.repository;

import com.project.dorumdorum.domain.notice.domain.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.project.dorumdorum.domain.notice.domain.repository;

import com.project.dorumdorum.domain.notice.domain.entity.Notice;

import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;

public interface NoticeRepository extends JpaRepository<Notice, Long> {

List<Notice> findByRoomNo(Long roomNo);
}
Loading