Skip to content

Commit

Permalink
feat: 공지사항 단일 조회 API 구현 (#279)
Browse files Browse the repository at this point in the history
* refactor: Exception 클래스 계층 구조 변경

* feat: 공지사항 단일 조회 API 구현

* test: 공지사항 단일 조회 API Controller, Service 테스트 코드 작성

* chore: data.sql 공지사항 더미데이터 추가

* docs: ERD에서 notice_image 테이블 sequence 컬럼 추가 및 오타 수정

* deploy: notice_image 테이블 생성 flyway 스크립트 추가
  • Loading branch information
leeeeeyeon committed Sep 2, 2024
1 parent 26ee472 commit 9c97c2a
Show file tree
Hide file tree
Showing 29 changed files with 201 additions and 49 deletions.
57 changes: 45 additions & 12 deletions db.vuerd.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"settings": {
"width": 2500,
"height": 2500,
"scrollTop": -587,
"scrollTop": -535,
"scrollLeft": -254.4,
"zoomLevel": 0.8,
"show": 431,
Expand Down Expand Up @@ -514,12 +514,14 @@
"columnIds": [
"cQkQYlH9QGKbVhLkix1H8",
"6UzHg3KECgLvrLHIlr2xR",
"1MqGj1Vu058uQDoS8bH-D"
"1MqGj1Vu058uQDoS8bH-D",
"WZFhUACICiTTI8hRlpZ7W"
],
"seqColumnIds": [
"cQkQYlH9QGKbVhLkix1H8",
"6UzHg3KECgLvrLHIlr2xR",
"1MqGj1Vu058uQDoS8bH-D"
"1MqGj1Vu058uQDoS8bH-D",
"WZFhUACICiTTI8hRlpZ7W"
],
"ui": {
"x": 714,
Expand All @@ -530,7 +532,7 @@
"color": ""
},
"meta": {
"updateAt": 1725272093595,
"updateAt": 1725278006200,
"createAt": 1725271961676
}
}
Expand Down Expand Up @@ -2023,16 +2025,16 @@
"comment": "",
"dataType": "BIGINT",
"default": "",
"options": 8,
"options": 10,
"ui": {
"keys": 0,
"keys": 1,
"widthName": 60,
"widthComment": 60,
"widthDataType": 60,
"widthDefault": 60
},
"meta": {
"updateAt": 1725272091412,
"updateAt": 1725279951124,
"createAt": 1725272066539
}
},
Expand Down Expand Up @@ -2061,7 +2063,7 @@
"tableId": "lRihpM29ZxxS_B8lgaufh",
"name": "imgUrl",
"comment": "",
"dataType": "TEX",
"dataType": "TEXT",
"default": "",
"options": 8,
"ui": {
Expand All @@ -2072,9 +2074,29 @@
"widthDefault": 60
},
"meta": {
"updateAt": 1725272100277,
"updateAt": 1725279959539,
"createAt": 1725272093595
}
},
"WZFhUACICiTTI8hRlpZ7W": {
"id": "WZFhUACICiTTI8hRlpZ7W",
"tableId": "lRihpM29ZxxS_B8lgaufh",
"name": "sequence",
"comment": "",
"dataType": "BIGINT",
"default": "",
"options": 8,
"ui": {
"keys": 0,
"widthName": 60,
"widthComment": 60,
"widthDataType": 60,
"widthDefault": 60
},
"meta": {
"updateAt": 1725278015692,
"createAt": 1725278006200
}
}
},
"relationshipEntities": {
Expand Down Expand Up @@ -2406,7 +2428,7 @@
"6UzHg3KECgLvrLHIlr2xR"
],
"x": 714,
"y": 1171.6669,
"y": 1183.6669,
"direction": 1
},
"meta": {
Expand Down Expand Up @@ -2553,7 +2575,8 @@
{
"name": 1725272085087,
"dataType": 1725272088183,
"options(notNull)": 1725272091412
"options(notNull)": 1725272091412,
"options(primaryKey)": 1725279951122
}
],
"6UzHg3KECgLvrLHIlr2xR": [
Expand All @@ -2580,9 +2603,19 @@
-1,
{
"name": 1725272095690,
"dataType": 1725272097579,
"dataType": 1725279959538,
"options(notNull)": 1725272100276
}
],
"WZFhUACICiTTI8hRlpZ7W": [
"tableColumnEntities",
1725278006198,
-1,
{
"name": 1725278009885,
"dataType": 1725278013500,
"options(notNull)": 1725278015691
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
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;
Expand Down Expand Up @@ -132,4 +133,11 @@ public DataResponseDto<UrlResponse> createBranchUrl(
public DataResponseDto<List<NoticeResponse>> getNotices() {
return DataResponseDto.from(adminService.getNotices());
}

@Operation(summary = "공지사항 단일 조회")
@GetMapping("/notices/web/{noticeId}")
public DataResponseDto<List<String>> getNotice(
@PathVariable Long noticeId) {
return DataResponseDto.from(adminService.getNotice(noticeId));
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.dilly.admin.application;

import com.dilly.admin.adaptor.NoticeImageReader;
import com.dilly.admin.adaptor.NoticeReader;
import com.dilly.admin.adaptor.SettingReader;
import com.dilly.admin.domain.music.Music;
import com.dilly.admin.domain.notice.Notice;
import com.dilly.admin.domain.notice.NoticeImage;
import com.dilly.admin.domain.setting.Setting;
import com.dilly.admin.dto.response.BoxImgResponse;
import com.dilly.admin.dto.response.ImgResponse;
Expand Down Expand Up @@ -42,6 +44,7 @@ public class AdminService {
private final StickerReader stickerReader;
private final SettingReader settingReader;
private final NoticeReader noticeReader;
private final NoticeImageReader noticeImageReader;

public List<ImgResponse> getProfiles() {
List<ProfileImage> profileImages = profileImageReader.findAllByOrderBySequenceAsc();
Expand Down Expand Up @@ -91,4 +94,11 @@ public List<NoticeResponse> getNotices() {

return notices.stream().map(NoticeResponse::from).toList();
}

public List<String> getNotice(Long noticeId) {
Notice notice = noticeReader.findById(noticeId);
List<NoticeImage> noticeImages = noticeImageReader.findAllByNoticeOrderBySequence(notice);

return noticeImages.stream().map(NoticeImage::getImgUrl).toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.dilly.global.util;

import com.dilly.exception.AuthorizationFailedException;
import com.dilly.exception.ErrorCode;
import com.dilly.exception.authorizationfailed.AuthorizationFailedException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
2 changes: 1 addition & 1 deletion packy-api/src/main/java/com/dilly/jwt/JwtService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.dilly.jwt;

import com.dilly.exception.AuthorizationFailedException;
import com.dilly.exception.ErrorCode;
import com.dilly.exception.authorizationfailed.AuthorizationFailedException;
import com.dilly.jwt.adaptor.JwtReader;
import com.dilly.jwt.adaptor.JwtWriter;
import com.dilly.jwt.dto.JwtRequest;
Expand Down
2 changes: 1 addition & 1 deletion packy-api/src/main/java/com/dilly/jwt/TokenProvider.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.dilly.jwt;

import com.dilly.exception.AuthorizationFailedException;
import com.dilly.exception.ErrorCode;
import com.dilly.exception.authorizationfailed.AuthorizationFailedException;
import com.dilly.jwt.dto.JwtResponse;
import com.dilly.member.domain.Member;
import io.jsonwebtoken.Claims;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import static com.dilly.global.constant.Constants.MINIMUM_REQUIRED_VERSION;

import com.dilly.exception.AuthorizationFailedException;
import com.dilly.exception.BadRequestException;
import com.dilly.exception.ErrorCode;
import com.dilly.exception.authorizationfailed.AuthorizationFailedException;
import com.dilly.exception.internalserver.InternalServerException;
import com.dilly.global.util.SecurityUtil;
import com.dilly.member.adaptor.MemberReader;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dilly.admin.api;

import static org.hamcrest.Matchers.hasSize;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.BDDMockito.given;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
Expand Down Expand Up @@ -272,4 +273,23 @@ void getNotices() throws Exception {
.andExpect(jsonPath("$.data").isArray())
.andExpect(jsonPath("$.data", hasSize(3)));
}

@DisplayName("공지사항을 조회한다.")
@Test
@WithCustomMockUser
void getNotice() throws Exception {
// given
List<String> noticeResponse = List.of("www.test1.com", "www.test2.com", "www.test3.com");

given(adminService.getNotice(anyLong())).willReturn(noticeResponse);

// when // then
mockMvc.perform(
get(baseUrl + "/admin/notices/web/" + anyLong())
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").isArray())
.andExpect(jsonPath("$.data", hasSize(3)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.dilly.BoxFixture;
import com.dilly.admin.domain.notice.Notice;
import com.dilly.admin.domain.notice.NoticeImage;
import com.dilly.admin.dto.response.BoxImgResponse;
import com.dilly.admin.dto.response.ImgResponse;
import com.dilly.admin.dto.response.MusicResponse;
Expand Down Expand Up @@ -109,4 +111,22 @@ void getNotices() {
// then
assertThat(response).isEqualTo(notices);
}

@DisplayName("공지사항을 조회한다.")
@Test
void getNotice() {
// given
Long noticeId = 1L;
Notice notice = noticeReader.findById(noticeId);

List<String> noticeImages = noticeImageReader.findAllByNoticeOrderBySequence(notice)
.stream().map(NoticeImage::getImgUrl)
.toList();

// when
List<String> response = adminService.getNotice(noticeId);

// then
assertThat(response).isEqualTo(noticeImages);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;

import com.dilly.exception.EntityNotFoundException;
import com.dilly.exception.GiftBoxAccessDeniedException;
import com.dilly.exception.GiftBoxAlreadyDeletedException;
import com.dilly.exception.GiftBoxAlreadyOpenedException;
import com.dilly.exception.UnsupportedException;
import com.dilly.exception.entitynotfound.EntityNotFoundException;
import com.dilly.gift.domain.Photo;
import com.dilly.gift.domain.giftbox.DeliverStatus;
import com.dilly.gift.domain.giftbox.GiftBox;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.mockito.BDDMockito.given;

import com.dilly.admin.adaptor.AdminGiftBoxReader;
import com.dilly.admin.adaptor.NoticeImageReader;
import com.dilly.admin.adaptor.NoticeReader;
import com.dilly.admin.adaptor.SettingReader;
import com.dilly.admin.application.AdminService;
Expand Down Expand Up @@ -145,6 +146,9 @@ public abstract class IntegrationTestSupport {
@Autowired
protected NoticeReader noticeReader;

@Autowired
protected NoticeImageReader noticeImageReader;

@Autowired
protected WithCustomMockUserSecurityContextFactory withCustomMockUserSecurityContextFactory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.dilly.exception.authorizationfailed.AuthorizationFailedException;
import com.dilly.exception.AuthorizationFailedException;
import com.dilly.global.IntegrationTestSupport;
import com.dilly.global.WithCustomMockUser;
import com.dilly.jwt.RefreshToken;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
package com.dilly.exception.authorizationfailed;

import com.dilly.exception.BusinessException;
import com.dilly.exception.ErrorCode;
package com.dilly.exception;

public class AuthorizationFailedException extends BusinessException {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
package com.dilly.exception.entitynotfound;

import com.dilly.exception.BusinessException;
import com.dilly.exception.ErrorCode;
package com.dilly.exception;

public class EntityNotFoundException extends BusinessException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public enum ErrorCode {
GIFTBOX_NOT_FOUND(HttpStatus.NOT_FOUND, "선물박스를 찾을 수 없습니다."),
PHOTO_NOT_FOUND(HttpStatus.NOT_FOUND, "사진을 찾을 수 없습니다."),
LETTER_NOT_FOUND(HttpStatus.NOT_FOUND, "편지를 찾을 수 없습니다."),
NOTICE_NOT_FOUND(HttpStatus.NOT_FOUND, "공지사항을 찾을 수 없습니다."),

// Unsupported
UNSUPPORTED_LOGIN_TYPE(HttpStatus.BAD_REQUEST, "지원하지 않는 로그인 타입입니다."),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.dilly.admin.adaptor;

import com.dilly.admin.dao.NoticeImageRepository;
import com.dilly.admin.domain.notice.Notice;
import com.dilly.admin.domain.notice.NoticeImage;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class NoticeImageReader {

private final NoticeImageRepository noticeImageRepository;

public List<NoticeImage> findAllByNoticeOrderBySequence(Notice notice) {
return noticeImageRepository.findAllByNoticeOrderBySequence(notice);
}
}
Loading

0 comments on commit 9c97c2a

Please sign in to comment.