diff --git a/src/main/java/org/runimo/runimo/common/GlobalConsts.java b/src/main/java/org/runimo/runimo/common/GlobalConsts.java index ae828406..7c8202a7 100644 --- a/src/main/java/org/runimo/runimo/common/GlobalConsts.java +++ b/src/main/java/org/runimo/runimo/common/GlobalConsts.java @@ -2,6 +2,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.runimo.runimo.common.scale.Distance; import java.util.Set; @@ -17,5 +18,5 @@ public final class GlobalConsts { ); public static final String EMPTYFIELD = "EMPTY"; - + public static final Distance DISTANCE_UNIT = new Distance(1000L); } diff --git a/src/main/java/org/runimo/runimo/common/scale/Distance.java b/src/main/java/org/runimo/runimo/common/scale/Distance.java index d77ce1b1..a4562006 100644 --- a/src/main/java/org/runimo/runimo/common/scale/Distance.java +++ b/src/main/java/org/runimo/runimo/common/scale/Distance.java @@ -21,4 +21,12 @@ public Distance(Long amount) { public Long getAmount() { return amount; } + + public Distance add(Distance distance) { + return new Distance(this.amount + distance.amount); + } + + public Distance divide(Distance divisor) { + return new Distance(this.amount / divisor.getAmount()); + } } diff --git a/src/main/java/org/runimo/runimo/item/domain/Egg.java b/src/main/java/org/runimo/runimo/item/domain/Egg.java index 6f0125cf..294e475e 100644 --- a/src/main/java/org/runimo/runimo/item/domain/Egg.java +++ b/src/main/java/org/runimo/runimo/item/domain/Egg.java @@ -1,9 +1,6 @@ package org.runimo.runimo.item.domain; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -14,6 +11,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@DiscriminatorValue("EGG") public class Egg extends Item { public static final Egg EMPTY = new Egg(EMPTYFIELD, EMPTYFIELD, EMPTYFIELD, EMPTYFIELD, null, 0L); @Column(name = "egg_type") diff --git a/src/main/java/org/runimo/runimo/rewards/service/RewardService.java b/src/main/java/org/runimo/runimo/rewards/service/RewardService.java index a4e4f84d..f819c36c 100644 --- a/src/main/java/org/runimo/runimo/rewards/service/RewardService.java +++ b/src/main/java/org/runimo/runimo/rewards/service/RewardService.java @@ -8,6 +8,7 @@ import org.runimo.runimo.rewards.service.eggs.EggGrantService; import org.runimo.runimo.rewards.service.dtos.RewardClaimCommand; import org.runimo.runimo.rewards.service.dtos.RewardResponse; +import org.runimo.runimo.rewards.service.lovepoint.LoveGrantService; import org.runimo.runimo.user.domain.User; import org.runimo.runimo.user.service.UserFinder; import org.springframework.stereotype.Service; @@ -24,6 +25,8 @@ public class RewardService { private final RecordFinder recordFinder; private final UserFinder userFinder; private final EggGrantService eggGrantService; + private final LoveGrantService loveGrantService; + @Transactional public RewardResponse claimReward(RewardClaimCommand command) { @@ -31,9 +34,9 @@ public RewardResponse claimReward(RewardClaimCommand command) { .orElseThrow(NoSuchElementException::new); validateRecord(runningRecord); Egg grantedEgg = rewardEgg(command); + Long grantedLoveAmount = loveGrantService.grantLoveToUserWithDistance(runningRecord); runningRecord.reward(command.userId()); - //TODO: 애정 보상 - return new RewardResponse(grantedEgg.getItemCode(), grantedEgg.getEggType()); + return new RewardResponse(grantedEgg.getItemCode(), grantedEgg.getEggType(), grantedLoveAmount); } private Egg rewardEgg(RewardClaimCommand command) { diff --git a/src/main/java/org/runimo/runimo/rewards/service/dtos/RewardResponse.java b/src/main/java/org/runimo/runimo/rewards/service/dtos/RewardResponse.java index b9363933..5a940077 100644 --- a/src/main/java/org/runimo/runimo/rewards/service/dtos/RewardResponse.java +++ b/src/main/java/org/runimo/runimo/rewards/service/dtos/RewardResponse.java @@ -4,6 +4,7 @@ public record RewardResponse( String eggCode, - EggType eggType + EggType eggType, + Long lovePointAmount ) { } diff --git a/src/main/java/org/runimo/runimo/rewards/service/lovepoint/LoveGrantService.java b/src/main/java/org/runimo/runimo/rewards/service/lovepoint/LoveGrantService.java new file mode 100644 index 00000000..b49fb2e3 --- /dev/null +++ b/src/main/java/org/runimo/runimo/rewards/service/lovepoint/LoveGrantService.java @@ -0,0 +1,33 @@ +package org.runimo.runimo.rewards.service.lovepoint; + +import lombok.RequiredArgsConstructor; + +import org.runimo.runimo.common.scale.Distance; +import org.runimo.runimo.records.domain.RunningRecord; +import org.runimo.runimo.user.domain.LovePoint; +import org.runimo.runimo.user.domain.User; +import org.runimo.runimo.user.service.LovePointProcessor; +import org.runimo.runimo.user.service.UserFinder; +import org.springframework.stereotype.Component; + +import static org.runimo.runimo.common.GlobalConsts.DISTANCE_UNIT; + + +@Component +@RequiredArgsConstructor +public class LoveGrantService { + private final UserFinder userFinder; + private final LovePointProcessor lovePointProcessor; + + public Long grantLoveToUserWithDistance(RunningRecord runningRecord) { + User user = userFinder.findUserById(runningRecord.getUserId()) + .orElseThrow(IllegalStateException::new); + Long loveAmount = calculateLoveAmount(runningRecord.getTotalDistance()); + LovePoint lovePoint = lovePointProcessor.updateLovePoint(user.getId(), loveAmount); + return lovePoint.getAmount(); + } + + private Long calculateLoveAmount(Distance distance) { + return distance.divide(DISTANCE_UNIT).getAmount(); + } +} diff --git a/src/main/java/org/runimo/runimo/user/domain/LovePoint.java b/src/main/java/org/runimo/runimo/user/domain/LovePoint.java new file mode 100644 index 00000000..f7de9228 --- /dev/null +++ b/src/main/java/org/runimo/runimo/user/domain/LovePoint.java @@ -0,0 +1,37 @@ +package org.runimo.runimo.user.domain; + +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; + +@Table(name = "user_love_point") +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class LovePoint extends BaseEntity { + public static final LovePoint EMPTY = new LovePoint(null, 0L); + @Column(name = "user_id", nullable = false) + private Long userId; + @Column(name = "amount", nullable = false) + private Long amount; + + @Builder + public LovePoint(Long userId, Long amount) { + this.userId = userId; + this.amount = amount; + } + + public void add(long amount) { + this.amount += amount; + } + + public void subtract(long amount) { + if (this.amount < amount) throw new IllegalStateException("Not enough love points"); + this.amount -= amount; + } +} diff --git a/src/main/java/org/runimo/runimo/user/repository/LovePointRepository.java b/src/main/java/org/runimo/runimo/user/repository/LovePointRepository.java new file mode 100644 index 00000000..6a2d539c --- /dev/null +++ b/src/main/java/org/runimo/runimo/user/repository/LovePointRepository.java @@ -0,0 +1,20 @@ +package org.runimo.runimo.user.repository; + +import jakarta.persistence.LockModeType; +import jakarta.persistence.QueryHint; +import org.runimo.runimo.user.domain.LovePoint; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.repository.QueryHints; + +import java.util.Optional; + +public interface LovePointRepository extends JpaRepository { + @Lock(LockModeType.PESSIMISTIC_WRITE) + @QueryHints({@QueryHint(name = "jakarta.persistence.lock.timeout", value = "3000")}) + @Query("select l from LovePoint l where l.userId = :id") + Optional findByUserIdWithXLock(Long id); + + Optional findLovePointByUserId(Long id); +} \ No newline at end of file diff --git a/src/main/java/org/runimo/runimo/user/service/LovePointProcessor.java b/src/main/java/org/runimo/runimo/user/service/LovePointProcessor.java new file mode 100644 index 00000000..ad89c98f --- /dev/null +++ b/src/main/java/org/runimo/runimo/user/service/LovePointProcessor.java @@ -0,0 +1,23 @@ +package org.runimo.runimo.user.service; + +import org.runimo.runimo.user.domain.LovePoint; +import org.runimo.runimo.user.repository.LovePointRepository; +import org.springframework.stereotype.Component; + +@Component +public class LovePointProcessor { + + private final LovePointRepository lovePointRepository; + + public LovePointProcessor(LovePointRepository lovePointRepository) { + this.lovePointRepository = lovePointRepository; + } + + // 유저의 러브포인트를 업데이트한다. XLOCK을 걸어서 동시성 문제를 해결한다. + public LovePoint updateLovePoint(Long userId, Long loveAmount) { + LovePoint lp = lovePointRepository.findByUserIdWithXLock(userId) + .orElseThrow(IllegalStateException::new); + lp.add(loveAmount); + return lovePointRepository.save(lp); + } +} diff --git a/src/main/java/org/runimo/runimo/user/service/UserCreator.java b/src/main/java/org/runimo/runimo/user/service/UserCreator.java index 9b8d9740..4f3fc640 100644 --- a/src/main/java/org/runimo/runimo/user/service/UserCreator.java +++ b/src/main/java/org/runimo/runimo/user/service/UserCreator.java @@ -1,9 +1,8 @@ package org.runimo.runimo.user.service; import lombok.RequiredArgsConstructor; -import org.runimo.runimo.user.domain.OAuthInfo; -import org.runimo.runimo.user.domain.SocialProvider; -import org.runimo.runimo.user.domain.User; +import org.runimo.runimo.user.domain.*; +import org.runimo.runimo.user.repository.LovePointRepository; import org.runimo.runimo.user.repository.OAuthInfoRepository; import org.runimo.runimo.user.repository.UserRepository; import org.runimo.runimo.user.service.dtos.UserSignupCommand; @@ -15,6 +14,7 @@ public class UserCreator { private final UserRepository userRepository; private final OAuthInfoRepository oAuthInfoRepository; + private final LovePointRepository lovePointRepository; @Transactional public User createUser(UserSignupCommand command) { @@ -34,4 +34,13 @@ public OAuthInfo createUserOAuthInfo(User user, SocialProvider provider, String .build(); return oAuthInfoRepository.save(oAuthInfo); } + + @Transactional + public LovePoint createLovePoint(Long userId) { + LovePoint lovePoint = LovePoint.builder() + .userId(userId) + .amount(0L) + .build(); + return lovePointRepository.save(lovePoint); + } } diff --git a/src/main/java/org/runimo/runimo/user/service/UserFinder.java b/src/main/java/org/runimo/runimo/user/service/UserFinder.java index 77011d86..afe00b91 100644 --- a/src/main/java/org/runimo/runimo/user/service/UserFinder.java +++ b/src/main/java/org/runimo/runimo/user/service/UserFinder.java @@ -1,7 +1,9 @@ package org.runimo.runimo.user.service; import lombok.RequiredArgsConstructor; +import org.runimo.runimo.user.domain.LovePoint; import org.runimo.runimo.user.domain.User; +import org.runimo.runimo.user.repository.LovePointRepository; import org.runimo.runimo.user.repository.UserRepository; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -13,6 +15,7 @@ public class UserFinder { private final UserRepository userRepository; + private final LovePointRepository lovePointRepository; @Transactional(readOnly = true) public Optional findUserByPublicId(final String publicId) { @@ -23,4 +26,8 @@ public Optional findUserByPublicId(final String publicId) { public Optional findUserById(final Long userId) { return userRepository.findById(userId); } + + public Optional findLovePointByUserId(Long userId) { + return lovePointRepository.findLovePointByUserId(userId); + } } diff --git a/src/main/java/org/runimo/runimo/user/service/usecases/UserRegisterService.java b/src/main/java/org/runimo/runimo/user/service/usecases/UserRegisterService.java index d2138060..375e6a2f 100644 --- a/src/main/java/org/runimo/runimo/user/service/usecases/UserRegisterService.java +++ b/src/main/java/org/runimo/runimo/user/service/usecases/UserRegisterService.java @@ -21,6 +21,7 @@ public class UserRegisterService { public User register(UserSignupCommand command, String providerId) { User savedUser = userCreator.createUser(command); userCreator.createUserOAuthInfo(savedUser, command.provider(), providerId); + userCreator.createLovePoint(savedUser.getId()); userItemCreator.createAll(savedUser.getId()); eggGrantService.grantGreetingEggToUser(savedUser); return savedUser; diff --git a/src/main/resources/sql/schema.sql b/src/main/resources/sql/schema.sql index 2206bc52..af5a9d17 100644 --- a/src/main/resources/sql/schema.sql +++ b/src/main/resources/sql/schema.sql @@ -10,6 +10,7 @@ DROP TABLE IF EXISTS item_activity; DROP TABLE IF EXISTS runimo; DROP TABLE IF EXISTS items; DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS user_love_point; SET FOREIGN_KEY_CHECKS = 1; @@ -37,6 +38,16 @@ CREATE TABLE `user_token` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ); +CREATE TABLE `user_love_point` +( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `amount` BIGINT NOT NULL DEFAULT 0, + `created_at` TIMESTAMP, + `updated_at` TIMESTAMP, + `deleted_at` TIMESTAMP +); + CREATE TABLE `oauth_accounts` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, diff --git a/src/test/java/org/runimo/runimo/CleanUpUtil.java b/src/test/java/org/runimo/runimo/CleanUpUtil.java index ada387e7..ccaf9f7f 100644 --- a/src/test/java/org/runimo/runimo/CleanUpUtil.java +++ b/src/test/java/org/runimo/runimo/CleanUpUtil.java @@ -12,6 +12,7 @@ public class CleanUpUtil { "oauth_accounts", "users", "running_records", + "user_love_point" }; @Autowired diff --git a/src/test/java/org/runimo/runimo/rewards/RewardTest.java b/src/test/java/org/runimo/runimo/rewards/RewardTest.java index 7449a8bc..7c30f1e9 100644 --- a/src/test/java/org/runimo/runimo/rewards/RewardTest.java +++ b/src/test/java/org/runimo/runimo/rewards/RewardTest.java @@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; import java.time.LocalDateTime; @@ -58,6 +59,7 @@ void tearDown() { } @Test + @Sql(scripts = "/sql/egg_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 보상_요청_테스트() { RecordCreateCommand recordCreateCommand = new RecordCreateCommand( savedUser.getId(), diff --git a/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java b/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java index 6528d4fc..d9d10e24 100644 --- a/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/rewards/api/RewardAcceptanceTest.java @@ -193,6 +193,80 @@ void tearDown() { .body("payload.egg_code", equalTo("EMPTY")); } + @Test + @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + void 달리기_기록_저장_후_애정_포인트_지급() throws JsonProcessingException { + String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); + RecordSaveRequest request = new RecordSaveRequest( + pivotTime, + pivotTime.plusMinutes(20), + 1000L, + 1000L); + ValidatableResponse res = given() + .header("Authorization", header) + .body(objectMapper.writeValueAsString(request)) + .contentType(ContentType.JSON) + .when() + .post("/api/v1/records") + .then() + .log().ifValidationFails() + .statusCode(HttpStatus.CREATED.value()) + .body("payload", notNullValue()) + .body("payload.saved_id", notNullValue()); + + Integer recordId = res.extract().path("payload.saved_id"); + + RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(Long.valueOf(recordId)); + + given() + .header("Authorization", header) + .body(objectMapper.writeValueAsString(rewardClaimRequest)) + .contentType(ContentType.JSON) + .when() + .post("/api/v1/rewards/runnings") + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .body("payload.love_point_amount", notNullValue()) + .body("payload.love_point_amount", greaterThan(0)); + } + @Test + @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + void 기준거리_미달이면_애정을_미지급() throws JsonProcessingException { + String header = "Bearer " + jwtTokenFactory.generateAccessToken("test-user-uuid-1"); + RecordSaveRequest request = new RecordSaveRequest( + pivotTime, + pivotTime.plusMinutes(20), + 900L, + 1000L); + ValidatableResponse res = given() + .header("Authorization", header) + .body(objectMapper.writeValueAsString(request)) + .contentType(ContentType.JSON) + .when() + .post("/api/v1/records") + .then() + .log().ifValidationFails() + .statusCode(HttpStatus.CREATED.value()) + .body("payload", notNullValue()) + .body("payload.saved_id", notNullValue()); + + Integer recordId = res.extract().path("payload.saved_id"); + + RewardClaimRequest rewardClaimRequest = new RewardClaimRequest(Long.valueOf(recordId)); + + given() + .header("Authorization", header) + .body(objectMapper.writeValueAsString(rewardClaimRequest)) + .contentType(ContentType.JSON) + .when() + .post("/api/v1/rewards/runnings") + .then() + .log().all() + .statusCode(HttpStatus.OK.value()) + .body("payload.love_point_amount", notNullValue()) + .body("payload.love_point_amount", equalTo(0)); + } } diff --git a/src/test/java/org/runimo/runimo/rewards/service/RewardServiceTest.java b/src/test/java/org/runimo/runimo/rewards/service/RewardServiceTest.java index a28f2770..b6433198 100644 --- a/src/test/java/org/runimo/runimo/rewards/service/RewardServiceTest.java +++ b/src/test/java/org/runimo/runimo/rewards/service/RewardServiceTest.java @@ -11,6 +11,7 @@ import org.runimo.runimo.rewards.service.dtos.RewardClaimCommand; import org.runimo.runimo.rewards.service.dtos.RewardResponse; import org.runimo.runimo.rewards.service.eggs.EggGrantService; +import org.runimo.runimo.rewards.service.lovepoint.LoveGrantService; import org.runimo.runimo.user.UserFixtures; import org.runimo.runimo.user.service.UserFinder; import org.springframework.test.util.ReflectionTestUtils; @@ -32,6 +33,8 @@ class RewardServiceTest { private UserFinder userFinder; @Mock private EggGrantService eggGrantService; + @Mock + private LoveGrantService loveGrantService; private static RunningRecord getRunningRecordWithIds(Long userId, Long recordId, boolean isRewarded) { RunningRecord runningRecord = RunningRecord.builder() @@ -47,7 +50,7 @@ private static RunningRecord getRunningRecordWithIds(Long userId, Long recordId, @BeforeEach void setUp() { openMocks(this); - rewardService = new RewardService(recordFinder, userFinder, eggGrantService); + rewardService = new RewardService(recordFinder, userFinder, eggGrantService, loveGrantService); when(userFinder.findUserById(any())).thenReturn(Optional.of(UserFixtures.getUserWithId(1L))); } @@ -59,10 +62,11 @@ void setUp() { when(recordFinder.findById(any())).thenReturn(java.util.Optional.of(unRewardedRecord)); when(recordFinder.findFirstRunOfCurrentWeek(any())).thenReturn(java.util.Optional.of(unRewardedRecord)); when(eggGrantService.grantRandomEggToUser(any())).thenReturn(Egg.builder().eggType(EggType.MADANG).build()); - + when(loveGrantService.grantLoveToUserWithDistance(any())).thenReturn(10L); RewardResponse res = rewardService.claimReward(command); assertNotNull(res); assertEquals(EggType.MADANG, res.eggType()); + assertNotEquals(0, res.lovePointAmount()); } @Test @@ -73,6 +77,7 @@ void setUp() { when(recordFinder.findById(any())).thenReturn(java.util.Optional.of(alreadyRewardedRecord)); when(recordFinder.findFirstRunOfCurrentWeek(any())).thenReturn(java.util.Optional.of(alreadyRewardedRecord)); when(eggGrantService.grantRandomEggToUser(any())).thenReturn(Egg.builder().eggType(EggType.MADANG).build()); + when(loveGrantService.grantLoveToUserWithDistance(any())).thenReturn(10L); assertThrows(IllegalStateException.class, () -> rewardService.claimReward(command)); } @@ -85,6 +90,7 @@ void setUp() { when(recordFinder.findById(any())).thenReturn(java.util.Optional.of(unRewardedRecord)); when(recordFinder.findFirstRunOfCurrentWeek(any())).thenReturn(Optional.of(anotherRecord)); + when(loveGrantService.grantLoveToUserWithDistance(any())).thenReturn(10L); RewardResponse res = rewardService.claimReward(command); verify(eggGrantService, never()).grantRandomEggToUser(any()); diff --git a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java index 15388263..31bdd206 100644 --- a/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java +++ b/src/test/java/org/runimo/runimo/user/api/UserItemAcceptanceTest.java @@ -124,6 +124,7 @@ void tearDown() { } @Test + @Sql(scripts = "/sql/user_item_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 회원가입후_알_지급_성공() throws JsonProcessingException { String token = jwtTokenFactory.generateAccessToken("test-user-uuid-1"); when(oidcService.validateOidcTokenAndGetProviderId(any(), any())) diff --git a/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java b/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java index a23b80f1..db8a8d7d 100644 --- a/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java +++ b/src/test/java/org/runimo/runimo/user/service/usecases/UserRegisterServiceTest.java @@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -36,6 +37,7 @@ void tearDown() { } @Test + @Sql(scripts = "/sql/egg_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) void 회원가입_알_지급_테스트() { // given UserSignupCommand command = new UserSignupCommand("test", SocialProvider.KAKAO, "1234"); diff --git a/src/test/resources/sql/egg_data.sql b/src/test/resources/sql/egg_data.sql new file mode 100644 index 00000000..e0f6d792 --- /dev/null +++ b/src/test/resources/sql/egg_data.sql @@ -0,0 +1,9 @@ +TRUNCATE TABLE items; + +INSERT INTO items (name, item_code, description, item_type, img_url, dtype, egg_type, hatch_require_amount, created_at, + updated_at) +VALUES ('마당알', 'A100', '마당알: 기본 알', 'USABLE', 'example.url', 'EGG', 'MADANG', 10, NOW(), NOW()); + +INSERT INTO items (name, item_code, description, item_type, img_url, dtype, egg_type, hatch_require_amount, created_at, + updated_at) +VALUES ('숲알', 'A101', '숲알: 기본 알', 'USABLE', 'example1.url', 'EGG', 'FOREST', 20, NOW(), NOW()); \ No newline at end of file diff --git a/src/test/resources/sql/schema.sql b/src/test/resources/sql/schema.sql index 2206bc52..af5a9d17 100644 --- a/src/test/resources/sql/schema.sql +++ b/src/test/resources/sql/schema.sql @@ -10,6 +10,7 @@ DROP TABLE IF EXISTS item_activity; DROP TABLE IF EXISTS runimo; DROP TABLE IF EXISTS items; DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS user_love_point; SET FOREIGN_KEY_CHECKS = 1; @@ -37,6 +38,16 @@ CREATE TABLE `user_token` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ); +CREATE TABLE `user_love_point` +( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `amount` BIGINT NOT NULL DEFAULT 0, + `created_at` TIMESTAMP, + `updated_at` TIMESTAMP, + `deleted_at` TIMESTAMP +); + CREATE TABLE `oauth_accounts` ( `id` BIGINT PRIMARY KEY AUTO_INCREMENT, diff --git a/src/test/resources/sql/user_item_test_data.sql b/src/test/resources/sql/user_item_test_data.sql index 78aea917..641f572d 100644 --- a/src/test/resources/sql/user_item_test_data.sql +++ b/src/test/resources/sql/user_item_test_data.sql @@ -11,15 +11,19 @@ SET FOREIGN_KEY_CHECKS = 1; TRUNCATE TABLE items; INSERT INTO items (name, item_code, description, item_type, img_url, dtype, egg_type, hatch_require_amount, created_at, updated_at) -VALUES ('마당알', 'A100', '마당알: 기본 알', 'USABLE', 'example.url', 'Egg', 'MADANG', 10, NOW(), NOW()); +VALUES ('마당알', 'A100', '마당알: 기본 알', 'USABLE', 'example.url', 'EGG', 'MADANG', 10, NOW(), NOW()); INSERT INTO items (name, item_code, description, item_type, img_url, dtype, egg_type, hatch_require_amount, created_at, updated_at) -VALUES ('숲알', 'A101', '숲알: 기본 알', 'USABLE', 'example1.url', 'Egg', 'FOREST', 20, NOW(), NOW()); +VALUES ('숲알', 'A101', '숲알: 기본 알', 'USABLE', 'example1.url', 'EGG', 'FOREST', 20, NOW(), NOW()); -- 보유 아이템 TRUNCATE TABLE user_item; INSERT INTO user_item (id, user_id, item_id, quantity, created_at, updated_at) VALUES (1001, 1, 1, 2, NOW(), NOW()), - (1002, 1, 2, 1, NOW(), NOW()) + (1002, 1, 2, 1, NOW(), NOW()); + +TRUNCATE TABLE user_love_point; +INSERT INTO user_love_point (id, user_id, amount, created_at, updated_at) +VALUES (1001, 1, 0, NOW(), NOW()); \ No newline at end of file