Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public class HatchController {
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "[HSH2011] 알 부화 성공"),
@ApiResponse(responseCode = "400", description = "[HEH4001] 부화 요청 알이 부화 가능한 상태가 아님"),
@ApiResponse(responseCode = "404", description = "[HEH4041] 부화 요청 알이 존재하지 않음")
@ApiResponse(responseCode = "404", description = "[HEH4041] 부화 요청 알이 존재하지 않음"),
@ApiResponse(responseCode = "500", description = "[HEH5001] [서버 내부 오류] 부화될 러니모 존재하지 않음")
})
@PostMapping("/api/v1/incubating-eggs/{incubatingEggId}/hatch")
public ResponseEntity<SuccessResponse<HatchEggResponse>> hatch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ public enum HatchHttpResponseCode implements CustomResponseCode {

HATCH_EGG_NOT_READY("HEH4001", "부화 요청 알이 부화 가능한 상태가 아님", "부화 요청 알이 부화 가능한 상태가 아님", HttpStatus.BAD_REQUEST),
HATCH_EGG_NOT_FOUND("HEH4041", "부화 요청 알이 존재하지 않음", "부화 요청 알이 존재하지 않음", HttpStatus.NOT_FOUND),


// TODO : 다르게 처리할 방법 고민해보기
Comment thread
ekgns33 marked this conversation as resolved.
HATCH_RUNIMO_NOT_FOUND_INTERNAL_ERROR("HEH5001", "[서버 내부 오류] 부화될 러니모 존재하지 않음", "[서버 내부 오류] 부화될 러니모 존재하지 않음", HttpStatus.INTERNAL_SERVER_ERROR),
;


Expand Down
22 changes: 16 additions & 6 deletions src/main/java/org/runimo/runimo/hatch/service/HatchClient.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package org.runimo.runimo.hatch.service;

import org.runimo.runimo.item.domain.EggType;
import org.runimo.runimo.runimo.domain.Runimo;
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.hatch.exception.HatchException;
import org.runimo.runimo.hatch.exception.HatchHttpResponseCode;
import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.runimo.runimo.runimo.repository.RunimoDefinitionRepository;
import org.runimo.runimo.user.domain.IncubatingEgg;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Component
@RequiredArgsConstructor
@Service
public class HatchClient {
public final RunimoDefinitionRepository runimoDefinitionRepository;

// TODO : 로직 구현
public Runimo getRunimoFromEgg(IncubatingEgg incubatingEgg) {
return new Runimo("토끼_dummy", "R-100", "마당에 사는 토끼 dummy", "http://dummy", EggType.MADANG);
public RunimoDefinition getRunimoDefFromEgg(IncubatingEgg incubatingEgg) {
String dummyRunimoCode = "R-101";

RunimoDefinition runimoDefinition = runimoDefinitionRepository.findByCode(dummyRunimoCode)
Comment thread
ekgns33 marked this conversation as resolved.
.orElseThrow(() -> HatchException.of(HatchHttpResponseCode.HATCH_RUNIMO_NOT_FOUND_INTERNAL_ERROR));

return runimoDefinition;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
import org.runimo.runimo.hatch.exception.HatchException;
import org.runimo.runimo.hatch.exception.HatchHttpResponseCode;
import org.runimo.runimo.hatch.service.HatchClient;
import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.runimo.runimo.runimo.domain.Runimo;
import org.runimo.runimo.runimo.domain.UserRunimo;
import org.runimo.runimo.runimo.repository.RunimoRepository;
import org.runimo.runimo.runimo.repository.UserRunimoRepository;
import org.runimo.runimo.user.domain.IncubatingEgg;
import org.runimo.runimo.user.repository.IncubatingEggRepository;
import org.springframework.stereotype.Service;
Expand All @@ -18,9 +17,8 @@
@Transactional(readOnly = true)
@Service
public class HatchUsecaseImpl implements HatchUsecase {
private final RunimoRepository runimoRepository;
private final IncubatingEggRepository incubatingEggRepository;
private final UserRunimoRepository userRunimoRepository;
private final RunimoRepository runimoRepository;
private final HatchClient hatchClient;

@Transactional
Expand All @@ -31,23 +29,23 @@ public HatchEggResponse execute(Long userId, Long incubatingEggId) {
validAndHatchIncubatingEgg(incubatingEgg);

// 부화 - 러니모 획득
Runimo runimo = hatchClient.getRunimoFromEgg(incubatingEgg);

RunimoDefinition runimoDefinition = hatchClient.getRunimoDefFromEgg(incubatingEgg);
// 이미 보유한 러니모인지 확인
boolean isDuplicatedRunimo = userRunimoRepository.existsByUserIdAndRunimoId(userId, runimo.getId());

// 러니모 저장 -> 나중에 다른 요청으로 빼야 할 듯
Runimo runimoSaved = runimoRepository.save(runimo);
UserRunimo userRunimo = UserRunimo.builder()
.userId(userId)
.runimoId(runimoSaved.getId())
.build();
userRunimoRepository.save(userRunimo);
boolean isDuplicatedRunimo = runimoRepository.existsByUserIdAndRunimoDefinitionId(userId, runimoDefinition.getId());

// 러니모 저장 (중복 아닐 경우만)
if(!isDuplicatedRunimo){
Runimo runimo = Runimo.builder()
.userId(userId)
.runimoDefinitionId(runimoDefinition.getId())
.build();
runimoRepository.save(runimo);
}

return new HatchEggResponse(
runimo.getName(),
runimo.getImgUrl(),
runimo.getCode(),
runimoDefinition.getName(),
runimoDefinition.getImgUrl(),
runimoDefinition.getCode(),
isDuplicatedRunimo
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

@Schema(description = "보유 러니모 목록 조회 응답")
public record GetMyRunimoListResponse(
List<RunimoInfo> myRunimos
List<RunimoInfo> runimos
) {
}
44 changes: 25 additions & 19 deletions src/main/java/org/runimo/runimo/runimo/domain/Runimo.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
package org.runimo.runimo.runimo.domain;

import jakarta.persistence.*;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.runimo.runimo.common.BaseEntity;
import org.runimo.runimo.item.domain.EggType;
import org.runimo.runimo.runimo.exception.RunimoException;
import org.runimo.runimo.runimo.exception.RunimoHttpResponseCode;

@Entity
@Table(name = "runimo")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Runimo extends BaseEntity {
@Column(name = "name")
private String name;

@Column(name = "code", nullable = false)
private String code;
@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "description")
private String description;
@Column(name = "runimo_definition_id", nullable = false)
private Long runimoDefinitionId;

@Column(name = "img_url")
private String imgUrl;
@Column(name = "total_run_count", nullable = false)
private Long totalRunCount = 0L;

@Column(name = "total_distance_in_meters", nullable = false)
private Long totalDistanceInMeters = 0L;

@Enumerated(EnumType.STRING)
@Column(name = "egg_type", nullable = false)
private EggType type;

@Builder
public Runimo(String name, String code, String description, String imgUrl, EggType type) {
this.name = name;
this.code = code;
this.description = description;
this.imgUrl = imgUrl;
this.type = type;
private Runimo(Long id, Long userId, Long runimoDefinitionId) {
this.id = id;
this.userId = userId;
this.runimoDefinitionId = runimoDefinitionId;
}

public void validateOwner(Long userId) {
if(!this.userId.equals(userId)){
throw RunimoException.of(RunimoHttpResponseCode.USER_DO_NOT_OWN_RUNIMO);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.runimo.runimo.runimo.domain;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.runimo.runimo.common.BaseEntity;
import org.runimo.runimo.item.domain.EggType;

@Entity
@Table(name = "runimo_definition")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class RunimoDefinition extends BaseEntity {
@Column(name = "name")
private String name;

@Column(name = "code", nullable = false)
private String code;

@Column(name = "description")
private String description;

@Column(name = "img_url")
private String imgUrl;

@Enumerated(EnumType.STRING)
@Column(name = "egg_type", nullable = false)
private EggType type;

@Builder
public RunimoDefinition(String name, String code, String description, String imgUrl, EggType type) {
this.name = name;
this.code = code;
this.description = description;
this.imgUrl = imgUrl;
this.type = type;
}
}
30 changes: 0 additions & 30 deletions src/main/java/org/runimo/runimo/runimo/domain/UserRunimo.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.runimo.runimo.runimo.repository;

import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface RunimoDefinitionRepository extends JpaRepository<RunimoDefinition, Long> {
Optional<RunimoDefinition> findByCode(String runimoCode);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
package org.runimo.runimo.runimo.repository;

import org.runimo.runimo.runimo.domain.Runimo;
import org.runimo.runimo.runimo.service.model.RunimoSimpleModel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface RunimoRepository extends JpaRepository<Runimo, Long> {

boolean existsByUserIdAndRunimoDefinitionId(Long UserId, Long runimoDefinitionId);

@Query("""
select new org.runimo.runimo.runimo.service.model.RunimoSimpleModel(r.id, r.name, r.imgUrl, r.code, r.type, r.description)
from Runimo ur
join RunimoDefinition r on r.id = ur.runimoDefinitionId
where ur.userId = :userId
""")
List<RunimoSimpleModel> findAllByUserId(@Param("userId") Long userId);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import org.runimo.runimo.runimo.controller.dto.response.GetMyRunimoListResponse;
import org.runimo.runimo.runimo.controller.dto.response.SetMainRunimoResponse;
import org.runimo.runimo.runimo.domain.Runimo;
import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.runimo.runimo.runimo.exception.RunimoException;
import org.runimo.runimo.runimo.exception.RunimoHttpResponseCode;
import org.runimo.runimo.runimo.repository.RunimoDefinitionRepository;
import org.runimo.runimo.runimo.repository.RunimoRepository;
import org.runimo.runimo.runimo.repository.UserRunimoRepository;
import org.runimo.runimo.runimo.service.model.RunimoSimpleModel;
import org.runimo.runimo.user.domain.User;
import org.runimo.runimo.user.service.UserFinder;
Expand All @@ -21,20 +22,20 @@
@RequiredArgsConstructor
@Service
public class RunimoUsecaseImpl implements RunimoUsecase{
private final RunimoDefinitionRepository runimoDefinitionRepository;
private final RunimoRepository runimoRepository;
private final UserRunimoRepository userRunimoRepository;
private final UserFinder userFinder;

public GetMyRunimoListResponse getMyRunimoList(Long userId) {
List<RunimoSimpleModel> runimos = userRunimoRepository.findAllByUserId(userId);
List<RunimoSimpleModel> runimos = runimoRepository.findAllByUserId(userId);
return new GetMyRunimoListResponse(RunimoSimpleModel.toDtoList(runimos));
}

@Transactional
public SetMainRunimoResponse setMainRunimo(Long userId, Long runimoId) {
Runimo runimo = runimoRepository.findById(runimoId)
.orElseThrow(() -> RunimoException.of(RunimoHttpResponseCode.RUNIMO_NOT_FOUND));
validateOwner(userId, runimo.getId());
runimo.validateOwner(userId);

User user = userFinder.findUserById(userId)
.orElseThrow(NoSuchElementException::new);
Expand All @@ -44,9 +45,4 @@ public SetMainRunimoResponse setMainRunimo(Long userId, Long runimoId) {
return new SetMainRunimoResponse(runimoId);
}

private void validateOwner(Long userId, Long runimoId) {
if(!userRunimoRepository.existsByUserIdAndRunimoId(userId, runimoId)){
throw RunimoException.of(RunimoHttpResponseCode.USER_DO_NOT_OWN_RUNIMO);
}
}
}
Loading
Loading