Skip to content

Commit

Permalink
Merge pull request #13 from TEAM-ALOM/5-feat-상점-구현
Browse files Browse the repository at this point in the history
5 feat 상점 구현
  • Loading branch information
xaxeon authored Nov 21, 2024
2 parents 8238a2b + f6336ce commit e6f7909
Show file tree
Hide file tree
Showing 13 changed files with 274 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
HELP.md
.gradle
application.yml
application-dev.yml
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.alom.dorundorunbe.domain.item.controller;

import com.alom.dorundorunbe.domain.item.domain.ItemCategory;
import com.alom.dorundorunbe.domain.item.dto.EquippedItemResponseDto;
import com.alom.dorundorunbe.domain.item.dto.ItemResponseDto;
import com.alom.dorundorunbe.domain.item.service.ItemService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/items")
public class ItemController {

private final ItemService itemService;

@GetMapping("/{itemCategory}")
@Operation(summary = "아이템 목록 조회", description = "카테고리별로 아이템 목록을 반환합니다(소유한 아이템 우선 정렬)")
public ResponseEntity<List<ItemResponseDto>> fetchItemByCategory(@PathVariable("itemCategory") ItemCategory itemCategory,
@RequestParam("userId") Long userId) {
return ResponseEntity.ok(itemService.findItemByCategory(itemCategory, userId));
}

@PostMapping("/{itemId}")
@Operation(summary = "아이템 구매", description = "캐시로 아이템을 구매합니다")
public ResponseEntity<Void> purchaseItem(@PathVariable("itemId") Long itemId,
@RequestParam("userId") Long userId) {
itemService.purchaseItem(itemId, userId);
return ResponseEntity.ok().build();
}

@PostMapping("/{itemId}/equipped")
@Operation(summary = "아이템 착용", description = "아이템 착용 후 착용 중인 아이템 목록을 반환합니다")
public ResponseEntity<List<EquippedItemResponseDto>> equippedItem(@PathVariable("itemId") Long itemId,
@RequestParam("userId") Long userId) {
return ResponseEntity.ok(itemService.equippedItem(itemId, userId));
}

@PostMapping("/{itemId}/unequipped")
@Operation(summary = "아이템 착용 해제", description = "아이템 착용 해제 후 착용 중인 아이템 목록을 반환합니다")
public ResponseEntity<List<EquippedItemResponseDto>> unequippedItem(@PathVariable("itemId") Long itemId,
@RequestParam("userId") Long userId) {
return ResponseEntity.ok(itemService.unequippedItem(itemId, userId));
}

@GetMapping("/equipped")
@Operation(summary = "착용한 아이템 목록 조회", description = "착용한 아이템 목록을 반환합니다")
public ResponseEntity<List<EquippedItemResponseDto>> fetchEquippedItem(@RequestParam("userId") Long userId) {
return ResponseEntity.ok(itemService.findEquippedItem(userId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ public class Item extends BaseEntity {
@Column(nullable = false, length = 32)
private String name;

@Enumerated(EnumType.STRING)
private ItemCategory itemCategory;

// 어떤 형태로 저장할지 추후 추가

@Column(nullable = false)
private int cost;
private Long cost;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.alom.dorundorunbe.domain.item.domain;

import lombok.Getter;

@Getter
public enum ItemCategory {
CLOTHES("옷"),
HAIR("머리"),
ACCESSORY("악세사리"),
BACKGROUND("배경");

private final String description;

ItemCategory(String description) {
this.description = description;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ public class UserItem extends BaseEntity {
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "item_id", nullable = false)
private Item item;

private Boolean equipped;

public void updateEquipped(Boolean equipped) {
this.equipped = equipped;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.alom.dorundorunbe.domain.item.dto;

import com.alom.dorundorunbe.domain.item.domain.ItemCategory;

public record EquippedItemResponseDto(
Long itemId,
String name,
ItemCategory itemCategory
) {
public static EquippedItemResponseDto of(Long itemId, String name, ItemCategory itemCategory) {
return new EquippedItemResponseDto(itemId, name, itemCategory);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.alom.dorundorunbe.domain.item.dto;

public record ItemResponseDto(
Long itemId,
String name,
Long cost,
Boolean owned
) {
public static ItemResponseDto of(Long itemId, String name, Long cost, Boolean owned) {
return new ItemResponseDto(itemId, name, cost, owned);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.alom.dorundorunbe.domain.item.repository;

import com.alom.dorundorunbe.domain.item.domain.Item;
import com.alom.dorundorunbe.domain.item.domain.ItemCategory;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ItemRepository extends JpaRepository<Item, Long> {

List<Item> findAllByItemCategory(ItemCategory itemCategory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.alom.dorundorunbe.domain.item.repository;

import com.alom.dorundorunbe.domain.item.domain.Item;
import com.alom.dorundorunbe.domain.item.domain.UserItem;
import com.alom.dorundorunbe.domain.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserItemRepository extends JpaRepository<UserItem, Long> {
Boolean existsByUserAndItem(User user, Item item);
UserItem findByUserAndItem(User user, Item item);
List<UserItem> findAllByUserAndEquipped(User user, Boolean equipped);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.alom.dorundorunbe.domain.item.service;

import com.alom.dorundorunbe.domain.item.domain.Item;
import com.alom.dorundorunbe.domain.item.domain.ItemCategory;
import com.alom.dorundorunbe.domain.item.domain.UserItem;
import com.alom.dorundorunbe.domain.item.dto.EquippedItemResponseDto;
import com.alom.dorundorunbe.domain.item.dto.ItemResponseDto;
import com.alom.dorundorunbe.domain.item.repository.ItemRepository;
import com.alom.dorundorunbe.domain.item.repository.UserItemRepository;
import com.alom.dorundorunbe.domain.user.domain.User;
import com.alom.dorundorunbe.domain.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ItemService {

private final ItemRepository itemRepository;
private final UserItemRepository userItemRepository;
private final UserService userService;

public List<ItemResponseDto> findItemByCategory(ItemCategory itemCategory, Long userId) {

User user = userService.findById(userId);
List<Item> itemList = itemRepository.findAllByItemCategory(itemCategory);

return itemList.stream()
.map(item -> ItemResponseDto.of(
item.getId(),
item.getName(),
item.getCost(),
userItemRepository.existsByUserAndItem(user, item)
))
.sorted(Comparator.comparing(ItemResponseDto::owned).reversed())
.toList();
}

public void purchaseItem(Long itemId, Long userId) {
User user = userService.findById(userId);
Item item = itemRepository.findById(itemId).orElseThrow();

if (userItemRepository.existsByUserAndItem(user, item)) {
throw new IllegalArgumentException("이미 소유한 아이템입니다");
}
if (user.getCash()<item.getCost()) {
throw new IllegalArgumentException("잔액이 부족합니다");
}

user.updateCash(user.getCash()-item.getCost());
UserItem userItem = UserItem.builder()
.user(user)
.item(item)
.build();
userItemRepository.save(userItem);
}

public List<EquippedItemResponseDto> equippedItem(Long itemId, Long userId) {
User user = userService.findById(userId);
Item item = itemRepository.findById(itemId).orElseThrow();
UserItem userItem = userItemRepository.findByUserAndItem(user, item);

if (userItem == null) {
throw new IllegalArgumentException("구매가 필요합니다");
}
if (userItem.getEquipped()) {
throw new IllegalArgumentException("이미 착용된 아이템입니다");
}

userItem.updateEquipped(true);

return userItemRepository.findAllByUserAndEquipped(user, true).stream()
.map(equippedUserItem -> EquippedItemResponseDto.of(
equippedUserItem.getItem().getId(),
equippedUserItem.getItem().getName(),
equippedUserItem.getItem().getItemCategory()
))
.toList();
}

public List<EquippedItemResponseDto> unequippedItem(Long itemId, Long userId) {
User user = userService.findById(userId);
Item item = itemRepository.findById(itemId).orElseThrow();
UserItem userItem = userItemRepository.findByUserAndItem(user, item);

if (userItem == null) {
throw new IllegalArgumentException("구매가 필요합니다");
}
if (!userItem.getEquipped()) {
throw new IllegalArgumentException("이미 미착용된 아이템입니다");
}

userItem.updateEquipped(false);

return userItemRepository.findAllByUserAndEquipped(user, true).stream()
.map(equippedUserItem -> EquippedItemResponseDto.of(
equippedUserItem.getItem().getId(),
equippedUserItem.getItem().getName(),
equippedUserItem.getItem().getItemCategory()
))
.toList();
}

public List<EquippedItemResponseDto> findEquippedItem(Long userId) {
User user = userService.findById(userId);

return userItemRepository.findAllByUserAndEquipped(user, true).stream()
.map(equippedUserItem -> EquippedItemResponseDto.of(
equippedUserItem.getItem().getId(),
equippedUserItem.getItem().getName(),
equippedUserItem.getItem().getItemCategory()
))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,9 @@ public class User extends BaseEntity {
private Gender gender;

@Column(nullable = false)
private int cash;
private Long cash;

public void updateCash(Long cash) {
this.cash = cash;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.alom.dorundorunbe.domain.user.service;

import com.alom.dorundorunbe.domain.user.domain.User;
import com.alom.dorundorunbe.domain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserService {

private final UserRepository userRepository;

public User findById(Long userId) {
return userRepository.findById(userId).orElseThrow();
}
}

0 comments on commit e6f7909

Please sign in to comment.