Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package until.the.eternity.metalwareinfo.application.service;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import until.the.eternity.metalwareinfo.domain.repository.MetalwareInfoRepositoryPort;
import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MetalwareInfoService {

private final MetalwareInfoRepositoryPort metalwareInfoRepository;

public List<MetalwareInfoResponse> findAll() {
List<String> metalwares = metalwareInfoRepository.findAllMetalwares();
return MetalwareInfoResponse.from(metalwares);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package until.the.eternity.metalwareinfo.domain.repository;

import java.util.List;

public interface MetalwareInfoRepositoryPort {
List<String> findAllMetalwares();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package until.the.eternity.metalwareinfo.infrastructure.persistence;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "metalware_info")
@Getter
@NoArgsConstructor
public class MetalwareInfoEntity {

@Id
@Column(name = "metalware", nullable = false, length = 50)
private String metalware;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package until.the.eternity.metalwareinfo.infrastructure.persistence;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface MetalwareInfoJpaRepository extends JpaRepository<MetalwareInfoEntity, String> {

@Query("SELECT m.metalware FROM MetalwareInfoEntity m")
List<String> findAllMetalwares();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package until.the.eternity.metalwareinfo.infrastructure.persistence;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import until.the.eternity.metalwareinfo.domain.repository.MetalwareInfoRepositoryPort;

@Repository
@RequiredArgsConstructor
public class MetalwareInfoRepositoryPortImpl implements MetalwareInfoRepositoryPort {
private final MetalwareInfoJpaRepository jpaRepository;

@Override
public List<String> findAllMetalwares() {
return jpaRepository.findAllMetalwares();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package until.the.eternity.metalwareinfo.interfaces.rest.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import until.the.eternity.metalwareinfo.application.service.MetalwareInfoService;
import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse;

@RestController
@RequestMapping("/api/metalware-infos")
@RequiredArgsConstructor
@Tag(name = "Metalware Info", description = "세공 정보 조회 API")
public class MetalwareInfoController {

private final MetalwareInfoService metalwareInfoService;

// TODO: 세공 레벨별 능력치, 최대 레벨, 한계 돌파 최대 레벨은 수기로 추가 후 조회 시 사용
@Operation(summary = "모든 세공 정보 조회", description = "시스템에 저장된 모든 세공 정보를 조회합니다.")
@GetMapping
public List<MetalwareInfoResponse> getAllMetalwareInfos() {
return metalwareInfoService.findAll();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package until.the.eternity.metalwareinfo.interfaces.rest.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Builder;

@Builder
@Schema(description = "세공 정보 응답 DTO")
public record MetalwareInfoResponse(
@Schema(description = "세공", example = "불의 연성술") String metalware) {
public static MetalwareInfoResponse from(String metalware) {
return MetalwareInfoResponse.builder().metalware(metalware).build();
}

public static List<MetalwareInfoResponse> from(List<String> metalwares) {
return metalwares.stream().map(MetalwareInfoResponse::from).collect(Collectors.toList());
}
}
3 changes: 3 additions & 0 deletions src/main/resources/db/migration/R__insert_item_info.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
delete from item_info;
INSERT INTO item_info (name, top_category, sub_category)
select distinct item_name, item_top_category, item_sub_category from auction_history;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
delete from item_option_value_info;
insert into item_option_value_info (option_type, option_sub_type, option_value, option_value2, option_desc)
select distinct option_type, option_sub_type, option_value, option_value2, option_desc from auction_item_option;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
delete from metalware_info;
insert into metalware_info (metalware)
select distinct regexp_replace(regexp_substr(option_value, ' ?[^\(]+'), ' ?[0-9][0-9]? ?레벨', '') as metalware
from auction_item_option
where option_type = '세공 옵션';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
create table metalware_info
(
metalware VARCHAR(50) not null primary key comment '세공',
level_attribute VARCHAR(50) comment '레벨별 능력치 효과',
max_level TINYINT comment '레벨 최대 수치',
limit_break_level TINYINT comment '한계 돌파 레벨 최대 수치'
)
comment '세공 정보 테이블';

-- 데이터 적재 쿼리
--insert into metalware_info (metalware)
--select distinct regexp_replace(regexp_substr(option_value, ' ?[^\(]+'), ' ?[0-9][0-9]? ?레벨', '') as metalware
--from auction_item_option
--where option_type = '세공 옵션';
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package until.the.eternity.metalwareinfo.application.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import until.the.eternity.metalwareinfo.domain.repository.MetalwareInfoRepositoryPort;
import until.the.eternity.metalwareinfo.interfaces.rest.dto.response.MetalwareInfoResponse;

@ExtendWith(MockitoExtension.class)
class MetalwareInfoServiceTest {

@Mock private MetalwareInfoRepositoryPort repositoryPort;

@InjectMocks private MetalwareInfoService service;

@Test
@DisplayName("모든 세공 정보를 조회하면 세공 목록을 반환한다")
void findAll_should_return_all_metalwares() {
// given
List<String> metalwares = List.of("불의 연성술", "물의 연성술", "바람의 연성술");
when(repositoryPort.findAllMetalwares()).thenReturn(metalwares);

// when
List<MetalwareInfoResponse> result = service.findAll();

// then
assertThat(result).hasSize(3);
assertThat(result.get(0).metalware()).isEqualTo("불의 연성술");
assertThat(result.get(1).metalware()).isEqualTo("물의 연성술");
assertThat(result.get(2).metalware()).isEqualTo("바람의 연성술");
verify(repositoryPort).findAllMetalwares();
}

@Test
@DisplayName("세공 정보가 없으면 빈 목록을 반환한다")
void findAll_should_return_empty_list_when_no_data() {
// given
when(repositoryPort.findAllMetalwares()).thenReturn(List.of());

// when
List<MetalwareInfoResponse> result = service.findAll();

// then
assertThat(result).isEmpty();
verify(repositoryPort).findAllMetalwares();
}
}