Skip to content

Commit

Permalink
feat: 수정에서 shopId가 아닌 mapId를 이용하도록 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
krSeonghyeon committed Dec 12, 2024
1 parent be254a3 commit 16ff6fe
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,8 @@ ResponseEntity<AdminCreateBenefitShopsResponse> createBenefitShops(
}
)
@Operation(summary = "특정 혜택을 제공하는 상점을 수정한다.")
@PutMapping("/{id}/shops")
@PutMapping
ResponseEntity<Void> modifyBenefitShops(
@PathVariable("id") Integer benefitId,
@RequestBody AdminModifyBenefitShopsRequest request,
@Auth(permit = {ADMIN}) Integer adminId
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,12 @@ public ResponseEntity<AdminCreateBenefitShopsResponse> createBenefitShops(
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

@PutMapping("/{id}/shops")
@PutMapping
public ResponseEntity<Void> modifyBenefitShops(
@PathVariable("id") Integer benefitId,
@RequestBody AdminModifyBenefitShopsRequest request,
@Auth(permit = {ADMIN}) Integer adminId
) {
adminBenefitService.modifyBenefitShops(benefitId, request);
adminBenefitService.modifyBenefitShops(request);
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import in.koreatech.koin.domain.shop.model.shop.Shop;
import io.swagger.v3.oas.annotations.media.Schema;

@JsonNaming(SnakeCaseStrategy.class)
public record AdminBenefitShopsResponse(
@Schema(example = "3", description = "상점 개수")
Integer count,
Expand All @@ -26,7 +27,11 @@ public static AdminBenefitShopsResponse from(List<BenefitCategoryMap> benefitCat
);
}

@JsonNaming(SnakeCaseStrategy.class)
private record InnerShopResponse(
@Schema(example = "1", description = "상점혜택 매핑id")
Integer shopBenefitMapId,

@Schema(example = "1", description = "고유 id")
Integer id,

Expand All @@ -39,6 +44,7 @@ private record InnerShopResponse(

public static InnerShopResponse from(BenefitCategoryMap benefitCategoryMap) {
return new InnerShopResponse(
benefitCategoryMap.getId(),
benefitCategoryMap.getShop().getId(),
benefitCategoryMap.getShop().getName(),
benefitCategoryMap.getDetail()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,30 @@
@JsonNaming(SnakeCaseStrategy.class)
public record AdminModifyBenefitShopsRequest(
@Schema(
description = "상점정보 리스트", example = """
description = "혜택문구 변경정보 리스트", example = """
[
{
"shop_id": 1,
"shopBenefitMapId": 1,
"detail": "배달비 무료"
},
{
"shop_id": 2,
"shopBenefitMapId": 2,
"detail": "최소주문금액 0원"
}
]
""",
requiredMode = REQUIRED
)
@NotNull(message = "상점정보 리스트는 필수입니다.")
@NotBlankElement(message = "상점정보 리스트는 빈 요소가 존재할 수 없습니다.")
List<InnerBenefitShopsRequest> shopDetails
@NotNull(message = "혜택문구 변경정보 리스트는 필수입니다.")
@NotBlankElement(message = "혜택문구 변경정보 리스트는 빈 요소가 존재할 수 없습니다.")
List<InnerBenefitShopsRequest> modifyDetails
) {

@JsonNaming(SnakeCaseStrategy.class)
public record InnerBenefitShopsRequest(
@Schema(description = "상점 고유 id", example = "2", requiredMode = REQUIRED)
@NotNull(message = "상점은 필수입니다.")
Integer shopId,
@Schema(description = "상점혜택 매핑id", example = "2", requiredMode = REQUIRED)
@NotNull(message = "상점혜택 매핑id는 필수입니다.")
Integer shopBenefitMapId,

@Schema(description = "혜택 미리보기 문구", example = "4인 이상 픽업서비스", requiredMode = REQUIRED)
@NotBlank(message = "혜택 미리보기 문구는 필수입니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package in.koreatech.koin.admin.benefit.exception;

import in.koreatech.koin.global.exception.DataNotFoundException;

public class BenefitMapNotFoundException extends DataNotFoundException {

private static final String DEFAULT_MESSAGE = "해당 혜택 카테고리에 존재하지 않는 입니다.";

public BenefitMapNotFoundException(String message) {
super(message);
}

public BenefitMapNotFoundException(String message, String detail) {
super(message, detail);
}

public static BenefitMapNotFoundException withDetail(String detail) {
return new BenefitMapNotFoundException(DEFAULT_MESSAGE, detail);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

public interface AdminBenefitCategoryMapRepository extends CrudRepository<BenefitCategoryMap, Integer> {

List<BenefitCategoryMap> findAllByIdIn(List<Integer> ids);

@Query("""
SELECT bcm
FROM BenefitCategoryMap bcm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import in.koreatech.koin.admin.benefit.dto.AdminSearchBenefitShopsResponse;
import in.koreatech.koin.admin.benefit.exception.BenefitDuplicationException;
import in.koreatech.koin.admin.benefit.exception.BenefitLimitException;
import in.koreatech.koin.admin.benefit.exception.BenefitShopNotFoundException;
import in.koreatech.koin.admin.benefit.exception.BenefitMapNotFoundException;
import in.koreatech.koin.admin.benefit.repository.AdminBenefitCategoryMapRepository;
import in.koreatech.koin.admin.benefit.repository.AdminBenefitCategoryRepository;
import in.koreatech.koin.admin.shop.repository.shop.AdminShopRepository;
Expand Down Expand Up @@ -122,26 +122,31 @@ public AdminCreateBenefitShopsResponse createBenefitShops(
}

@Transactional
public void modifyBenefitShops(Integer benefitId, AdminModifyBenefitShopsRequest request) {
Map<Integer, String> shopIdToDetail = request.shopDetails().stream()
public void modifyBenefitShops(AdminModifyBenefitShopsRequest request) {
Map<Integer, String> shopBenefitIdToDetail = request.modifyDetails().stream()
.collect(Collectors.toMap(
AdminModifyBenefitShopsRequest.InnerBenefitShopsRequest::shopId,
AdminModifyBenefitShopsRequest.InnerBenefitShopsRequest::shopBenefitMapId,
AdminModifyBenefitShopsRequest.InnerBenefitShopsRequest::detail
));

List<BenefitCategoryMap> benefitCategoryMaps = adminBenefitCategoryMapRepository.findAllByBenefitCategoryIdAndShopIds(
benefitId,
shopIdToDetail.keySet().stream().toList()
);
List<Integer> notFoundShopIds = shopIdToDetail.keySet().stream()
.filter(shopId -> benefitCategoryMaps.stream().noneMatch(map -> map.getShop().getId().equals(shopId)))
List<BenefitCategoryMap> benefitCategoryMaps =
adminBenefitCategoryMapRepository.findAllByIdIn(shopBenefitIdToDetail.keySet().stream().toList());

validateBenefitMapIds(shopBenefitIdToDetail, benefitCategoryMaps);
benefitCategoryMaps.forEach(map -> map.modifyDetail(shopBenefitIdToDetail.get(map.getId())));
}

private static void validateBenefitMapIds(
Map<Integer, String> shopBenefitIdToDetail,
List<BenefitCategoryMap> benefitCategoryMaps
) {
List<Integer> notFoundMapIds = shopBenefitIdToDetail.keySet().stream()
.filter(mapId -> benefitCategoryMaps.stream().noneMatch(map -> map.getId().equals(mapId)))
.toList();

if (!notFoundShopIds.isEmpty()) {
throw new BenefitShopNotFoundException("해당 혜택 카테고리에 존재하지 않는 상점이 포함되어 있습니다. shopId: " + notFoundShopIds);
if (!notFoundMapIds.isEmpty()) {
throw new BenefitMapNotFoundException("해당 혜택 카테고리에 존재하지 않는 상점이 포함되어 있습니다. shopBenefitMapId: " + notFoundMapIds);
}

benefitCategoryMaps.forEach(map -> map.modifyDetail(shopIdToDetail.get(map.getShop().getId())));
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public class AdminBenefitApiTest extends AcceptanceTest {
BenefitCategory 서비스_증정;
BenefitCategory 가게까지_픽업;

BenefitCategoryMap 김밥천국_혜택;
BenefitCategoryMap 마슬랜_혜택;
BenefitCategoryMap 티바_혜택;
BenefitCategoryMap 신전_혜택;

Shop 마슬랜;
Shop 김밥천국;
Shop 영업중인_티바;
Expand All @@ -105,10 +110,10 @@ void setup() {
영업중인_티바 = shopFixture.영업중인_티바(현수_사장님);
영업중이_아닌_신전_떡볶이 = shopFixture.영업중이_아닌_신전_떡볶이(현수_사장님);

benefitCategoryMapFixture.설명이_포함된_혜택_추가(김밥천국, 배달비_무료, "설명1");
benefitCategoryMapFixture.설명이_포함된_혜택_추가(마슬랜, 배달비_무료, "설명2");
benefitCategoryMapFixture.설명이_포함된_혜택_추가(영업중인_티바, 배달비_무료, "설명3");
benefitCategoryMapFixture.설명이_포함된_혜택_추가(영업중이_아닌_신전_떡볶이, 배달비_무료, "설명4");
김밥천국_혜택 = benefitCategoryMapFixture.설명이_포함된_혜택_추가(김밥천국, 배달비_무료, "설명1");
마슬랜_혜택 = benefitCategoryMapFixture.설명이_포함된_혜택_추가(마슬랜, 배달비_무료, "설명2");
티바_혜택 = benefitCategoryMapFixture.설명이_포함된_혜택_추가(영업중인_티바, 배달비_무료, "설명3");
신전_혜택 = benefitCategoryMapFixture.설명이_포함된_혜택_추가(영업중이_아닌_신전_떡볶이, 배달비_무료, "설명4");

notificationMessage_가게 = shopNotificationMessageFixture.알림메시지_가게();
shopParentCategory_가게 = shopParentCategoryFixture.상위_카테고리_가게(notificationMessage_가게);
Expand Down Expand Up @@ -239,28 +244,36 @@ void setup() {
"count": 4,
"shops": [
{
"shop_benefit_map_id": %d,
"id": %d,
"name": "김밥천국",
"detail": "설명1"
},
{
"shop_benefit_map_id": %d,
"id": %d,
"name": "마슬랜 치킨",
"detail": "설명2"
},
{
"shop_benefit_map_id": %d,
"id": %d,
"name": "티바",
"detail": "설명3"
},
{
"shop_benefit_map_id": %d,
"id": %d,
"name": "신전 떡볶이",
"detail": "설명4"
}
]
}
""", 김밥천국.getId(), 마슬랜.getId(), 영업중인_티바.getId(), 영업중이_아닌_신전_떡볶이.getId())));
""",
김밥천국_혜택.getId(), 김밥천국.getId(),
마슬랜_혜택.getId(), 마슬랜.getId(),
티바_혜택.getId(), 영업중인_티바.getId(),
신전_혜택.getId(), 영업중이_아닌_신전_떡볶이.getId())));
}

@Test
Expand Down Expand Up @@ -306,42 +319,41 @@ void setup() {
@Test
void 특정_혜택을_제공하는_상점들을_수정한다() throws Exception {
mockMvc.perform(
put("/admin/benefit/{id}/shops", 배달비_무료.getId())
put("/admin/benefit")
.header("Authorization", "Bearer " + token_admin)
.contentType(MediaType.APPLICATION_JSON)
.content(String.format("""
{
"shop_details": [
"modify_details": [
{
"shop_id": %d,
"shop_benefit_map_id": %d,
"detail": "김밥새혜택설명"
},
{
"shop_id": %d,
"shop_benefit_map_id": %d,
"detail": "마슬랜새혜택설명"
}
]
}
""", 김밥천국.getId(), 마슬랜.getId()))
""", 김밥천국_혜택.getId(), 마슬랜_혜택.getId()))
)
.andExpect(status().isOk());

transactionTemplate.executeWithoutResult(status -> {
List<BenefitCategoryMap> updatedBenefit =
adminBenefitCategoryMapRepository.findAllByBenefitCategoryIdAndShopIds(
배달비_무료.getId(),
List.of(김밥천국.getId(), 마슬랜.getId())
adminBenefitCategoryMapRepository.findAllByIdIn(
List.of(김밥천국_혜택.getId(), 마슬랜_혜택.getId())
);

Map<Integer, String> details = updatedBenefit.stream()
.collect(Collectors.toMap(
map -> map.getShop().getId(),
BenefitCategoryMap::getId,
BenefitCategoryMap::getDetail
));

assertThat(details).isEqualTo(Map.of(
김밥천국.getId(), "김밥새혜택설명",
마슬랜.getId(), "마슬랜새혜택설명"
김밥천국_혜택.getId(), "김밥새혜택설명",
마슬랜_혜택.getId(), "마슬랜새혜택설명"
));
});
}
Expand Down

0 comments on commit 16ff6fe

Please sign in to comment.