Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d53473c
feat/#10: 학생회 제휴 게시글 생성/수정/조회/삭제 기능 구현
jjaeroong Dec 7, 2025
286901a
refactor/#10: 학생회 제휴/행사 게시글 생성 중, 이미지 presignedUrl temp 호출 후 게시글 생성 시…
jjaeroong Dec 22, 2025
88a18ec
refactor/#10: 불필요한 임포트 및 미사용 파일 제거
jjaeroong Dec 22, 2025
0ce0f50
refactor/#10: 게시글 생성 시, date 및 place 필드 저장 에러 수정
jjaeroong Dec 22, 2025
95a182a
refactor/#10: 게시글 생성 시, presingedUrl 로직 수정
jjaeroong Dec 23, 2025
c88440d
refactor/#10: 게시글 생성 시, 이미지 전용 presingedUrl API 생성
jjaeroong Dec 23, 2025
4644afd
refactor/#10: 게시글 생성 시, 이미지 sequence 필드 삭제 및 스웨거 API 설명 추가
jjaeroong Dec 23, 2025
dd47065
Merge dev into feature/#10
jjaeroong Dec 23, 2025
474738e
refactor/#10: ociConfig 필요한 필드에 getter 추가
jjaeroong Dec 23, 2025
fe1a223
refactor/#10: 행사/제휴 게시글 날짜·시간 처리 로직 분리
jjaeroong Dec 23, 2025
d8ba38c
refactor/#10: builder -> mapper 전환 및 presignedUrl 파일명 수정
jjaeroong Dec 27, 2025
3f950f8
refactor/#10: 사용하지 않는 import 제거
jjaeroong Dec 27, 2025
b4cab94
style/#10: 네이버 코드 포매터 적용
jjaeroong Dec 27, 2025
9f29cb4
style/#10: 파일별 마지막 줄 개행적용
jjaeroong Dec 27, 2025
9a97b17
refactor/#10: deletePost 컨트롤러 사용하지 않는 어노테이션 제거
jjaeroong Dec 27, 2025
dbe58c2
refactor/#10: ociConfig 수정 및 application-test 파일 추가
jjaeroong Dec 27, 2025
b71f9d1
refactor/#10: application-test 파일 수정
jjaeroong 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
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ dependencies {
// mail
implementation 'org.springframework.boot:spring-boot-starter-mail'

// OCI SDK BOM
implementation platform('com.oracle.oci.sdk:oci-java-sdk-bom:3.31.0')

// OCI ObjectStorage
implementation 'com.oracle.oci.sdk:oci-java-sdk-objectstorage'
implementation 'com.oracle.oci.sdk:oci-java-sdk-common'

//HTTP 클라이언트
implementation 'com.oracle.oci.sdk:oci-java-sdk-common-httpclient-jersey3'

compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,12 @@ public class StudentCouncil extends BaseEntity {
public void changePassword(String newPassword) {
this.password = newPassword;
}

public String getFullCouncilName() {
StringBuilder fullName = new StringBuilder();
if (school != null) fullName.append(school.getSchoolName());
if (college != null) fullName.append(" ").append(college.getCollegeName());
if (major != null) fullName.append(" ").append(major.getMajorName());
return fullName.append(" 학생회").toString().trim();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.campus.campus.domain.studentcouncilpost.application.dto;

import com.campus.campus.domain.studentcouncilpost.domain.entity.PostCategory;
import com.campus.campus.domain.studentcouncilpost.domain.entity.ThumbnailIcon;
import java.time.LocalDateTime;

public record PostListItemResponseDto(
Long id,
PostCategory category,
String title,
String place,
LocalDateTime endDateTime,
String thumbnailImageUrl,
ThumbnailIcon thumbnailIcon,
Boolean isWriter
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.campus.campus.domain.studentcouncilpost.application.dto;

import com.campus.campus.domain.studentcouncilpost.domain.entity.PostCategory;
import com.campus.campus.domain.studentcouncilpost.domain.entity.ThumbnailIcon;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;

public record PostRequestDto(

@NotNull
PostCategory category,

@NotBlank
String title,

@NotBlank
String content,

String place,

@Schema(example = "2025-04-10T18:00")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
LocalDateTime startDateTime,

@Schema(example = "2025-04-30T23:59")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
LocalDateTime endDateTime,

// 썸네일 (둘 중 하나는 필수)
String thumbnailImageUrl,
ThumbnailIcon thumbnailIcon,

// 본문 이미지들
List<String> imageUrls
) {}
Copy link
Member

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,36 @@
package com.campus.campus.domain.studentcouncilpost.application.dto;

import com.campus.campus.domain.studentcouncilpost.domain.entity.PostCategory;
import com.campus.campus.domain.studentcouncilpost.domain.entity.ThumbnailIcon;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PostResponseDto {
private Long id;
private Long writerId;
private String writerName;
private Boolean isWriter;

private PostCategory category;
private String title;
private String content;

private String place;

private LocalDate startDate;
private LocalDate endDate;
private LocalDateTime startDateTime;


private String thumbnailImageUrl;
private ThumbnailIcon thumbnailIcon;

private List<String> images;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ErrorCodeInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum ErrorCode implements ErrorCodeInterface {

POST_NOT_FOUND(2401, HttpStatus.NOT_FOUND, "게시글을 찾을 수 없습니다."),
NOT_POST_WRITER(2402, HttpStatus.FORBIDDEN, "작성자만 해당 작업을 수행할 수 있습니다."),
THUMBNAIL_REQUIRED(2403, HttpStatus.BAD_REQUEST, "썸네일(이미지 또는 아이콘)은 반드시 필요합니다."),

// EVENT 관련
EVENT_START_DATETIME_REQUIRED(2405, HttpStatus.BAD_REQUEST, "행사는 시작 일시가 필요합니다."),
EVENT_END_DATETIME_NOT_ALLOWED(2406, HttpStatus.BAD_REQUEST, "행사는 종료 일시를 가질 수 없습니다."),

// PARTNERSHIP 관련
PARTNERSHIP_DATE_REQUIRED(2407, HttpStatus.BAD_REQUEST, "제휴는 시작일과 종료일이 필요합니다.");

private final int code;
private final HttpStatus status;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class EventEndDateTimeNotAllowedException extends ApplicationException {
public EventEndDateTimeNotAllowedException() {
super(ErrorCode.EVENT_END_DATETIME_NOT_ALLOWED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class EventStartDateTimeRequiredException extends ApplicationException {
public EventStartDateTimeRequiredException() {
super(ErrorCode.EVENT_START_DATETIME_REQUIRED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class NotPostWriterException extends ApplicationException {
public NotPostWriterException() {
super(ErrorCode.NOT_POST_WRITER);
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class PartnershipDateRequiredException extends ApplicationException {
public PartnershipDateRequiredException() {
super(ErrorCode.PARTNERSHIP_DATE_REQUIRED);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class PostNotFoundException extends ApplicationException {
public PostNotFoundException() {
super(ErrorCode.POST_NOT_FOUND);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.campus.campus.domain.studentcouncilpost.application.exception;

import com.campus.campus.global.common.exception.ApplicationException;

public class ThumbnailRequiredException extends ApplicationException {
public ThumbnailRequiredException() {
super(ErrorCode.THUMBNAIL_REQUIRED);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.campus.campus.domain.studentcouncilpost.application.mapper;

import com.campus.campus.domain.studentcouncilpost.application.dto.PostListItemResponseDto;
import com.campus.campus.domain.studentcouncilpost.application.dto.PostResponseDto;
import com.campus.campus.domain.studentcouncilpost.domain.entity.StudentCouncilPost;
import java.util.Collections;
import java.util.List;

public class StudentCouncilPostMapper {

public static PostListItemResponseDto toListItem(
StudentCouncilPost post,
Long currentUserId
) {
return new PostListItemResponseDto(
post.getId(),
post.getCategory(),
post.getTitle(),
post.getPlace(),
post.getEndDateTime(),
post.getThumbnailImageUrl(),
post.getThumbnailIcon(),
currentUserId != null && post.getWriter().getId().equals(currentUserId)
);

}

public static PostResponseDto toDetail(
StudentCouncilPost post,
List<String> images,
Long currentUserId
) {

var writer = post.getWriter();
var builder = PostResponseDto.builder()
.id(post.getId())
.writerId(writer.getId())
.writerName(writer.getFullCouncilName())
.isWriter(post.isWrittenBy(currentUserId))
.category(post.getCategory())
.title(post.getTitle())
.content(post.getContent())
.place(post.getPlace())
.thumbnailImageUrl(post.getThumbnailImageUrl())
.thumbnailIcon(post.getThumbnailIcon())
.images(images != null ? images : Collections.emptyList());

if (post.isEvent()) {
builder.startDateTime(post.getStartDateTime());
} else {
builder.startDate(post.getDisplayStartDate());
builder.endDate(post.getDisplayEndDate());
}

return builder.build();
}

}
Loading
Loading