From 9871fc2445383f9031b91919c3df9f25a2fd0d46 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 02:57:54 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lost_item/domain/LostItemDetail.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/main/java/org/mju_likelion/festival/lost_item/domain/LostItemDetail.java diff --git a/src/main/java/org/mju_likelion/festival/lost_item/domain/LostItemDetail.java b/src/main/java/org/mju_likelion/festival/lost_item/domain/LostItemDetail.java new file mode 100644 index 0000000..94adddc --- /dev/null +++ b/src/main/java/org/mju_likelion/festival/lost_item/domain/LostItemDetail.java @@ -0,0 +1,30 @@ +package org.mju_likelion.festival.lost_item.domain; + +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class LostItemDetail { + + private final UUID id; + private final String title; + private final String content; + private final String imageUrl; + private final LocalDateTime createdAt; + private final Boolean isFounded; + + @Override + public String toString() { + return "SimpleLostItem{" + + "id=" + id + '\'' + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", createdAt=" + createdAt + '\'' + + ", isFounded=" + isFounded + + '}'; + } +} From 9bc8423dcfa067f0435b2d2978c3344747faaf65 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 02:58:06 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=9D=91=EB=8B=B5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/LostItemDetailResponse.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/main/java/org/mju_likelion/festival/lost_item/dto/response/LostItemDetailResponse.java diff --git a/src/main/java/org/mju_likelion/festival/lost_item/dto/response/LostItemDetailResponse.java b/src/main/java/org/mju_likelion/festival/lost_item/dto/response/LostItemDetailResponse.java new file mode 100644 index 0000000..427137c --- /dev/null +++ b/src/main/java/org/mju_likelion/festival/lost_item/dto/response/LostItemDetailResponse.java @@ -0,0 +1,53 @@ +package org.mju_likelion.festival.lost_item.dto.response; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import java.time.LocalDateTime; +import java.util.UUID; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.mju_likelion.festival.lost_item.domain.LostItemDetail; + +@Getter +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@NoArgsConstructor +public class LostItemDetailResponse { + + private UUID id; + private String title; + private String content; + private String imageUrl; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime createdAt; + private Boolean isFounded; + + public static LostItemDetailResponse from(final LostItemDetail lostItemDetail) { + return new LostItemDetailResponse( + lostItemDetail.getId(), + lostItemDetail.getTitle(), + lostItemDetail.getContent(), + lostItemDetail.getImageUrl(), + lostItemDetail.getCreatedAt(), + lostItemDetail.getIsFounded() + ); + } + + @Override + public String toString() { + return "SimpleLostItem{" + + "id=" + id + '\'' + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", createdAt=" + createdAt + '\'' + + ", isFounded=" + isFounded + + '}'; + } +} From 4b7053ff3b9e30d4e1d710a1c77058e5fd704926 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 02:58:59 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/LostItemQueryRepository.java | 32 +++++++++++++++++++ .../service/LostItemQueryService.java | 17 ++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/main/java/org/mju_likelion/festival/lost_item/domain/repository/LostItemQueryRepository.java b/src/main/java/org/mju_likelion/festival/lost_item/domain/repository/LostItemQueryRepository.java index ad33fe4..85c2800 100644 --- a/src/main/java/org/mju_likelion/festival/lost_item/domain/repository/LostItemQueryRepository.java +++ b/src/main/java/org/mju_likelion/festival/lost_item/domain/repository/LostItemQueryRepository.java @@ -1,11 +1,13 @@ package org.mju_likelion.festival.lost_item.domain.repository; import static org.mju_likelion.festival.common.util.uuid.UUIDUtil.hexToUUID; +import static org.mju_likelion.festival.common.util.uuid.UUIDUtil.uuidToHex; import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.mju_likelion.festival.common.enums.SortOrder; +import org.mju_likelion.festival.lost_item.domain.LostItemDetail; import org.mju_likelion.festival.lost_item.domain.SimpleLostItem; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @@ -17,6 +19,7 @@ public class LostItemQueryRepository { private final RowMapper simpleLostItemRowMapper = simpleLostItemRowMapper(); + private final RowMapper lostItemDetailRowMapper = lostItemDetailRowMapper(); private final NamedParameterJdbcTemplate jdbcTemplate; private RowMapper simpleLostItemRowMapper() { @@ -34,6 +37,21 @@ private RowMapper simpleLostItemRowMapper() { }; } + private RowMapper lostItemDetailRowMapper() { + return (rs, rowNum) -> { + String hexId = rs.getString("lostItemId"); + UUID uuid = hexToUUID(hexId); + return new LostItemDetail( + uuid, + rs.getString("title"), + rs.getString("content"), + rs.getString("imageUrl"), + rs.getTimestamp("createdAt").toLocalDateTime(), + rs.getBoolean("isFounded") + ); + }; + } + /** * 페이지네이션을 적용하여 분실물 간단 정보 List 조회. * @@ -128,4 +146,18 @@ public int findTotalPageByKeyword(final String keyword, final int size) { return jdbcTemplate.queryForObject(sql, params, Integer.class); } + + public LostItemDetail findLostItemDetailById(final UUID id) { + String sql = "SELECT HEX(li.id) AS lostItemId, li.title AS title, li.content AS content, " + + "CASE WHEN li.retriever_info IS NULL THEN FALSE ELSE TRUE END AS isFounded, " + + "i.url AS imageUrl, li.created_at AS createdAt " + + "FROM lost_item li " + + "INNER JOIN image i ON li.image_id = i.id " + + "WHERE li.id = UNHEX(:id)"; + + MapSqlParameterSource params = new MapSqlParameterSource() + .addValue("id", uuidToHex(id)); + + return jdbcTemplate.queryForObject(sql, params, lostItemDetailRowMapper); + } } diff --git a/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemQueryService.java b/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemQueryService.java index 899b5d1..071acf8 100644 --- a/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemQueryService.java +++ b/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemQueryService.java @@ -9,10 +9,13 @@ import org.mju_likelion.festival.common.enums.SortOrder; import org.mju_likelion.festival.common.exception.NotFoundException; import org.mju_likelion.festival.lost_item.domain.LostItem; +import org.mju_likelion.festival.lost_item.domain.LostItemDetail; import org.mju_likelion.festival.lost_item.domain.SimpleLostItem; import org.mju_likelion.festival.lost_item.domain.repository.LostItemJpaRepository; import org.mju_likelion.festival.lost_item.domain.repository.LostItemQueryRepository; +import org.mju_likelion.festival.lost_item.dto.response.LostItemDetailResponse; import org.mju_likelion.festival.lost_item.dto.response.SimpleLostItemsResponse; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,6 +58,14 @@ public SimpleLostItemsResponse searchLostItems( return SimpleLostItemsResponse.of(simpleLostItems, totalPage); } + @Cacheable(value = "lostItem", key = "#lostItemId") + public LostItemDetailResponse getLostItem(final UUID lostItemId) { + validateLostItemExistence(lostItemId); + LostItemDetail lostItemDetail = lostItemQueryRepository.findLostItemDetailById(lostItemId); + + return LostItemDetailResponse.from(lostItemDetail); + } + public LostItem getExistLostItem(final UUID lostItemId) { return lostItemJpaRepository.findById(lostItemId) .orElseThrow(() -> new NotFoundException(LOST_ITEM_NOT_FOUND_ERROR)); @@ -65,4 +76,10 @@ public void validatePage(final int page, final int totalPage) { throw new NotFoundException(PAGE_OUT_OF_BOUND_ERROR); } } + + public void validateLostItemExistence(final UUID lostItemId) { + if (!lostItemJpaRepository.existsById(lostItemId)) { + throw new NotFoundException(LOST_ITEM_NOT_FOUND_ERROR); + } + } } From 8bce8b4d472dd58a28f09e75b48dc9c463d9037f Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 02:59:22 +0900 Subject: [PATCH 4/8] =?UTF-8?q?style:=20=EC=8A=AC=EB=9E=98=EC=89=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../festival/lost_item/domain/SimpleLostItem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mju_likelion/festival/lost_item/domain/SimpleLostItem.java b/src/main/java/org/mju_likelion/festival/lost_item/domain/SimpleLostItem.java index 37b3775..908f1ed 100644 --- a/src/main/java/org/mju_likelion/festival/lost_item/domain/SimpleLostItem.java +++ b/src/main/java/org/mju_likelion/festival/lost_item/domain/SimpleLostItem.java @@ -19,11 +19,11 @@ public class SimpleLostItem { @Override public String toString() { return "SimpleLostItem{" + - "id=" + id + + "id=" + id + '\'' + ", title='" + title + '\'' + ", content='" + content + '\'' + ", imageUrl='" + imageUrl + '\'' + - ", createdAt=" + createdAt + + ", createdAt=" + createdAt + '\'' + ", isFounded=" + isFounded + '}'; } From 703c81b666843035a4227416ccecd31a9809464c Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 02:59:47 +0900 Subject: [PATCH 5/8] =?UTF-8?q?refactor:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=B3=80=EA=B2=BD=20=EC=8B=9C=20=EC=BA=90?= =?UTF-8?q?=EC=8B=9C=20=EC=A7=80=EC=9A=B0=EB=8F=84=EB=A1=9D=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../festival/lost_item/service/LostItemService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemService.java b/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemService.java index 36633df..c1e0fda 100644 --- a/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemService.java +++ b/src/main/java/org/mju_likelion/festival/lost_item/service/LostItemService.java @@ -12,6 +12,7 @@ import org.mju_likelion.festival.lost_item.dto.request.CreateLostItemRequest; import org.mju_likelion.festival.lost_item.dto.request.LostItemFoundRequest; import org.mju_likelion.festival.lost_item.dto.request.UpdateLostItemRequest; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,6 +41,7 @@ public void createLostItem( lostItemJpaRepository.save(lostItem); } + @CacheEvict(value = "lostItem", key = "#lostItemId") public void updateLostItem( final UUID lostItemId, final UpdateLostItemRequest updateLostItemRequest, @@ -53,6 +55,7 @@ public void updateLostItem( lostItemJpaRepository.save(lostItem); } + @CacheEvict(value = "lostItem", key = "#lostItemId") public void foundLostItem( final UUID lostItemId, final LostItemFoundRequest lostItemFoundRequest, @@ -66,6 +69,7 @@ public void foundLostItem( lostItemJpaRepository.save(lostItem); } + @CacheEvict(value = "lostItem", key = "#lostItemId") public void deleteLostItem(final UUID lostItemId, final UUID studentCouncilId) { LostItem lostItem = lostItemQueryService.getExistLostItem(lostItemId); adminQueryService.validateAdminExistence(studentCouncilId); From c971f6d4a9896bdef7381c02fe66e07134904983 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 03:04:31 +0900 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20Path=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/mju_likelion/festival/common/api/ApiPaths.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/mju_likelion/festival/common/api/ApiPaths.java b/src/main/java/org/mju_likelion/festival/common/api/ApiPaths.java index f936500..ae22603 100644 --- a/src/main/java/org/mju_likelion/festival/common/api/ApiPaths.java +++ b/src/main/java/org/mju_likelion/festival/common/api/ApiPaths.java @@ -16,6 +16,7 @@ public class ApiPaths { private static final String LOST_ITEMS = "/lost-items"; public static final String GET_ALL_LOST_ITEMS = LOST_ITEMS; public static final String SEARCH_LOST_ITEMS = LOST_ITEMS + "/search"; + public static final String GET_LOST_ITEM = LOST_ITEMS + "/{id}"; public static final String POST_LOST_ITEM = LOST_ITEMS; public static final String PATCH_LOST_ITEM = LOST_ITEMS + "/{id}"; public static final String FOUND_LOST_ITEM = LOST_ITEMS + "/{id}/found"; From de0f615ead9646be56e067dfee7d68bbc87e8194 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 03:05:10 +0900 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20exclude=20?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/authentication/config/AuthenticationConfig.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mju_likelion/festival/common/authentication/config/AuthenticationConfig.java b/src/main/java/org/mju_likelion/festival/common/authentication/config/AuthenticationConfig.java index 3c88132..60bf26e 100644 --- a/src/main/java/org/mju_likelion/festival/common/authentication/config/AuthenticationConfig.java +++ b/src/main/java/org/mju_likelion/festival/common/authentication/config/AuthenticationConfig.java @@ -3,6 +3,7 @@ import static org.mju_likelion.festival.common.api.ApiPaths.DELETE_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.FOUND_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.GET_BOOTH_MANAGING_DETAIL; +import static org.mju_likelion.festival.common.api.ApiPaths.GET_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.GET_MY_STAMP; import static org.mju_likelion.festival.common.api.ApiPaths.ISSUE_BOOTH_QR; import static org.mju_likelion.festival.common.api.ApiPaths.PATCH_ANNOUNCEMENT; @@ -67,9 +68,9 @@ private void addStudentCouncilAuthenticationInterceptor(final InterceptorRegistr .addPathPatterns(DELETE_LOST_ITEM) .addPathPatterns(POST_LOST_ITEM) .addPathPatterns(PATCH_LOST_ITEM) - .addPathPatterns(DELETE_LOST_ITEM) .addPathPatterns(FOUND_LOST_ITEM) - .excludePathPatterns(SEARCH_LOST_ITEMS); + .excludePathPatterns(SEARCH_LOST_ITEMS) + .excludePathPatterns(GET_LOST_ITEM); } /** From a0d4ca647ba68a3eea344483485f22a9be8ddc64 Mon Sep 17 00:00:00 2001 From: Kim Daehyeon Date: Thu, 3 Oct 2024 03:05:34 +0900 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20=EB=B6=84=EC=8B=A4=EB=AC=BC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20API=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20#209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lost_item/controller/LostItemController.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/mju_likelion/festival/lost_item/controller/LostItemController.java b/src/main/java/org/mju_likelion/festival/lost_item/controller/LostItemController.java index dbc7feb..9f82ec8 100644 --- a/src/main/java/org/mju_likelion/festival/lost_item/controller/LostItemController.java +++ b/src/main/java/org/mju_likelion/festival/lost_item/controller/LostItemController.java @@ -3,6 +3,7 @@ import static org.mju_likelion.festival.common.api.ApiPaths.DELETE_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.FOUND_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.GET_ALL_LOST_ITEMS; +import static org.mju_likelion.festival.common.api.ApiPaths.GET_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.PATCH_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.POST_LOST_ITEM; import static org.mju_likelion.festival.common.api.ApiPaths.SEARCH_LOST_ITEMS; @@ -17,6 +18,7 @@ import org.mju_likelion.festival.lost_item.dto.request.CreateLostItemRequest; import org.mju_likelion.festival.lost_item.dto.request.LostItemFoundRequest; import org.mju_likelion.festival.lost_item.dto.request.UpdateLostItemRequest; +import org.mju_likelion.festival.lost_item.dto.response.LostItemDetailResponse; import org.mju_likelion.festival.lost_item.dto.response.SimpleLostItemsResponse; import org.mju_likelion.festival.lost_item.service.LostItemQueryService; import org.mju_likelion.festival.lost_item.service.LostItemService; @@ -58,6 +60,13 @@ public ResponseEntity getLostItems( lostItemQueryService.searchLostItems(SortOrder.fromString(sort), keyword, page, size)); } + @GetMapping(GET_LOST_ITEM) + public ResponseEntity getLostItem( + @PathVariable final UUID id) { + + return ResponseEntity.ok(lostItemQueryService.getLostItem(id)); + } + @PostMapping(POST_LOST_ITEM) public ResponseEntity createLostItem( @RequestBody @Valid final CreateLostItemRequest createLostItemRequest,