-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: ResponseStatus + DTO 방식으로 변경 * feat: 아이템, 인벤토리 Entity 생성 * feat: 아이템 목록 조회 API 구현 * test: containsExactly 검증으로 수정 * test: 아이템 목록 조회 Service 테스트 * test: 인벤토리 아이템 목록 조회 Repository 테스트 * feat: Stream 유틸 클래스 생성 및 적용 * fix: ItemFixture를 통한 아이템 생성 시 build() 추가 * test: 구매하지 않은 아이템 목록 조회 Repository 테스트 * feat: MethodArgumentTypeMismatchException handler 추가 * test: 아이템 목록 조회 Controller 테스트 * fix: Mapper 생성자 접근 레벨 private으로 변경 * feat: ItemType 생성 및 적용 * refactor: 잘못된 요청 타입 에러 메시지 상수화
- Loading branch information
Showing
27 changed files
with
757 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.moabam.api.application; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import com.moabam.api.domain.entity.Item; | ||
import com.moabam.api.domain.entity.enums.ItemType; | ||
import com.moabam.api.domain.repository.InventorySearchRepository; | ||
import com.moabam.api.domain.repository.ItemSearchRepository; | ||
import com.moabam.api.dto.ItemMapper; | ||
import com.moabam.api.dto.ItemsResponse; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
public class ItemService { | ||
|
||
private final ItemSearchRepository itemSearchRepository; | ||
private final InventorySearchRepository inventorySearchRepository; | ||
|
||
public ItemsResponse getItems(Long memberId, ItemType type) { | ||
List<Item> purchasedItems = inventorySearchRepository.findItems(memberId, type); | ||
List<Item> notPurchasedItems = itemSearchRepository.findNotPurchasedItems(memberId, type); | ||
|
||
return ItemMapper.toItemsResponse(purchasedItems, notPurchasedItems); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.moabam.api.domain.entity; | ||
|
||
import static java.util.Objects.*; | ||
|
||
import org.hibernate.annotations.ColumnDefault; | ||
|
||
import com.moabam.global.common.entity.BaseTimeEntity; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.FetchType; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Index; | ||
import jakarta.persistence.JoinColumn; | ||
import jakarta.persistence.ManyToOne; | ||
import jakarta.persistence.Table; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@Table(name = "inventory", indexes = @Index(name = "idx_member_id", columnList = "member_id")) | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Inventory extends BaseTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
@Column(name = "id") | ||
private Long id; | ||
|
||
@Column(name = "member_id", updatable = false, nullable = false) | ||
private Long memberId; | ||
|
||
@ManyToOne(fetch = FetchType.LAZY) | ||
@JoinColumn(name = "item_id", updatable = false, nullable = false) | ||
private Item item; | ||
|
||
@Column(name = "is_default", nullable = false) | ||
@ColumnDefault("false") | ||
private boolean isDefault; | ||
|
||
@Builder | ||
private Inventory(Long memberId, Item item, boolean isDefault) { | ||
this.memberId = requireNonNull(memberId); | ||
this.item = requireNonNull(item); | ||
this.isDefault = isDefault; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package com.moabam.api.domain.entity; | ||
|
||
import static com.moabam.global.error.model.ErrorMessage.*; | ||
import static java.util.Objects.*; | ||
|
||
import org.hibernate.annotations.ColumnDefault; | ||
|
||
import com.moabam.api.domain.entity.enums.ItemCategory; | ||
import com.moabam.api.domain.entity.enums.ItemType; | ||
import com.moabam.global.common.entity.BaseTimeEntity; | ||
import com.moabam.global.error.exception.BadRequestException; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.EnumType; | ||
import jakarta.persistence.Enumerated; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
import lombok.AccessLevel; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@Table(name = "item") | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
public class Item extends BaseTimeEntity { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
@Column(name = "id") | ||
private Long id; | ||
|
||
@Enumerated(value = EnumType.STRING) | ||
@Column(name = "type", nullable = false) | ||
private ItemType type; | ||
|
||
@Enumerated(value = EnumType.STRING) | ||
@Column(name = "category", nullable = false) | ||
private ItemCategory category; | ||
|
||
@Column(name = "name", nullable = false) | ||
private String name; | ||
|
||
@Column(name = "image", nullable = false) | ||
private String image; | ||
|
||
@Column(name = "bug_price", nullable = false) | ||
@ColumnDefault("0") | ||
private int bugPrice; | ||
|
||
@Column(name = "golden_bug_price", nullable = false) | ||
@ColumnDefault("0") | ||
private int goldenBugPrice; | ||
|
||
@Column(name = "unlock_level", nullable = false) | ||
@ColumnDefault("1") | ||
private int unlockLevel; | ||
|
||
@Builder | ||
private Item(ItemType type, ItemCategory category, String name, String image, int bugPrice, int goldenBugPrice, | ||
Integer unlockLevel) { | ||
this.type = requireNonNull(type); | ||
this.category = requireNonNull(category); | ||
this.name = requireNonNull(name); | ||
this.image = requireNonNull(image); | ||
this.bugPrice = validatePrice(bugPrice); | ||
this.goldenBugPrice = validatePrice(goldenBugPrice); | ||
this.unlockLevel = validateLevel(requireNonNullElse(unlockLevel, 1)); | ||
} | ||
|
||
private int validatePrice(int price) { | ||
if (price < 0) { | ||
throw new BadRequestException(INVALID_PRICE); | ||
} | ||
|
||
return price; | ||
} | ||
|
||
private int validateLevel(int level) { | ||
if (level < 1) { | ||
throw new BadRequestException(INVALID_LEVEL); | ||
} | ||
|
||
return level; | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/com/moabam/api/domain/entity/enums/ItemCategory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.moabam.api.domain.entity.enums; | ||
|
||
public enum ItemCategory { | ||
|
||
SKIN; | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/moabam/api/domain/entity/enums/ItemType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.moabam.api.domain.entity.enums; | ||
|
||
public enum ItemType { | ||
|
||
MORNING, | ||
NIGHT; | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/com/moabam/api/domain/repository/InventoryRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.moabam.api.domain.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import com.moabam.api.domain.entity.Inventory; | ||
|
||
public interface InventoryRepository extends JpaRepository<Inventory, Long> { | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/moabam/api/domain/repository/InventorySearchRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.moabam.api.domain.repository; | ||
|
||
import static com.moabam.api.domain.entity.QInventory.*; | ||
import static com.moabam.api.domain.entity.QItem.*; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.stereotype.Repository; | ||
|
||
import com.moabam.api.domain.entity.Item; | ||
import com.moabam.api.domain.entity.enums.ItemType; | ||
import com.moabam.global.common.util.DynamicQuery; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class InventorySearchRepository { | ||
|
||
private final JPAQueryFactory jpaQueryFactory; | ||
|
||
public List<Item> findItems(Long memberId, ItemType type) { | ||
return jpaQueryFactory.selectFrom(inventory) | ||
.join(inventory.item, item) | ||
.where( | ||
DynamicQuery.generateEq(memberId, inventory.memberId::eq), | ||
DynamicQuery.generateEq(type, inventory.item.type::eq)) | ||
.orderBy(inventory.createdAt.desc()) | ||
.select(item) | ||
.fetch(); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/com/moabam/api/domain/repository/ItemRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.moabam.api.domain.repository; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import com.moabam.api.domain.entity.Item; | ||
|
||
public interface ItemRepository extends JpaRepository<Item, Long> { | ||
|
||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/com/moabam/api/domain/repository/ItemSearchRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.moabam.api.domain.repository; | ||
|
||
import static com.moabam.api.domain.entity.QInventory.*; | ||
import static com.moabam.api.domain.entity.QItem.*; | ||
|
||
import java.util.List; | ||
|
||
import org.springframework.stereotype.Repository; | ||
|
||
import com.moabam.api.domain.entity.Item; | ||
import com.moabam.api.domain.entity.enums.ItemType; | ||
import com.moabam.global.common.util.DynamicQuery; | ||
import com.querydsl.core.types.dsl.BooleanExpression; | ||
import com.querydsl.jpa.impl.JPAQueryFactory; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class ItemSearchRepository { | ||
|
||
private final JPAQueryFactory jpaQueryFactory; | ||
|
||
public List<Item> findNotPurchasedItems(Long memberId, ItemType type) { | ||
return jpaQueryFactory.selectFrom(item) | ||
.leftJoin(inventory) | ||
.on(inventory.item.id.eq(item.id)) | ||
.where( | ||
DynamicQuery.generateEq(type, item.type::eq), | ||
DynamicQuery.generateEq(memberId, this::filterByMemberId)) | ||
.orderBy( | ||
item.unlockLevel.asc(), | ||
item.bugPrice.asc(), | ||
item.goldenBugPrice.asc(), | ||
item.name.asc()) | ||
.fetch(); | ||
} | ||
|
||
private BooleanExpression filterByMemberId(Long memberId) { | ||
return inventory.memberId.isNull() | ||
.or(inventory.memberId.ne(memberId)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.moabam.api.dto; | ||
|
||
import java.util.List; | ||
|
||
import com.moabam.api.domain.entity.Item; | ||
import com.moabam.global.common.util.StreamUtils; | ||
|
||
import lombok.AccessLevel; | ||
import lombok.NoArgsConstructor; | ||
|
||
@NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
public final class ItemMapper { | ||
|
||
public static ItemResponse toItemResponse(Item item) { | ||
return ItemResponse.builder() | ||
.id(item.getId()) | ||
.type(item.getType().name()) | ||
.category(item.getCategory().name()) | ||
.name(item.getName()) | ||
.image(item.getImage()) | ||
.level(item.getUnlockLevel()) | ||
.bugPrice(item.getBugPrice()) | ||
.goldenBugPrice(item.getGoldenBugPrice()) | ||
.build(); | ||
} | ||
|
||
public static ItemsResponse toItemsResponse(List<Item> purchasedItems, List<Item> notPurchasedItems) { | ||
return ItemsResponse.builder() | ||
.purchasedItems(StreamUtils.map(purchasedItems, ItemMapper::toItemResponse)) | ||
.notPurchasedItems(StreamUtils.map(notPurchasedItems, ItemMapper::toItemResponse)) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.moabam.api.dto; | ||
|
||
import lombok.Builder; | ||
|
||
@Builder | ||
public record ItemResponse( | ||
Long id, | ||
String type, | ||
String category, | ||
String name, | ||
String image, | ||
int level, | ||
int bugPrice, | ||
int goldenBugPrice | ||
) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.moabam.api.dto; | ||
|
||
import java.util.List; | ||
|
||
import lombok.Builder; | ||
|
||
@Builder | ||
public record ItemsResponse( | ||
List<ItemResponse> purchasedItems, | ||
List<ItemResponse> notPurchasedItems | ||
) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.