diff --git a/src/main/java/org/sopt/app/application/description/DescriptionInfo.java b/src/main/java/org/sopt/app/application/description/DescriptionInfo.java index ffb7fdf5..ac9dcee1 100755 --- a/src/main/java/org/sopt/app/application/description/DescriptionInfo.java +++ b/src/main/java/org/sopt/app/application/description/DescriptionInfo.java @@ -7,6 +7,7 @@ import lombok.ToString; @NoArgsConstructor(access = AccessLevel.PRIVATE) +@Deprecated public class DescriptionInfo { @Getter diff --git a/src/main/java/org/sopt/app/application/description/DescriptionService.java b/src/main/java/org/sopt/app/application/description/DescriptionService.java index c2c4b54d..293d9f27 100755 --- a/src/main/java/org/sopt/app/application/description/DescriptionService.java +++ b/src/main/java/org/sopt/app/application/description/DescriptionService.java @@ -8,6 +8,7 @@ @Service @RequiredArgsConstructor +@Deprecated public class DescriptionService { private final MainDescriptionRepository mainDescriptionRepository; diff --git a/src/main/java/org/sopt/app/application/home/ActivityDurationCalculator.java b/src/main/java/org/sopt/app/application/home/ActivityDurationCalculator.java new file mode 100644 index 00000000..f62ca67a --- /dev/null +++ b/src/main/java/org/sopt/app/application/home/ActivityDurationCalculator.java @@ -0,0 +1,47 @@ +package org.sopt.app.application.home; + +import java.time.*; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.sopt.app.common.exception.BadRequestException; +import org.sopt.app.common.response.ErrorCode; + +@RequiredArgsConstructor +public class ActivityDurationCalculator { + private final Long firstActivityGeneration; + + public static ActivityDurationCalculator of(final List generations) { + if (generations == null || generations.isEmpty()) { + throw new BadRequestException(ErrorCode.USER_GENERATION_INFO_NOT_FOUND); + } + + Long firstGeneration = Long.MAX_VALUE; + for (Long generation : generations) { + if (generation < firstGeneration) { + firstGeneration = generation; + } + } + return new ActivityDurationCalculator(firstGeneration); + } + + public int getActivityDuration() { + LocalDate startDate = calculateStartDate(); + return calculateMonthDifference(startDate); + } + + private LocalDate calculateStartDate() { + final int SOPT_START_YEAR = 2007; + final int EVEN_GENERATION_START_MONTH = 3; + final int ODD_GENERATION_START_MONTH = 9; + int startMonth = (firstActivityGeneration % 2 == 0) ? EVEN_GENERATION_START_MONTH : ODD_GENERATION_START_MONTH; + int startYear = SOPT_START_YEAR + (int) (firstActivityGeneration / 2); + return LocalDate.of(startYear, startMonth, 1); + } + + private int calculateMonthDifference(LocalDate startDate) { + LocalDate currentDate = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDate(); + Period period = Period.between(startDate, currentDate); + int monthDifference = period.getYears() * 12 + period.getMonths(); + return monthDifference + 1; + } +} diff --git a/src/main/java/org/sopt/app/facade/DescriptionFacade.java b/src/main/java/org/sopt/app/facade/HomeFacade.java similarity index 57% rename from src/main/java/org/sopt/app/facade/DescriptionFacade.java rename to src/main/java/org/sopt/app/facade/HomeFacade.java index ad025f7d..96956bc3 100755 --- a/src/main/java/org/sopt/app/facade/DescriptionFacade.java +++ b/src/main/java/org/sopt/app/facade/HomeFacade.java @@ -1,24 +1,39 @@ package org.sopt.app.facade; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.val; +import org.sopt.app.application.home.ActivityDurationCalculator; import org.sopt.app.application.playground.PlaygroundAuthService; import org.sopt.app.application.description.DescriptionInfo.MainDescription; import org.sopt.app.application.description.DescriptionService; import org.sopt.app.domain.entity.User; +import org.sopt.app.presentation.home.HomeDescriptionResponse; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -public class DescriptionFacade { +public class HomeFacade { private final DescriptionService descriptionService; private final PlaygroundAuthService playgroundAuthService; @Transactional(readOnly = true) + @Deprecated public MainDescription getMainDescriptionForUser(User user) { val userActiveInfo = playgroundAuthService.getPlaygroundUserActiveInfo(user.getPlaygroundToken(), user.getPlaygroundId()); return descriptionService.getMainDescription(userActiveInfo.status()); } + + @Transactional(readOnly = true) + public HomeDescriptionResponse getHomeMainDescription(User user) { + List ownGenerations = playgroundAuthService.getOwnPlaygroundProfile(user.getPlaygroundToken()) + .getAllGenerations(); + ActivityDurationCalculator calculator = ActivityDurationCalculator.of(ownGenerations); + return HomeDescriptionResponse.of( + user.getUsername(), + calculator.getActivityDuration() + ); + } } diff --git a/src/main/java/org/sopt/app/interfaces/postgres/MainDescriptionRepository.java b/src/main/java/org/sopt/app/interfaces/postgres/MainDescriptionRepository.java index 82f852d1..a36abb0d 100755 --- a/src/main/java/org/sopt/app/interfaces/postgres/MainDescriptionRepository.java +++ b/src/main/java/org/sopt/app/interfaces/postgres/MainDescriptionRepository.java @@ -3,6 +3,7 @@ import org.sopt.app.domain.entity.MainDescription; import org.springframework.data.jpa.repository.JpaRepository; +@Deprecated public interface MainDescriptionRepository extends JpaRepository { } diff --git a/src/main/java/org/sopt/app/presentation/description/DescriptionController.java b/src/main/java/org/sopt/app/presentation/description/DescriptionController.java index 9bdf4be3..78a51aff 100755 --- a/src/main/java/org/sopt/app/presentation/description/DescriptionController.java +++ b/src/main/java/org/sopt/app/presentation/description/DescriptionController.java @@ -7,7 +7,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.RequiredArgsConstructor; import lombok.val; -import org.sopt.app.facade.DescriptionFacade; +import org.sopt.app.facade.HomeFacade; import org.sopt.app.domain.entity.User; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -19,7 +19,7 @@ @SecurityRequirement(name = "Authorization") public class DescriptionController { - private final DescriptionFacade descriptionFacade; + private final HomeFacade homeFacade; @Operation(summary = "메인 문구 조회") @ApiResponses({ @@ -31,7 +31,7 @@ public class DescriptionController { public ResponseEntity getMainDescription( @AuthenticationPrincipal User user ) { - val response = descriptionFacade.getMainDescriptionForUser(user); + val response = homeFacade.getMainDescriptionForUser(user); return ResponseEntity.ok( DescriptionResponse.MainDescription.builder() .topDescription(response.getTopDescription()) diff --git a/src/main/java/org/sopt/app/presentation/home/HomeController.java b/src/main/java/org/sopt/app/presentation/home/HomeController.java new file mode 100644 index 00000000..81deff47 --- /dev/null +++ b/src/main/java/org/sopt/app/presentation/home/HomeController.java @@ -0,0 +1,37 @@ +package org.sopt.app.presentation.home; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.RequiredArgsConstructor; +import org.sopt.app.domain.entity.User; +import org.sopt.app.facade.HomeFacade; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v2/home") +@SecurityRequirement(name = "Authorization") +public class HomeController { + + private final HomeFacade homeFacade; + + @Operation(summary = "홈 메인 문구 조회") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "success"), + @ApiResponse(responseCode = "401", description = "token error", content = @Content), + @ApiResponse(responseCode = "500", description = "server error", content = @Content) + }) + @GetMapping("/description") + public ResponseEntity getHomeMainDescription( + @AuthenticationPrincipal User user + ) { + return ResponseEntity.ok( + homeFacade.getHomeMainDescription(user) + ); + } +} diff --git a/src/main/java/org/sopt/app/presentation/home/HomeDescriptionResponse.java b/src/main/java/org/sopt/app/presentation/home/HomeDescriptionResponse.java new file mode 100644 index 00000000..0eb736f5 --- /dev/null +++ b/src/main/java/org/sopt/app/presentation/home/HomeDescriptionResponse.java @@ -0,0 +1,14 @@ +package org.sopt.app.presentation.home; + +import lombok.*; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class HomeDescriptionResponse { + private final String activityDescription; + public static HomeDescriptionResponse of(String userName, int totalActivityMonths) { + return new HomeDescriptionResponse( + userName + "님은\nSOPT와 " + totalActivityMonths + "개월째" + ); + } +} diff --git a/src/test/java/org/sopt/app/facade/DescriptionFacadeTest.java b/src/test/java/org/sopt/app/facade/HomeFacadeTest.java similarity index 91% rename from src/test/java/org/sopt/app/facade/DescriptionFacadeTest.java rename to src/test/java/org/sopt/app/facade/HomeFacadeTest.java index e981c656..7455cea0 100755 --- a/src/test/java/org/sopt/app/facade/DescriptionFacadeTest.java +++ b/src/test/java/org/sopt/app/facade/HomeFacadeTest.java @@ -20,7 +20,7 @@ import org.sopt.app.domain.enums.UserStatus; @ExtendWith(MockitoExtension.class) -class DescriptionFacadeTest { +class HomeFacadeTest { @Mock private DescriptionService descriptionService; @@ -29,7 +29,7 @@ class DescriptionFacadeTest { private PlaygroundAuthService playgroundAuthService; @InjectMocks - private DescriptionFacade descriptionFacade; + private HomeFacade homeFacade; @Test @DisplayName("SUCCESS_활동 유저 메인 문구 조회") @@ -42,7 +42,7 @@ void SUCCESS_getMainDescriptionForUserActive() { .thenReturn(DescriptionInfo.MainDescription.builder().topDescription("activeTop") .bottomDescription("activeBottom").build()); - MainDescription result = descriptionFacade.getMainDescriptionForUser(user); + MainDescription result = homeFacade.getMainDescriptionForUser(user); Assertions.assertEquals("activeTop", result.getTopDescription()); Assertions.assertEquals("activeBottom", result.getBottomDescription()); } @@ -58,7 +58,7 @@ void SUCCESS_getMainDescriptionForUserInactive() { .thenReturn(DescriptionInfo.MainDescription.builder().topDescription("inactiveTop") .bottomDescription("inactiveBottom").build()); - MainDescription result = descriptionFacade.getMainDescriptionForUser(user); + MainDescription result = homeFacade.getMainDescriptionForUser(user); Assertions.assertEquals("inactiveTop", result.getTopDescription()); Assertions.assertEquals("inactiveBottom", result.getBottomDescription()); }