├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src ├── main │ └── java │ │ └── org │ │ └── guzzing │ │ └── studayserver │ │ ├── global │ │ ├── common │ │ │ ├── auth │ │ │ │ ├── OAuth2Provider.java │ │ │ │ └── RoleType.java │ │ │ ├── member │ │ │ │ ├── MemberId.java │ │ │ │ └── MemberIdAnnotationConfig.java │ │ │ ├── time │ │ │ │ └── TimeConverter.java │ │ │ ├── controller │ │ │ │ └── MainController.java │ │ │ └── entity │ │ │ │ └── BaseEntity.java │ │ ├── exception │ │ │ ├── LikeException.java │ │ │ ├── ChildException.java │ │ │ ├── AcademyException.java │ │ │ ├── MemberException.java │ │ │ ├── RegionException.java │ │ │ ├── ReviewException.java │ │ │ ├── LessonException.java │ │ │ └── DashboardException.java │ │ └── config │ │ │ ├── JpaConfig.java │ │ │ ├── ScheduleConfig.java │ │ │ ├── TimeZoneConfig.java │ │ │ ├── QueryDslConfig.java │ │ │ ├── CaffeineCacheType.java │ │ │ └── CaffeineCacheConfig.java │ │ ├── domain │ │ ├── auth │ │ │ ├── service │ │ │ │ └── dto │ │ │ │ │ ├── AuthLogoutResult.java │ │ │ │ │ ├── AuthRefreshResult.java │ │ │ │ │ └── AuthLoginResult.java │ │ │ ├── client │ │ │ │ ├── ClientStrategy.java │ │ │ │ ├── dto │ │ │ │ │ ├── GoogleUser.java │ │ │ │ │ └── KakaoUser.java │ │ │ │ └── ClientStrategyHandler.java │ │ │ ├── controller │ │ │ │ └── dto │ │ │ │ │ ├── AuthLogoutResponse.java │ │ │ │ │ ├── AuthRefreshResponse.java │ │ │ │ │ └── AuthLoginResponse.java │ │ │ ├── exception │ │ │ │ ├── TokenExpiredException.java │ │ │ │ ├── TokenIsLogoutException.java │ │ │ │ └── TokenValidFailedException.java │ │ │ ├── config │ │ │ │ └── PermitAllEndpoint.java │ │ │ ├── jwt │ │ │ │ └── JwtHeaderUtil.java │ │ │ ├── repository │ │ │ │ └── JwtCacheRepository.java │ │ │ └── listener │ │ │ │ └── WithdrawAuthTokenListener.java │ │ ├── child │ │ │ ├── service │ │ │ │ ├── param │ │ │ │ │ ├── ChildCreateParam.java │ │ │ │ │ ├── ChildDeleteParam.java │ │ │ │ │ └── ChildModifyParam.java │ │ │ │ ├── result │ │ │ │ │ ├── ChildProfileImagePatchResult.java │ │ │ │ │ ├── AcademyCalendarDetailChildInfo.java │ │ │ │ │ └── ChildrenFindResult.java │ │ │ │ ├── ChildDateScheduleResult.java │ │ │ │ ├── ChildAccessService.java │ │ │ │ ├── ChildWithScheduleResult.java │ │ │ │ └── ChildWithScheduleMappingDummyEntity.java │ │ │ ├── repository │ │ │ │ └── ChildRepository.java │ │ │ ├── controller │ │ │ │ ├── response │ │ │ │ │ └── ChildProfileImagePatchResponse.java │ │ │ │ └── request │ │ │ │ │ ├── ChildCreateRequest.java │ │ │ │ │ └── ChildModifyRequest.java │ │ │ ├── schedule │ │ │ │ └── ChildIncreaseGradeSchedule.java │ │ │ ├── model │ │ │ │ ├── ProfileImageUri.java │ │ │ │ └── ChildNickname.java │ │ │ └── listener │ │ │ │ └── WithdrawProfileImageListener.java │ │ ├── like │ │ │ ├── service │ │ │ │ └── dto │ │ │ │ │ ├── request │ │ │ │ │ └── LikePostParam.java │ │ │ │ │ └── response │ │ │ │ │ ├── LikedAcademyFeeInfo.java │ │ │ │ │ ├── LikePostResult.java │ │ │ │ │ └── LikeGetResult.java │ │ │ ├── controller │ │ │ │ └── dto │ │ │ │ │ ├── response │ │ │ │ │ ├── LikePostResponse.java │ │ │ │ │ └── LikeGetResponses.java │ │ │ │ │ └── request │ │ │ │ │ └── LikePostRequest.java │ │ │ └── repository │ │ │ │ ├── LikeJpaRepository.java │ │ │ │ └── LikeRepository.java │ │ ├── dashboard │ │ │ ├── facade │ │ │ │ ├── dto │ │ │ │ │ ├── DashboardPatchResult.java │ │ │ │ │ ├── DashboardGetResults.java │ │ │ │ │ ├── DashboardPutResult.java │ │ │ │ │ ├── DashboardPostResult.java │ │ │ │ │ └── DashboardGetResult.java │ │ │ │ └── vo │ │ │ │ │ ├── ChildInfo.java │ │ │ │ │ ├── LessonInfo.java │ │ │ │ │ └── AcademyInfo.java │ │ │ ├── controller │ │ │ │ ├── dto │ │ │ │ │ ├── response │ │ │ │ │ │ ├── DashboardPatchResponse.java │ │ │ │ │ │ ├── DashboardGetResponses.java │ │ │ │ │ │ ├── DashboardPostResponse.java │ │ │ │ │ │ ├── DashboardPutResponse.java │ │ │ │ │ │ └── DashboardGetResponse.java │ │ │ │ │ └── request │ │ │ │ │ │ ├── DashboardPutRequest.java │ │ │ │ │ │ └── DashboardPostRequest.java │ │ │ │ └── vo │ │ │ │ │ └── Schedule.java │ │ │ ├── model │ │ │ │ ├── vo │ │ │ │ │ ├── SimpleMemo.java │ │ │ │ │ ├── SimpleMemoType.java │ │ │ │ │ ├── Repeatance.java │ │ │ │ │ └── FeeInfo.java │ │ │ │ └── dto │ │ │ │ │ └── PaymentInfo.java │ │ │ ├── repository │ │ │ │ ├── DashboardQuerydslRepository.java │ │ │ │ ├── DashboardScheduleJpaRepository.java │ │ │ │ ├── DashboardJpaRepository.java │ │ │ │ ├── DashboardQuerydslRepositoryImpl.java │ │ │ │ └── DashboardRepository.java │ │ │ └── service │ │ │ │ ├── access │ │ │ │ ├── DashboardAccessService.java │ │ │ │ └── dto │ │ │ │ │ └── LessonScheduleAccessResult.java │ │ │ │ ├── dto │ │ │ │ ├── response │ │ │ │ │ ├── DashBoardFindByIdsResults.java │ │ │ │ │ ├── DashboardScheduleAccessResult.java │ │ │ │ │ └── DashboardResult.java │ │ │ │ └── request │ │ │ │ │ ├── DashboardPutParam.java │ │ │ │ │ └── DashboardPostParam.java │ │ │ │ ├── vo │ │ │ │ ├── ScheduleInfos.java │ │ │ │ └── ScheduleInfo.java │ │ │ │ └── DashboardReadService.java │ │ ├── academy │ │ │ ├── repository │ │ │ │ ├── dto │ │ │ │ │ ├── AcademyFee.java │ │ │ │ │ ├── LessonInfoToCreateDashboard.java │ │ │ │ │ ├── request │ │ │ │ │ │ └── AcademyByLocationWithCursorRepositoryRequest.java │ │ │ │ │ ├── AcademyFilterCondition.java │ │ │ │ │ ├── response │ │ │ │ │ │ ├── AcademiesByName.java │ │ │ │ │ │ ├── AcademyByFilterWithScroll.java │ │ │ │ │ │ ├── AcademyByLocationRepositoryResponse.java │ │ │ │ │ │ ├── AcademiesByFilterWithScroll.java │ │ │ │ │ │ ├── AcademiesByLocationWithScrollRepositoryResponse.java │ │ │ │ │ │ ├── AcademyByLocationWithCursorRepositoryResponse.java │ │ │ │ │ │ └── AcademyByLocationWithCursorNotLikeRepositoryResponse.java │ │ │ │ │ ├── AcademyWithLikeByLocation.java │ │ │ │ │ └── AcademyWithNotLikeByLocation.java │ │ │ │ ├── academycategory │ │ │ │ │ ├── AcademyCategoryRepository.java │ │ │ │ │ └── AcademyCategoryJpaRepository.java │ │ │ │ ├── review │ │ │ │ │ ├── ReviewCountJpaRepository.java │ │ │ │ │ └── ReviewCountRepository.java │ │ │ │ └── lesson │ │ │ │ │ ├── LessonRepository.java │ │ │ │ │ └── LessonJpaRepository.java │ │ │ ├── service │ │ │ │ ├── dto │ │ │ │ │ ├── param │ │ │ │ │ │ ├── AcademiesByNameParam.java │ │ │ │ │ │ ├── AcademiesByLocationWithScrollParam.java │ │ │ │ │ │ ├── AcademyByLocationWithCursorParam.java │ │ │ │ │ │ ├── AcademyByLocationParam.java │ │ │ │ │ │ └── AcademyFilterWithScrollParam.java │ │ │ │ │ └── result │ │ │ │ │ │ ├── LessonFindByIdsResults.java │ │ │ │ │ │ ├── AcademyFeeInfo.java │ │ │ │ │ │ ├── LessonGetResults.java │ │ │ │ │ │ ├── AcademiesByNameResults.java │ │ │ │ │ │ ├── LessonGetResult.java │ │ │ │ │ │ ├── AcademiesByNameResult.java │ │ │ │ │ │ ├── AcademyAndLessonDetailResult.java │ │ │ │ │ │ ├── ReviewPercentGetResult.java │ │ │ │ │ │ └── LessonInfoToCreateDashboardResults.java │ │ │ │ ├── AcademyAccessService.java │ │ │ │ └── LessonReadService.java │ │ │ ├── model │ │ │ │ ├── vo │ │ │ │ │ ├── academyinfo │ │ │ │ │ │ └── ShuttleAvailability.java │ │ │ │ │ ├── Address.java │ │ │ │ │ └── Location.java │ │ │ │ ├── CategoryName.java │ │ │ │ ├── Category.java │ │ │ │ └── AcademyCategory.java │ │ │ ├── facade │ │ │ │ └── dto │ │ │ │ │ ├── AcademyDetailFacadeParam.java │ │ │ │ │ └── AcademiesByLocationFacadeParam.java │ │ │ ├── util │ │ │ │ ├── Direction.java │ │ │ │ ├── Latitude.java │ │ │ │ └── Longitude.java │ │ │ └── controller │ │ │ │ └── dto │ │ │ │ ├── request │ │ │ │ ├── AcademiesByNameRequest.java │ │ │ │ └── AcademyByLocationWithScrollRequest.java │ │ │ │ ├── response │ │ │ │ ├── LessonGetResponses.java │ │ │ │ ├── AcademiesByNameResponses.java │ │ │ │ ├── LessonGetResponse.java │ │ │ │ ├── AcademiesByNameResponse.java │ │ │ │ ├── ReviewPercentGetResponse.java │ │ │ │ ├── LessonInfoToCreateDashboardResponses.java │ │ │ │ └── AcademyGetResponse.java │ │ │ │ └── validation │ │ │ │ ├── ValidCategoryName.java │ │ │ │ └── ValidCategoryNameValidator.java │ │ ├── calendar │ │ │ ├── service │ │ │ │ ├── dto │ │ │ │ │ ├── param │ │ │ │ │ │ ├── AcademyCalendarLoadToUpdateParam.java │ │ │ │ │ │ ├── AcademyCalendarDetailParam.java │ │ │ │ │ │ ├── AcademyCalendarDeleteParam.java │ │ │ │ │ │ ├── AcademyCalendarDeleteByDashboardParam.java │ │ │ │ │ │ ├── LessonScheduleParam.java │ │ │ │ │ │ └── AcademyCalendarUpdateParam.java │ │ │ │ │ ├── result │ │ │ │ │ │ ├── AcademyCalendarUpdateResults.java │ │ │ │ │ │ ├── AcademyScheduleYearMonthResults.java │ │ │ │ │ │ ├── AcademyScheduleFindByDateResults.java │ │ │ │ │ │ ├── AcademyCalendarCreateResults.java │ │ │ │ │ │ ├── AcademyCalendarLoadToUpdateResult.java │ │ │ │ │ │ └── AcademyCalendarDetailResult.java │ │ │ │ │ ├── GeneratedLessonSchedule.java │ │ │ │ │ └── RepeatPeriod.java │ │ │ │ ├── AcademyCalendarAccessService.java │ │ │ │ ├── scheduler │ │ │ │ │ ├── ScheduleWeekMaker.java │ │ │ │ │ ├── ScheduleDailyMaker.java │ │ │ │ │ ├── ScheduleYearlyMaker.java │ │ │ │ │ ├── ScheduleMonthMaker.java │ │ │ │ │ └── AcademyScheduleMaker.java │ │ │ │ └── AcademyCalendarAccessServiceImpl.java │ │ │ ├── repository │ │ │ │ ├── dto │ │ │ │ │ └── AcademyTimeTemplateDateInfo.java │ │ │ │ └── academytimetemplate │ │ │ │ │ ├── AcademyTimeTemplateRepository.java │ │ │ │ │ └── AcademyTimeTemplateJpaRepository.java │ │ │ ├── exception │ │ │ │ ├── NotGeneratedScheduleException.java │ │ │ │ └── DateOverlapException.java │ │ │ ├── model │ │ │ │ └── Periodicity.java │ │ │ ├── controller │ │ │ │ └── dto │ │ │ │ │ ├── response │ │ │ │ │ ├── AcademyCalendarCreateResponse.java │ │ │ │ │ └── AcademyCalendarUpdateResponse.java │ │ │ │ │ └── request │ │ │ │ │ ├── AcademyCalendarDeleteRequest.java │ │ │ │ │ ├── LessonTime.java │ │ │ │ │ ├── AttendanceDate.java │ │ │ │ │ ├── validation │ │ │ │ │ ├── ValidDateString.java │ │ │ │ │ ├── ValidLessonTime.java │ │ │ │ │ ├── ValidAttendanceDate.java │ │ │ │ │ ├── ValidEnum.java │ │ │ │ │ ├── ValidEnumValidator.java │ │ │ │ │ └── AttendanceDateValidator.java │ │ │ │ │ └── AcademyCalendarDetailRequest.java │ │ │ └── facade │ │ │ │ └── dto │ │ │ │ └── AcademyCalendarDetailFacadeParam.java │ │ ├── member │ │ │ ├── service │ │ │ │ ├── MemberAccessService.java │ │ │ │ ├── param │ │ │ │ │ └── MemberRegisterParam.java │ │ │ │ └── result │ │ │ │ │ └── MemberInformationResult.java │ │ │ ├── annotation │ │ │ │ ├── ValidMember.java │ │ │ │ └── ValidatedMemberId.java │ │ │ ├── event │ │ │ │ └── WithdrawEvent.java │ │ │ ├── repository │ │ │ │ └── MemberRepository.java │ │ │ ├── model │ │ │ │ └── vo │ │ │ │ │ └── Email.java │ │ │ └── controller │ │ │ │ └── request │ │ │ │ └── MemberRegisterRequest.java │ │ ├── calendar_info │ │ │ ├── service │ │ │ │ ├── param │ │ │ │ │ └── CalendarYearMonthMarkParam.java │ │ │ │ ├── util │ │ │ │ │ └── DateUtility.java │ │ │ │ └── result │ │ │ │ │ ├── CalendarFindSchedulesByDateIncompleteResult.java │ │ │ │ │ └── ChildAcademyScheduleCombineResult.java │ │ │ └── controller │ │ │ │ └── request │ │ │ │ └── CalendarYearMonthMarkRequest.java │ │ ├── region │ │ │ ├── service │ │ │ │ └── dto │ │ │ │ │ ├── location │ │ │ │ │ ├── RegionGetNameParam.java │ │ │ │ │ ├── RegionGetNameResult.java │ │ │ │ │ └── RegionResult.java │ │ │ │ │ └── beopjungdong │ │ │ │ │ ├── SidoResult.java │ │ │ │ │ ├── SigunguResult.java │ │ │ │ │ └── UpmyeondongResult.java │ │ │ ├── aop │ │ │ │ ├── ValidSido.java │ │ │ │ ├── ValidSigungu.java │ │ │ │ └── ValidUpmyeondong.java │ │ │ ├── controller │ │ │ │ └── dto │ │ │ │ │ ├── RegionGetNameResponse.java │ │ │ │ │ ├── RegionGetNameRequest.java │ │ │ │ │ ├── RegionLocationResponse.java │ │ │ │ │ └── RegionResponse.java │ │ │ ├── model │ │ │ │ └── vo │ │ │ │ │ └── RegionUnit.java │ │ │ └── repository │ │ │ │ ├── RegionRepository.java │ │ │ │ └── RegionJpaRepository.java │ │ ├── review │ │ │ ├── service │ │ │ │ ├── dto │ │ │ │ │ ├── request │ │ │ │ │ │ └── ReviewPostParam.java │ │ │ │ │ └── response │ │ │ │ │ │ └── ReviewableResult.java │ │ │ │ ├── ReviewCommandService.java │ │ │ │ └── ReviewReadService.java │ │ │ ├── repository │ │ │ │ ├── ReviewRepository.java │ │ │ │ └── ReviewJpaRepository.java │ │ │ └── controller │ │ │ │ └── dto │ │ │ │ ├── response │ │ │ │ ├── ReviewPostResponse.java │ │ │ │ └── ReviewableResponse.java │ │ │ │ └── request │ │ │ │ └── ReviewPostRequest.java │ │ └── holiday │ │ │ ├── repository │ │ │ └── HolidayRepository.java │ │ │ ├── service │ │ │ ├── result │ │ │ │ └── HolidayFindByYearMonthResult.java │ │ │ └── HolidayService.java │ │ │ └── model │ │ │ └── Holiday.java │ │ └── StudayServerApplication.java └── test │ └── java │ └── org │ └── guzzing │ └── studayserver │ ├── testutil │ ├── fixture │ │ ├── child │ │ │ └── ChildFixture.java │ │ └── member │ │ │ └── MemberFixture.java │ └── security │ │ └── WithMockCustomOAuth2LoginUser.java │ ├── domain │ ├── academy │ │ ├── service │ │ │ └── TestDatabaseConfig.java │ │ ├── util │ │ │ ├── LatitudeTest.java │ │ │ └── LongitudeTest.java │ │ └── model │ │ │ ├── vo │ │ │ ├── AddressTest.java │ │ │ └── academyinfo │ │ │ │ └── AcademyInfoAboutScheduleDetailTest.java │ │ │ └── LessonTest.java │ ├── calendar │ │ └── controller │ │ │ └── dto │ │ │ └── request │ │ │ └── AcademyCalendarDetailRequestTest.java │ ├── dashboard │ │ └── model │ │ │ └── vo │ │ │ └── RepeatanceTest.java │ └── calendar_info │ │ └── service │ │ └── util │ │ └── DateUtilityTest.java │ └── config │ ├── QuerydslTestConfig.java │ └── JwtTestConfig.java ├── appspec.yml └── scripts └── deploy.sh /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'studayserver' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guzzing/Studay_Server/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/auth/OAuth2Provider.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.auth; 2 | 3 | public enum OAuth2Provider { 4 | KAKAO, 5 | GOOGLE; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/service/dto/AuthLogoutResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.service.dto; 2 | 3 | public record AuthLogoutResult( 4 | boolean isLogout 5 | ) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/param/ChildCreateParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.param; 2 | 3 | public record ChildCreateParam( 4 | String nickname, 5 | String grade 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/param/ChildDeleteParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.param; 2 | 3 | public record ChildDeleteParam( 4 | Long memberId, 5 | Long childId 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/service/dto/request/LikePostParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.service.dto.request; 2 | 3 | public record LikePostParam( 4 | Long memberId, 5 | Long academyId 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/dto/DashboardPatchResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.dto; 2 | 3 | public record DashboardPatchResult( 4 | long dashboardId, 5 | boolean isActive 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/AcademyFee.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto; 2 | 3 | public interface AcademyFee { 4 | 5 | Long getMaxEducationFee(); 6 | 7 | String getAcademyName(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/AcademyCalendarLoadToUpdateParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | public record AcademyCalendarLoadToUpdateParam( 4 | Long academyScheduleId 5 | ) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/LessonInfoToCreateDashboard.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto; 2 | 3 | public interface LessonInfoToCreateDashboard { 4 | 5 | Long getId(); 6 | 7 | String getCurriculum(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/AcademyCalendarDetailParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | public record AcademyCalendarDetailParam( 4 | Long childId, 5 | Long scheduleId 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/result/ChildProfileImagePatchResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.result; 2 | 3 | public record ChildProfileImagePatchResult( 4 | Long childId, 5 | String profileImageUrl 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/LikeException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class LikeException extends RuntimeException { 4 | 5 | public LikeException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/dto/DashboardGetResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.dto; 2 | 3 | import java.util.List; 4 | 5 | public record DashboardGetResults( 6 | List results 7 | ) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/ChildException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class ChildException extends RuntimeException { 4 | 5 | public ChildException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/response/DashboardPatchResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.response; 2 | 3 | public record DashboardPatchResponse( 4 | long dashboardId, 5 | boolean isActive 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/AcademyException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class AcademyException extends RuntimeException { 4 | 5 | public AcademyException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/MemberException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class MemberException extends RuntimeException { 4 | 5 | public MemberException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/RegionException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class RegionException extends RuntimeException { 4 | 5 | public RegionException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/ReviewException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class ReviewException extends RuntimeException { 4 | 5 | public ReviewException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/AcademyCalendarDeleteParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | public record AcademyCalendarDeleteParam( 4 | Long academyScheduleId, 5 | boolean isAllDeleted 6 | ) { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/client/ClientStrategy.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.client; 2 | 3 | import org.guzzing.studayserver.domain.member.model.Member; 4 | 5 | public interface ClientStrategy { 6 | 7 | Member getUserData(String accessToken); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/service/MemberAccessService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.service; 2 | 3 | public interface MemberAccessService { 4 | 5 | void validateMember(final Long memberId); 6 | 7 | void validateChild(final Long memberId, final Long childId); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar_info/service/param/CalendarYearMonthMarkParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.service.param; 2 | 3 | public record CalendarYearMonthMarkParam( 4 | long memberId, 5 | int year, 6 | int month 7 | ) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/param/ChildModifyParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.param; 2 | 3 | public record ChildModifyParam( 4 | String nickname, 5 | String grade, 6 | Long memberId, 7 | Long childId 8 | ) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/result/AcademyCalendarDetailChildInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.result; 2 | 3 | public record AcademyCalendarDetailChildInfo( 4 | Long childId, 5 | String childName, 6 | String imageUrl 7 | ) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/response/DashboardGetResponses.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.response; 2 | 3 | import java.util.List; 4 | 5 | public record DashboardGetResponses( 6 | List responses 7 | ) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/service/dto/response/LikedAcademyFeeInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.service.dto.response; 2 | 3 | public record LikedAcademyFeeInfo( 4 | long likeId, 5 | long academyId, 6 | String academyName, 7 | Long expectedFee 8 | ) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/request/AcademyByLocationWithCursorRepositoryRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.request; 2 | 3 | public record AcademyByLocationWithCursorRepositoryRequest( 4 | String pointFormat, 5 | Long memberId, 6 | Long lastAcademyId 7 | ) { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/LessonException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class LessonException extends RuntimeException { 4 | 5 | public LessonException() { 6 | } 7 | 8 | public LessonException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/JpaConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 5 | 6 | @EnableJpaAuditing 7 | @Configuration 8 | public class JpaConfig { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/ScheduleConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.scheduling.annotation.EnableScheduling; 5 | 6 | @EnableScheduling 7 | @Configuration 8 | public class ScheduleConfig { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/AcademyFilterCondition.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto; 2 | 3 | public record AcademyFilterCondition( 4 | String pointFormat, 5 | String categories, 6 | Long desiredMinAmount, 7 | Long desiredMaxAmount 8 | ) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/response/DashboardPostResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.response; 2 | 3 | public record DashboardPostResponse( 4 | long dashboardId, 5 | long childId, 6 | long academyId, 7 | long lessonId 8 | ) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/exception/DashboardException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.exception; 2 | 3 | public class DashboardException extends RuntimeException { 4 | 5 | public DashboardException() { 6 | } 7 | 8 | public DashboardException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/AcademyCalendarDeleteByDashboardParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | import java.time.LocalDate; 4 | 5 | public record AcademyCalendarDeleteByDashboardParam( 6 | Long dashboardId, 7 | LocalDate requestedDate 8 | ) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/location/RegionGetNameParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.location; 2 | 3 | import org.guzzing.studayserver.domain.region.controller.dto.RegionGetNameRequest; 4 | 5 | public record RegionGetNameParam( 6 | double latitude, 7 | double longitude 8 | ) { 9 | } 10 | -------------------------------------------------------------------------------- /appspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.0 2 | os: linux 3 | 4 | files: 5 | - source: / 6 | destination: /home/ubuntu/studay 7 | overwrite: yes 8 | file_exists_behavior: OVERWRITE 9 | permissions: 10 | - object: /home/ubuntu/studay/ 11 | owner: ubuntu 12 | group: ubuntu 13 | hooks: 14 | AfterInstall: 15 | - location: scripts/deploy.sh 16 | timeout: 60 17 | runas: ubuntu 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/model/vo/SimpleMemo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.vo; 2 | 3 | public record SimpleMemo( 4 | boolean kindness, 5 | boolean goodFacility, 6 | boolean cheapFee, 7 | boolean goodManagement, 8 | boolean lovelyTeaching, 9 | boolean shuttleAvailability 10 | ) { 11 | 12 | } -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/service/dto/AuthRefreshResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.service.dto; 2 | 3 | public record AuthRefreshResult( 4 | String appToken, 5 | Long userId 6 | ) { 7 | 8 | public static AuthRefreshResult of(String appToken, Long userId) { 9 | return new AuthRefreshResult(appToken, userId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/repository/dto/AcademyTimeTemplateDateInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.repository.dto; 2 | 3 | import java.time.LocalDate; 4 | 5 | public interface AcademyTimeTemplateDateInfo { 6 | 7 | LocalDate getStartDateOfAttendance(); 8 | 9 | LocalDate getEndDateOfAttendance(); 10 | 11 | Long getId(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/LessonScheduleParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalTime; 5 | 6 | public record LessonScheduleParam( 7 | DayOfWeek dayOfWeek, 8 | LocalTime lessonStartTime, 9 | LocalTime lessonEndTime 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/repository/DashboardQuerydslRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.dashboard.model.Dashboard; 5 | 6 | public interface DashboardQuerydslRepository { 7 | 8 | List findActiveOnlyByChildId(final Long childId); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademiesByName.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | public interface AcademiesByName { 4 | 5 | Long getAcademyId(); 6 | 7 | String getAcademyName(); 8 | 9 | String getFullAddress(); 10 | 11 | Double getLongitude(); 12 | 13 | Double getLatitude(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/AcademyCalendarAccessService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service; 2 | 3 | import org.guzzing.studayserver.domain.calendar.service.dto.param.AcademyCalendarDeleteByDashboardParam; 4 | 5 | public interface AcademyCalendarAccessService { 6 | 7 | void deleteSchedule(AcademyCalendarDeleteByDashboardParam param); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/access/DashboardAccessService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.access; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.service.dto.response.DashboardScheduleAccessResult; 4 | 5 | public interface DashboardAccessService { 6 | 7 | DashboardScheduleAccessResult getDashboardSchedule(Long dashboardId); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/access/dto/LessonScheduleAccessResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.access.dto; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalTime; 5 | 6 | public record LessonScheduleAccessResult( 7 | DayOfWeek dayOfWeek, 8 | LocalTime lessonStartTime, 9 | LocalTime lessonEndTime 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/service/param/MemberRegisterParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.service.param; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.child.service.param.ChildCreateParam; 5 | 6 | public record MemberRegisterParam( 7 | String nickname, 8 | String email, 9 | List children 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/aop/ValidSido.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.aop; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface ValidSido { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/aop/ValidSigungu.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.aop; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface ValidSigungu { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/member/MemberId.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.member; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.PARAMETER}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface MemberId { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/aop/ValidUpmyeondong.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.aop; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface ValidUpmyeondong { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/testutil/fixture/child/ChildFixture.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.testutil.fixture.child; 2 | 3 | import org.guzzing.studayserver.domain.child.model.Child; 4 | 5 | public class ChildFixture { 6 | 7 | public static Child child() { 8 | return new Child( 9 | "김별", 10 | "초등학교 1학년", 11 | "aakdjlaf.com" 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/StudayServerApplication.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class StudayServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(StudayServerApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/annotation/ValidMember.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Target(ElementType.METHOD) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface ValidMember { 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/annotation/ValidatedMemberId.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Target(ElementType.PARAMETER) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | public @interface ValidatedMemberId { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/dto/DashboardPutResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.dto; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | 6 | public record DashboardPutResult( 7 | long dashboardId, 8 | PaymentInfo paymentInfo, 9 | SimpleMemo simpleMemo 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/vo/ChildInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.vo; 2 | 3 | import org.guzzing.studayserver.domain.child.model.Child; 4 | 5 | public record ChildInfo( 6 | long childId, 7 | String childNickName 8 | ) { 9 | 10 | public static ChildInfo from(final Child entity) { 11 | return new ChildInfo(entity.getId(), entity.getNickName()); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/param/AcademiesByNameParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.param; 2 | 3 | public record AcademiesByNameParam( 4 | String academyName, 5 | int pageNumber 6 | ) { 7 | 8 | public static AcademiesByNameParam of(String academyName, 9 | int pageNumber) { 10 | return new AcademiesByNameParam(academyName, pageNumber); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar_info/service/util/DateUtility.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.service.util; 2 | 3 | import java.time.YearMonth; 4 | 5 | public class DateUtility { 6 | 7 | private DateUtility() { 8 | } 9 | 10 | public static int getLastDayOfMonth(int year, int month) { 11 | YearMonth yearMonth = YearMonth.of(year, month); 12 | return yearMonth.lengthOfMonth(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/repository/ChildRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.repository; 2 | 3 | import java.util.Optional; 4 | import org.guzzing.studayserver.domain.child.model.Child; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface ChildRepository extends JpaRepository { 8 | 9 | Optional findByIdAndMemberId(Long childId, Long memberId); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/model/dto/PaymentInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.dto; 2 | 3 | import jakarta.validation.constraints.Positive; 4 | import java.time.LocalDate; 5 | 6 | public record PaymentInfo( 7 | @Positive Long educationFee, 8 | @Positive Long bookFee, 9 | @Positive Long shuttleFee, 10 | @Positive Long etcFee, 11 | LocalDate paymentDay 12 | ) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/dto/response/DashBoardFindByIdsResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.dto.response; 2 | 3 | import java.util.List; 4 | 5 | public record DashBoardFindByIdsResults( 6 | List dashBoards 7 | ) { 8 | 9 | public record DashBoardFindByIdsResult( 10 | Long dashboardId, 11 | Long lessonId 12 | ) { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/scheduler/ScheduleWeekMaker.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.scheduler; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class ScheduleWeekMaker implements AcademyScheduleMaker { 6 | 7 | private static final Long WEEKLY = 1L; 8 | 9 | @Override 10 | public LocalDate getNextRepeatedDate(LocalDate baseDate) { 11 | return baseDate.plusWeeks(WEEKLY); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/scheduler/ScheduleDailyMaker.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.scheduler; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class ScheduleDailyMaker implements AcademyScheduleMaker { 6 | 7 | private static final Long DAILY = 1L; 8 | 9 | @Override 10 | public LocalDate getNextRepeatedDate(LocalDate baseDate) { 11 | return baseDate.plusDays(DAILY); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/scheduler/ScheduleYearlyMaker.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.scheduler; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class ScheduleYearlyMaker implements AcademyScheduleMaker { 6 | 7 | private static final Long YEARLY = 1L; 8 | 9 | @Override 10 | public LocalDate getNextRepeatedDate(LocalDate baseDate) { 11 | return baseDate.plusYears(YEARLY); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/ChildDateScheduleResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service; 2 | 3 | import java.time.LocalDate; 4 | import java.time.LocalTime; 5 | 6 | public record ChildDateScheduleResult( 7 | Long childId, 8 | LocalDate schedule_date, 9 | LocalTime lessonStartTime, 10 | LocalTime lessonEndTime, 11 | String academyName, 12 | String lessonSubject 13 | ) { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/dto/request/DashboardPutParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.dto.request; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | 6 | public record DashboardPutParam( 7 | long dashboardId, 8 | PaymentInfo paymentInfo, 9 | SimpleMemo simpleMemo 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/service/dto/request/ReviewPostParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.service.dto.request; 2 | 3 | public record ReviewPostParam( 4 | Long memberId, 5 | Long academyId, 6 | Boolean kindness, 7 | Boolean cheapFee, 8 | Boolean goodFacility, 9 | Boolean goodManagement, 10 | Boolean lovelyTeaching, 11 | Boolean shuttleAvailability 12 | ) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/vo/academyinfo/ShuttleAvailability.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model.vo.academyinfo; 2 | 3 | import java.util.Objects; 4 | 5 | public enum ShuttleAvailability { 6 | AVAILABLE, 7 | NEED_INQUIRE, 8 | FREE; 9 | 10 | public static ShuttleAvailability getShuttleAvailability(final String shuttle) { 11 | return Objects.equals(shuttle, "0") ? NEED_INQUIRE : AVAILABLE; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/scheduler/ScheduleMonthMaker.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.scheduler; 2 | 3 | import java.time.LocalDate; 4 | 5 | public class ScheduleMonthMaker implements AcademyScheduleMaker { 6 | 7 | private static final Long MONTHLY = 1L; 8 | 9 | @Override 10 | public LocalDate getNextRepeatedDate(LocalDate baseDate) { 11 | return baseDate.plusMonths(MONTHLY); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/facade/dto/AcademyDetailFacadeParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.facade.dto; 2 | 3 | public record AcademyDetailFacadeParam( 4 | Long memberId, 5 | Long academyId 6 | ) { 7 | 8 | public static AcademyDetailFacadeParam of(Long memberId, Long academyId) { 9 | return new AcademyDetailFacadeParam( 10 | memberId, 11 | academyId 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademyByFilterWithScroll.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | public record AcademyByFilterWithScroll( 4 | Long academyId, 5 | String academyName, 6 | String fullAddress, 7 | String phoneNumber, 8 | Double latitude, 9 | Double longitude, 10 | String shuttleAvailable, 11 | boolean isLiked 12 | ) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/LessonFindByIdsResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import java.util.List; 4 | 5 | public record LessonFindByIdsResults( 6 | List lessons 7 | ) { 8 | 9 | public record LessonFindByIdsResult( 10 | Long lessonId, 11 | String academyName, 12 | String lessonName 13 | ) { 14 | 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/response/DashboardPutResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | 6 | public record DashboardPutResponse( 7 | long dashboardId, 8 | PaymentInfo paymentInfo, 9 | SimpleMemo simpleMemo 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/service/dto/AuthLoginResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.service.dto; 2 | 3 | public record AuthLoginResult( 4 | String appToken, 5 | Boolean isNewMember, 6 | Long userId, 7 | String name 8 | ) { 9 | 10 | public static AuthLoginResult of(String appToken, boolean isNewMember, Long userId, String name) { 11 | return new AuthLoginResult(appToken, isNewMember, userId, name); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/beopjungdong/SidoResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.beopjungdong; 2 | 3 | import java.util.List; 4 | 5 | public record SidoResult( 6 | String nation, 7 | List sidos, 8 | int sidoCount 9 | ) { 10 | 11 | public static SidoResult from(final List baseRegionSido) { 12 | return new SidoResult("전국", baseRegionSido, baseRegionSido.size()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/ChildAccessService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service; 2 | 3 | import org.guzzing.studayserver.domain.child.service.result.AcademyCalendarDetailChildInfo; 4 | import org.guzzing.studayserver.domain.dashboard.facade.vo.ChildInfo; 5 | 6 | public interface ChildAccessService { 7 | 8 | ChildInfo findChildInfo(final Long childId); 9 | 10 | AcademyCalendarDetailChildInfo getChildImages(final Long childrenId); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/service/dto/response/ReviewableResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.service.dto.response; 2 | 3 | public record ReviewableResult( 4 | long memberId, 5 | long academyId, 6 | boolean reviewable 7 | ) { 8 | 9 | public static ReviewableResult of(final long memberId, final long academyId, final boolean reviewable) { 10 | return new ReviewableResult(memberId, academyId, reviewable); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/TimeZoneConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import java.util.TimeZone; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class TimeZoneConfig implements CommandLineRunner { 9 | 10 | @Override 11 | public void run(String... args) { 12 | TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/controller/dto/AuthLogoutResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.controller.dto; 2 | 3 | import org.guzzing.studayserver.domain.auth.service.dto.AuthLogoutResult; 4 | 5 | public record AuthLogoutResponse( 6 | boolean isLogout 7 | ) { 8 | 9 | public static AuthLogoutResponse from(AuthLogoutResult authLogoutResult) { 10 | return new AuthLogoutResponse( 11 | authLogoutResult.isLogout() 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/request/DashboardPutRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.NotNull; 4 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 5 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 6 | 7 | public record DashboardPutRequest( 8 | PaymentInfo paymentInfo, 9 | @NotNull SimpleMemo simpleMemo 10 | ) { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/academycategory/AcademyCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.academycategory; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.AcademyCategory; 5 | 6 | public interface AcademyCategoryRepository { 7 | 8 | AcademyCategory save(AcademyCategory academyCategory); 9 | 10 | List findCategoryIdsByAcademyId(Long academyId); 11 | 12 | void deleteAll(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/beopjungdong/SigunguResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.beopjungdong; 2 | 3 | import java.util.List; 4 | 5 | public record SigunguResult( 6 | String sido, 7 | List sigungus, 8 | int sigunguCount 9 | ) { 10 | 11 | public static SigunguResult from(final String sido, final List sigungus) { 12 | return new SigunguResult(sido, sigungus, sigungus.size()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # JAR 파일 경로 설정 4 | JAR_PATH="/home/ubuntu/studay/build/libs/studayserver-0.0.1-SNAPSHOT.jar" 5 | 6 | # 실행 중인 애플리케이션의 PID 찾기 7 | CURRENT_PID=$(pgrep -f $JAR_PATH) 8 | 9 | # 실행 중인 애플리케이션이 있으면 종료 10 | if [[ -n $CURRENT_PID ]]; then 11 | echo "종료할 프로세스 PID: $CURRENT_PID" 12 | sudo kill $CURRENT_PID 13 | 14 | # 프로세스가 종료될 때까지 대기 15 | while ps -p $CURRENT_PID &>/dev/null; do 16 | sleep 1 17 | done 18 | fi 19 | 20 | # 애플리케이션 실행 21 | nohup java -jar $JAR_PATH &>/dev/null & 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademyByLocationRepositoryResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | public interface AcademyByLocationRepositoryResponse { 4 | 5 | long getAcademyId(); 6 | String getAcademyName(); 7 | String getFullAddress(); 8 | String getPhoneNumber(); 9 | double getLatitude(); 10 | double getLongitude(); 11 | String getShuttleAvailable(); 12 | long getCategoryId(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/util/Direction.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.util; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum Direction { 7 | NORTH(0.0), 8 | WEST(270.0), 9 | SOUTH(180.0), 10 | EAST(90.0), 11 | NORTHWEST(315.0), 12 | SOUTHWEST(225.0), 13 | SOUTHEAST(135.0), 14 | NORTHEAST(45.0); 15 | 16 | private final Double bearing; 17 | 18 | Direction(Double bearing) { 19 | this.bearing = bearing; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/exception/NotGeneratedScheduleException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.exception; 2 | 3 | import org.guzzing.studayserver.global.error.response.ErrorCode; 4 | 5 | public class NotGeneratedScheduleException extends RuntimeException { 6 | 7 | private final ErrorCode errorCode; 8 | 9 | public NotGeneratedScheduleException(final ErrorCode errorCode) { 10 | super(errorCode.getMessage()); 11 | this.errorCode = errorCode; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/service/dto/response/LikePostResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.service.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.like.model.Like; 4 | 5 | public record LikePostResult( 6 | Long likeId, 7 | Long memberId, 8 | Long academyId 9 | ) { 10 | 11 | public static LikePostResult from(final Like entity) { 12 | return new LikePostResult(entity.getId(), entity.getMemberId(), entity.getAcademyId()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/repository/ReviewRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.repository; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.Academy; 4 | import org.guzzing.studayserver.domain.member.model.Member; 5 | import org.guzzing.studayserver.domain.review.model.Review; 6 | 7 | public interface ReviewRepository { 8 | 9 | Review save(final Review review); 10 | 11 | boolean existsByMemberAndAcademy(final Member member, final Academy academy); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/exception/TokenExpiredException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.exception; 2 | 3 | import lombok.Getter; 4 | import org.guzzing.studayserver.global.error.response.ErrorCode; 5 | 6 | @Getter 7 | public class TokenExpiredException extends RuntimeException { 8 | 9 | private final ErrorCode errorCode; 10 | 11 | public TokenExpiredException(final ErrorCode errorCode) { 12 | super(errorCode.getMessage()); 13 | this.errorCode = errorCode; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/exception/TokenIsLogoutException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.exception; 2 | 3 | import lombok.Getter; 4 | import org.guzzing.studayserver.global.error.response.ErrorCode; 5 | 6 | @Getter 7 | public class TokenIsLogoutException extends RuntimeException { 8 | 9 | private final ErrorCode errorCode; 10 | 11 | public TokenIsLogoutException(final ErrorCode errorCode) { 12 | super(errorCode.getMessage()); 13 | this.errorCode = errorCode; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/controller/dto/response/ReviewPostResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.review.service.dto.response.ReviewPostResult; 4 | 5 | public record ReviewPostResponse( 6 | Long reviewId, 7 | Long academyId 8 | ) { 9 | 10 | public static ReviewPostResponse from(final ReviewPostResult result) { 11 | return new ReviewPostResponse(result.reviewId(), result.academyId()); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/CategoryName.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CategoryName { 7 | MATH(1L), 8 | SCIENCE(2L), 9 | KOREAN_LANGUAGE(3L), 10 | ENGLISH(4L), 11 | COMPUTER(5L), 12 | ARTS_AND_PHYSICAL_EDUCATION(6L), 13 | FOREIGN_LANGUAGE(7L), 14 | TUTORING_SCHOOL(8L), 15 | ETC(9L); 16 | 17 | private final Long id; 18 | 19 | CategoryName(Long id) { 20 | this.id = id; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/exception/TokenValidFailedException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.exception; 2 | 3 | import lombok.Getter; 4 | import org.guzzing.studayserver.global.error.response.ErrorCode; 5 | 6 | @Getter 7 | public class TokenValidFailedException extends IllegalStateException { 8 | 9 | private final ErrorCode errorCode; 10 | 11 | public TokenValidFailedException(final ErrorCode errorCode) { 12 | super(errorCode.getMessage()); 13 | this.errorCode = errorCode; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/service/TestDatabaseConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service; 2 | 3 | import org.springframework.boot.test.context.TestConfiguration; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.jdbc.core.JdbcTemplate; 6 | 7 | @TestConfiguration 8 | public class TestDatabaseConfig { 9 | 10 | @Bean 11 | public DatabaseInitializer databaseInitializer(JdbcTemplate jdbcTemplate) { 12 | return new DatabaseInitializer(jdbcTemplate); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/config/QuerydslTestConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.config; 2 | 3 | import com.querydsl.jpa.impl.JPAQueryFactory; 4 | import jakarta.persistence.EntityManager; 5 | import org.springframework.boot.test.context.TestConfiguration; 6 | import org.springframework.context.annotation.Bean; 7 | 8 | @TestConfiguration 9 | public class QuerydslTestConfig { 10 | 11 | @Bean 12 | public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) { 13 | return new JPAQueryFactory(entityManager); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/controller/dto/response/LikePostResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.like.service.dto.response.LikePostResult; 4 | 5 | public record LikePostResponse( 6 | Long likeId, 7 | Long memberId, 8 | Long academyId 9 | ) { 10 | 11 | public static LikePostResponse from(final LikePostResult result) { 12 | return new LikePostResponse(result.likeId(), result.memberId(), result.academyId()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/QueryDslConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import com.querydsl.jpa.impl.JPAQueryFactory; 4 | import jakarta.persistence.EntityManager; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class QueryDslConfig { 10 | 11 | @Bean 12 | public JPAQueryFactory jpaQueryFactory(final EntityManager entityManager) { 13 | return new JPAQueryFactory(entityManager); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/AcademyFeeInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.AcademyFee; 4 | 5 | public record AcademyFeeInfo( 6 | String academyName, 7 | Long expectedFee 8 | ) { 9 | 10 | public static AcademyFeeInfo from(AcademyFee academyFee) { 11 | return new AcademyFeeInfo( 12 | academyFee.getAcademyName(), 13 | academyFee.getMaxEducationFee()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyCalendarUpdateResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.util.List; 4 | 5 | public record AcademyCalendarUpdateResults( 6 | List academyTimeTemplateIds 7 | ) { 8 | 9 | public static AcademyCalendarUpdateResults to(AcademyCalendarCreateResults academyCalendarCreateResults) { 10 | return new AcademyCalendarUpdateResults( 11 | academyCalendarCreateResults.academyTimeTemplateIds() 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/controller/dto/AuthRefreshResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.controller.dto; 2 | 3 | import org.guzzing.studayserver.domain.auth.service.dto.AuthRefreshResult; 4 | 5 | public record AuthRefreshResponse( 6 | String appToken, 7 | Long userId 8 | ) { 9 | 10 | public static AuthRefreshResponse from(AuthRefreshResult authRefreshResult) { 11 | return new AuthRefreshResponse( 12 | authRefreshResult.appToken(), 13 | authRefreshResult.userId() 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/exception/DateOverlapException.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.exception; 2 | 3 | import java.util.Set; 4 | import org.guzzing.studayserver.global.error.response.ErrorCode; 5 | 6 | public class DateOverlapException extends RuntimeException { 7 | 8 | private final ErrorCode errorCode; 9 | 10 | public DateOverlapException(final ErrorCode errorCode, Set dashboardIds) { 11 | super(String.format("중복된 시간표:{} {}", dashboardIds, errorCode.getMessage())); 12 | this.errorCode = errorCode; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/controller/dto/response/ReviewableResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.review.service.dto.response.ReviewableResult; 4 | 5 | public record ReviewableResponse( 6 | long academyId, 7 | boolean reviewable 8 | ) { 9 | 10 | public static ReviewableResponse from(final ReviewableResult result) { 11 | return new ReviewableResponse( 12 | result.academyId(), 13 | result.reviewable()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/model/vo/SimpleMemoType.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.vo; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum SimpleMemoType { 7 | KINDNESS("kindness"), 8 | GOOD_FACILITY("goodFacility"), 9 | CHEAP_FEE("cheapFee"), 10 | GOOD_MANAGEMENT("goodManagement"), 11 | LOVELY_TEACHING("lovelyTeaching"), 12 | SHUTTLE_AVAILABILITY("shuttleAvailability"); 13 | 14 | private final String type; 15 | 16 | SimpleMemoType(final String type) { 17 | this.type = type; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/location/RegionGetNameResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.location; 2 | 3 | import org.guzzing.studayserver.domain.region.model.Region; 4 | 5 | public record RegionGetNameResult( 6 | String sido, 7 | String sigungu, 8 | String upmyeondong 9 | ) { 10 | public static RegionGetNameResult from(Region region) { 11 | return new RegionGetNameResult( 12 | region.getSido(), 13 | region.getSigungu(), 14 | region.getUpmyeondong() 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/repository/ReviewJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.repository; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.Academy; 4 | import org.guzzing.studayserver.domain.member.model.Member; 5 | import org.guzzing.studayserver.domain.review.model.Review; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | public interface ReviewJpaRepository extends JpaRepository, ReviewRepository { 9 | 10 | boolean existsByMemberAndAcademy(final Member member, final Academy academy); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/holiday/repository/HolidayRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.holiday.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.holiday.model.Holiday; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | 8 | public interface HolidayRepository extends JpaRepository { 9 | 10 | @Query("SELECT h FROM Holiday h WHERE YEAR(h.date) = :year AND MONTH(h.date) = :month") 11 | List findByYearMonth(int year, int month); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/beopjungdong/UpmyeondongResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.beopjungdong; 2 | 3 | import java.util.List; 4 | 5 | public record UpmyeondongResult( 6 | String sido, 7 | String sigungu, 8 | List upmyeondongs, 9 | int upmyeondongCount 10 | ) { 11 | 12 | public static UpmyeondongResult from(final String sido, final String sigungu, final List upmyeondong) { 13 | return new UpmyeondongResult(sido, sigungu, upmyeondong, upmyeondong.size()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/controller/response/ChildProfileImagePatchResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.controller.response; 2 | 3 | import org.guzzing.studayserver.domain.child.service.result.ChildProfileImagePatchResult; 4 | 5 | public record ChildProfileImagePatchResponse( 6 | Long childId, 7 | String profileImageUrl 8 | ) { 9 | 10 | public static ChildProfileImagePatchResponse from(final ChildProfileImagePatchResult result) { 11 | return new ChildProfileImagePatchResponse(result.childId(), result.profileImageUrl()); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/event/WithdrawEvent.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.event; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import java.util.List; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class WithdrawEvent { 9 | 10 | private final HttpServletRequest request; 11 | private final List childProfileImageUris; 12 | 13 | public WithdrawEvent(HttpServletRequest request, List childProfileImageUris) { 14 | this.request = request; 15 | this.childProfileImageUris = childProfileImageUris; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/testutil/fixture/member/MemberFixture.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.testutil.fixture.member; 2 | 3 | import org.guzzing.studayserver.domain.member.model.Member; 4 | import org.guzzing.studayserver.domain.member.model.vo.NickName; 5 | import org.guzzing.studayserver.global.common.auth.OAuth2Provider; 6 | import org.guzzing.studayserver.global.common.auth.RoleType; 7 | 8 | public class MemberFixture { 9 | 10 | public static Member makeMemberEntity() { 11 | return Member.of(new NickName("나는왕이다"), "12345678", OAuth2Provider.KAKAO, RoleType.USER); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/time/TimeConverter.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.time; 2 | 3 | import java.time.LocalTime; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class TimeConverter { 8 | 9 | protected TimeConverter() { 10 | } 11 | 12 | public static LocalTime getLocalTime(final String time) { 13 | final List timeData = Arrays.stream(time.split(":")) 14 | .map(Integer::parseInt) 15 | .toList(); 16 | 17 | return LocalTime.of(timeData.get(0), timeData.get(1)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/request/AcademiesByNameRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.request; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.param.AcademiesByNameParam; 4 | 5 | public record AcademiesByNameRequest( 6 | String academyName, 7 | int pageNumber 8 | ) { 9 | 10 | public static AcademiesByNameParam to(AcademiesByNameRequest request) { 11 | return new AcademiesByNameParam( 12 | request.academyName, 13 | request.pageNumber 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyScheduleYearMonthResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | 6 | public record AcademyScheduleYearMonthResults( 7 | List academyScheduleYearMonthResults 8 | ) { 9 | 10 | public record AcademyScheduleYearMonthResult( 11 | Long academyTimeTemplateId, 12 | Long childId, 13 | Long academyScheduleId, 14 | LocalDate scheduleDate 15 | ) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/controller/dto/RegionGetNameResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.controller.dto; 2 | 3 | import org.guzzing.studayserver.domain.region.service.dto.location.RegionGetNameResult; 4 | 5 | public record RegionGetNameResponse( 6 | String sido, 7 | String sigungu, 8 | String upmyeondong 9 | ) { 10 | public static RegionGetNameResponse to(RegionGetNameResult result) { 11 | return new RegionGetNameResponse( 12 | result.sido(), 13 | result.sigungu(), 14 | result.upmyeondong() 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/repository/MemberRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.repository; 2 | 3 | import java.util.Optional; 4 | import org.guzzing.studayserver.domain.member.model.Member; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | 8 | public interface MemberRepository extends JpaRepository { 9 | 10 | Member findBySocialId(String socialId); 11 | 12 | @Query("select m from Member m where m.socialId= ?1") 13 | Optional findMemberIfExisted(String socialId); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/model/vo/RegionUnit.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.model.vo; 2 | 3 | import java.util.List; 4 | 5 | public enum RegionUnit { 6 | SIDO(List.of("시", "도")), 7 | SIGUNGU(List.of("시", "군", "구")), 8 | UPMYEONDONG(List.of("구", "읍", "면", "동")); 9 | 10 | private final List unitValue; 11 | 12 | RegionUnit(List unitValue) { 13 | this.unitValue = unitValue; 14 | } 15 | 16 | public boolean isMatched(final String input) { 17 | return this.unitValue.stream() 18 | .anyMatch(input::contains); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/model/Periodicity.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.model; 2 | 3 | import java.util.Arrays; 4 | import java.util.Objects; 5 | 6 | public enum Periodicity { 7 | DAILY, 8 | WEEKLY, 9 | MONTHLY, 10 | YEARLY; 11 | 12 | public static Periodicity of(final String value) { 13 | return Arrays.stream(Periodicity.values()) 14 | .filter(periodicity -> Objects.equals(periodicity.name(), value)) 15 | .findAny() 16 | .orElseThrow(() -> new IllegalArgumentException("설정한 반복 주기와 일치하는 주기가 없습니다.")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/dto/response/DashboardScheduleAccessResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.model.Periodicity; 5 | import org.guzzing.studayserver.domain.dashboard.service.access.dto.LessonScheduleAccessResult; 6 | 7 | public record DashboardScheduleAccessResult( 8 | Long childId, 9 | Long academyId, 10 | Long lessonId, 11 | Periodicity periodicity, 12 | List lessonScheduleInAccessResponses 13 | ) { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/LessonGetResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.Lesson; 5 | 6 | public record LessonGetResults( 7 | List lessonGetResults 8 | ) { 9 | 10 | public static LessonGetResults from(List lessons) { 11 | return new LessonGetResults( 12 | lessons 13 | .stream() 14 | .map(LessonGetResult::from) 15 | .toList()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyScheduleFindByDateResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.time.LocalTime; 4 | import java.util.List; 5 | 6 | public record AcademyScheduleFindByDateResults( 7 | List academySchedules 8 | ) { 9 | 10 | 11 | public record AcademyScheduleFindByDateResult( 12 | long academyScheduleId, 13 | LocalTime startTime, 14 | LocalTime endTime, 15 | long dashboardId, 16 | Long childId 17 | ) { 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/dto/request/DashboardPostParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.dto.request; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | import org.guzzing.studayserver.domain.dashboard.service.vo.ScheduleInfos; 6 | 7 | public record DashboardPostParam( 8 | Long childId, 9 | Long academyId, 10 | Long lessonId, 11 | ScheduleInfos scheduleInfos, 12 | PaymentInfo paymentInfo, 13 | SimpleMemo simpleMemo 14 | ) { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/response/AcademyCalendarCreateResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.service.dto.result.AcademyCalendarCreateResults; 5 | 6 | public record AcademyCalendarCreateResponse( 7 | List academyTimeTemplateIds 8 | ) { 9 | 10 | public static AcademyCalendarCreateResponse from(AcademyCalendarCreateResults results) { 11 | return new AcademyCalendarCreateResponse( 12 | results.academyTimeTemplateIds() 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/response/AcademyCalendarUpdateResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.service.dto.result.AcademyCalendarUpdateResults; 5 | 6 | public record AcademyCalendarUpdateResponse( 7 | List academyCalendarIds 8 | ) { 9 | 10 | public static AcademyCalendarUpdateResponse from(AcademyCalendarUpdateResults results) { 11 | return new AcademyCalendarUpdateResponse( 12 | results.academyTimeTemplateIds() 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/result/ChildrenFindResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service.result; 2 | 3 | import java.util.List; 4 | 5 | public record ChildrenFindResult( 6 | List children 7 | ) { 8 | 9 | public ChildrenFindResult(List children) { 10 | this.children = List.copyOf(children); 11 | } 12 | 13 | public record ChildFindResult( 14 | Long childId, 15 | String profileImageUrl, 16 | String nickname, 17 | String grade, 18 | String schedule 19 | ) { 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/testutil/security/WithMockCustomOAuth2LoginUser.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.testutil.security; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | import org.springframework.security.test.context.support.WithSecurityContext; 6 | 7 | @Retention(RetentionPolicy.RUNTIME) 8 | @WithSecurityContext(factory = WithMockCustomOAuth2LoginUserSecurityContextFactory.class) 9 | public @interface WithMockCustomOAuth2LoginUser { 10 | 11 | long memberId() default 1L; 12 | 13 | String socialId() default "a"; 14 | 15 | String username() default "username"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/review/ReviewCountJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.review; 2 | 3 | import java.util.Optional; 4 | import org.guzzing.studayserver.domain.academy.model.ReviewCount; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | 8 | public interface ReviewCountJpaRepository extends JpaRepository, ReviewCountRepository { 9 | 10 | @Query("select rc from ReviewCount rc where rc.academy.id =:academyId") 11 | Optional findByAcademyId(Long academyId); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/AcademiesByNameResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.response.AcademiesByName; 4 | import org.springframework.data.domain.Slice; 5 | 6 | public record AcademiesByNameResults( 7 | Slice academiesByNameResults 8 | ) { 9 | 10 | public static AcademiesByNameResults to(Slice academiesByNames) { 11 | return new AcademiesByNameResults( 12 | academiesByNames.map(AcademiesByNameResult::from)); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/config/PermitAllEndpoint.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.config; 2 | 3 | public class PermitAllEndpoint { 4 | 5 | private PermitAllEndpoint() { 6 | } 7 | 8 | protected static final String[] permitAllArray = new String[]{ 9 | "/", 10 | "/auth/kakao", 11 | "/auth/google", 12 | "/error", 13 | "/docs/**", 14 | "/favicon.ico", 15 | "/swagger-ui/**", 16 | "/swagger-resources/**", 17 | "/v3/api-docs/**", 18 | "/actuator/**", 19 | "/metrics/**" 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/facade/dto/AcademyCalendarDetailFacadeParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.facade.dto; 2 | 3 | import org.guzzing.studayserver.domain.calendar.service.dto.param.AcademyCalendarDetailParam; 4 | 5 | public record AcademyCalendarDetailFacadeParam( 6 | Long lessonId, 7 | Long childId, 8 | Long scheduleId 9 | ) { 10 | 11 | public static AcademyCalendarDetailParam to(AcademyCalendarDetailFacadeParam param) { 12 | return new AcademyCalendarDetailParam( 13 | param.childId(), 14 | param.scheduleId() 15 | ); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/AcademyCalendarDeleteRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request; 2 | 3 | import org.guzzing.studayserver.domain.calendar.service.dto.param.AcademyCalendarDeleteParam; 4 | 5 | public record AcademyCalendarDeleteRequest( 6 | Long academyScheduleId, 7 | Boolean isAllDeleted 8 | ) { 9 | 10 | public static AcademyCalendarDeleteParam to(Long academyScheduleId, boolean isAllDeleted) { 11 | return new AcademyCalendarDeleteParam( 12 | academyScheduleId, 13 | isAllDeleted 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/controller/dto/request/LikePostRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.controller.dto.request; 2 | 3 | import jakarta.validation.Valid; 4 | import jakarta.validation.constraints.NotNull; 5 | import jakarta.validation.constraints.Positive; 6 | import org.guzzing.studayserver.domain.like.service.dto.request.LikePostParam; 7 | 8 | public record LikePostRequest( 9 | @NotNull @Positive Long academyId 10 | ) { 11 | 12 | public static LikePostParam to(@Valid final LikePostRequest request, final Long memberId) { 13 | return new LikePostParam(memberId, request.academyId()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/controller/dto/response/LikeGetResponses.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.like.service.dto.response.LikeGetResult; 5 | import org.guzzing.studayserver.domain.like.service.dto.response.LikedAcademyFeeInfo; 6 | 7 | public record LikeGetResponses( 8 | List likeAcademyInfos, 9 | long totalFee 10 | ) { 11 | 12 | public static LikeGetResponses from(final LikeGetResult result) { 13 | return new LikeGetResponses(result.likeAcademyInfos(), result.totalFee()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademiesByFilterWithScroll.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | import java.util.List; 4 | 5 | public record AcademiesByFilterWithScroll( 6 | List academiesByLocation, 7 | boolean hasNext 8 | ) { 9 | 10 | public static AcademiesByFilterWithScroll of( 11 | List academiesByLocation, 12 | boolean hasNext 13 | ) { 14 | return new AcademiesByFilterWithScroll( 15 | academiesByLocation, 16 | hasNext 17 | ); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/auth/RoleType.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.auth; 2 | 3 | import java.util.Arrays; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | @AllArgsConstructor 9 | public enum RoleType { 10 | 11 | USER("ROLE_USER", "일반 사용자 권한"), 12 | NONE("NONE", "권한 없음"); 13 | 14 | private final String code; 15 | private final String name; 16 | 17 | public static RoleType of(String code) { 18 | return Arrays.stream(RoleType.values()) 19 | .filter(r -> r.getCode().equals(code)) 20 | .findAny() 21 | .orElse(NONE); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/config/JwtTestConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @ConfigurationProperties(prefix = "test") 8 | public class JwtTestConfig { 9 | 10 | public static final String AUTHORIZATION_HEADER = "Authorization"; 11 | public static final String BEARER = "Bearer "; 12 | 13 | private String jwt; 14 | 15 | public String getJwt() { 16 | return BEARER + jwt; 17 | } 18 | 19 | public void setJwt(String jwt) { 20 | this.jwt = jwt; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/controller/MainController.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RequestMapping("/") 10 | @RestController 11 | public class MainController { 12 | 13 | @GetMapping 14 | public ResponseEntity main() { 15 | return ResponseEntity.status(HttpStatus.OK) 16 | .build(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/LessonTime.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Getter; 5 | import org.guzzing.studayserver.domain.calendar.controller.dto.request.validation.ValidLessonTime; 6 | 7 | @Getter 8 | @ValidLessonTime 9 | public class LessonTime { 10 | 11 | private String lessonStartTime; 12 | 13 | private String lessonEndTime; 14 | 15 | @NotBlank 16 | public LessonTime(String lessonStartTime, String lessonEndTime) { 17 | this.lessonStartTime = lessonStartTime; 18 | this.lessonEndTime = lessonEndTime; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/model/vo/Repeatance.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.vo; 2 | 3 | import java.util.Arrays; 4 | import java.util.Objects; 5 | import org.guzzing.studayserver.global.exception.DashboardException; 6 | 7 | public enum Repeatance { 8 | NONE, 9 | WEEKLY, 10 | MONTHLY, 11 | YEARLY; 12 | 13 | public static Repeatance of(final String value) { 14 | return Arrays.stream(Repeatance.values()) 15 | .filter(repeatance -> Objects.equals(repeatance.name(), value)) 16 | .findAny() 17 | .orElseThrow(() -> new DashboardException("설정한 반복 주기와 일치하는 주기가 없습니다.")); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/vo/LessonInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.vo; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.Lesson; 4 | 5 | public record LessonInfo( 6 | long lessonId, 7 | String curriculum, 8 | int capacity, 9 | String duration, 10 | long totalFee 11 | ) { 12 | 13 | public static LessonInfo from(final Lesson entity) { 14 | return new LessonInfo( 15 | entity.getId(), 16 | entity.getCurriculum(), 17 | entity.getCapacity(), 18 | entity.getDuration(), 19 | entity.getTotalFee()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/dto/DashboardPostResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.dto; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | import org.guzzing.studayserver.domain.dashboard.service.vo.ScheduleInfos; 6 | 7 | public record DashboardPostResult( 8 | long dashboardId, 9 | long childId, 10 | long academyId, 11 | long lessonId, 12 | ScheduleInfos scheduleInfos, 13 | PaymentInfo paymentInfo, 14 | SimpleMemo simpleMemo, 15 | boolean isActive, 16 | boolean isDeleted 17 | ) { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/param/AcademyCalendarUpdateParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.param; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | import org.guzzing.studayserver.domain.calendar.model.Periodicity; 6 | 7 | public record AcademyCalendarUpdateParam( 8 | List lessonScheduleParams, 9 | LocalDate startDateOfAttendance, 10 | LocalDate endDateOfAttendance, 11 | boolean isAlarmed, 12 | Long memberId, 13 | Long childId, 14 | Long dashboardId, 15 | String memo, 16 | Periodicity periodicity, 17 | boolean isAllUpdated 18 | ) { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/controller/dto/AuthLoginResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.controller.dto; 2 | 3 | import org.guzzing.studayserver.domain.auth.service.dto.AuthLoginResult; 4 | 5 | public record AuthLoginResponse( 6 | String appToken, 7 | Boolean isNewMember, 8 | Long userId, 9 | String name 10 | ) { 11 | 12 | public static AuthLoginResponse from(AuthLoginResult authLoginResult) { 13 | return new AuthLoginResponse( 14 | authLoginResult.appToken(), 15 | authLoginResult.isNewMember(), 16 | authLoginResult.userId(), 17 | authLoginResult.name() 18 | ); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/dto/response/DashboardResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 4 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 5 | import org.guzzing.studayserver.domain.dashboard.service.vo.ScheduleInfos; 6 | 7 | public record DashboardResult( 8 | long dashboardId, 9 | long childId, 10 | long academyId, 11 | long lessonId, 12 | ScheduleInfos scheduleInfos, 13 | PaymentInfo paymentInfo, 14 | SimpleMemo simpleMemo, 15 | boolean isActive, 16 | boolean isDeleted 17 | ) { 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/util/LatitudeTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.util; 2 | 3 | import org.junit.jupiter.api.DisplayName; 4 | import org.junit.jupiter.params.ParameterizedTest; 5 | import org.junit.jupiter.params.provider.ValueSource; 6 | 7 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 8 | 9 | class LatitudeTest { 10 | 11 | @DisplayName("위도 범위에 범어나면 예외를 던진다.") 12 | @ValueSource(doubles = {32, 100, 44}) 13 | @ParameterizedTest 14 | void createLatitude_outOfBounds_throwException(double latitude) { 15 | assertThatThrownBy( 16 | () -> Longitude.of(latitude)) 17 | .isInstanceOf(IllegalArgumentException.class); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/util/LongitudeTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.util; 2 | 3 | import org.junit.jupiter.api.DisplayName; 4 | import org.junit.jupiter.params.ParameterizedTest; 5 | import org.junit.jupiter.params.provider.ValueSource; 6 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 7 | 8 | class LongitudeTest { 9 | 10 | @DisplayName("경도 범위에 범어나면 예외를 던진다.") 11 | @ValueSource(doubles = {200, 123, 133}) 12 | @ParameterizedTest 13 | void createLongitude_outOfBounds_throwException(double longitude) { 14 | assertThatThrownBy( 15 | () -> Longitude.of(longitude)) 16 | .isInstanceOf(IllegalArgumentException.class); 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/LessonGetResponses.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.service.dto.result.LessonGetResults; 5 | 6 | public record LessonGetResponses( 7 | List lessons 8 | ) { 9 | 10 | public static LessonGetResponses from(LessonGetResults lessonGetResults) { 11 | return new LessonGetResponses( 12 | lessonGetResults 13 | .lessonGetResults() 14 | .stream() 15 | .map(LessonGetResponse::from) 16 | .toList()); 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/LessonGetResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.Lesson; 4 | 5 | public record LessonGetResult( 6 | Long lessonId, 7 | String subject, 8 | Integer capacity, 9 | String duration, 10 | Long totalFee 11 | ) { 12 | 13 | public static LessonGetResult from(Lesson lesson) { 14 | return new LessonGetResult( 15 | lesson.getId(), 16 | lesson.getCurriculum(), 17 | lesson.getCapacity(), 18 | lesson.getDuration(), 19 | lesson.getTotalFee() 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/AcademiesByNameResponses.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.result.AcademiesByNameResults; 4 | import org.springframework.data.domain.Slice; 5 | 6 | public record AcademiesByNameResponses( 7 | Slice academiesByNameResponses 8 | ) { 9 | 10 | public static AcademiesByNameResponses from(AcademiesByNameResults academiesByNameResults) { 11 | return new AcademiesByNameResponses( 12 | academiesByNameResults.academiesByNameResults() 13 | .map(AcademiesByNameResponse::from) 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/review/ReviewCountRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.review; 2 | 3 | import jakarta.persistence.EntityNotFoundException; 4 | import java.util.Optional; 5 | import org.guzzing.studayserver.domain.academy.model.ReviewCount; 6 | 7 | public interface ReviewCountRepository { 8 | 9 | Optional findByAcademyId(Long academyId); 10 | 11 | default ReviewCount getByAcademyId(Long academyId) { 12 | return this.findByAcademyId(academyId) 13 | .orElseThrow(() -> new EntityNotFoundException("해당 학원에 대한 리뷰 카운트가 존재하지 않습니다.")); 14 | } 15 | 16 | ReviewCount save(ReviewCount reviewCount); 17 | 18 | void deleteAll(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/controller/request/ChildCreateRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.controller.request; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Size; 5 | import org.guzzing.studayserver.domain.child.service.param.ChildCreateParam; 6 | 7 | public record ChildCreateRequest( 8 | @NotBlank(message = "아이의 이름은 빈 값일 수 없습니다.") 9 | @Size(min = 1, max = 10, message = "아이 이름의 길이는 1-10자 사이여야 합니다.") 10 | String nickname, 11 | 12 | @NotBlank(message = "아이의 학년은 빈 값일 수 없습니다.") 13 | String grade 14 | ) { 15 | 16 | public ChildCreateParam toParam() { 17 | return new ChildCreateParam(nickname, grade); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyCalendarCreateResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.model.AcademyTimeTemplate; 5 | 6 | public record AcademyCalendarCreateResults( 7 | List academyTimeTemplateIds 8 | ) { 9 | 10 | public static AcademyCalendarCreateResults of(List academyTimeTemplates) { 11 | return new AcademyCalendarCreateResults( 12 | academyTimeTemplates 13 | .stream() 14 | .map(AcademyTimeTemplate::getId) 15 | .toList() 16 | ); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.EntityListeners; 5 | import jakarta.persistence.MappedSuperclass; 6 | import java.time.LocalDate; 7 | import org.springframework.data.annotation.CreatedDate; 8 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 9 | 10 | @MappedSuperclass 11 | @EntityListeners(AuditingEntityListener.class) 12 | public class BaseEntity { 13 | 14 | @CreatedDate 15 | @Column(updatable = false, name = "updated_date") 16 | private LocalDate updatedDate; 17 | 18 | public LocalDate getUpdatedDate() { 19 | return updatedDate; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/model/vo/AddressTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model.vo; 2 | 3 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 4 | 5 | import org.guzzing.studayserver.domain.academy.model.vo.academyinfo.AcademyInfo; 6 | import org.guzzing.studayserver.domain.academy.model.vo.academyinfo.ShuttleAvailability; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class AddressTest { 10 | 11 | @Test 12 | void makeInvalidAddress_throwException() { 13 | //Then 14 | assertThatThrownBy( 15 | () -> AcademyInfo.of("박세영 코딩학원", "123456789", ShuttleAvailability.AVAILABLE.name(), "예능(대)") 16 | ).isInstanceOf(IllegalArgumentException.class); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/Category.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.EnumType; 6 | import jakarta.persistence.Enumerated; 7 | import jakarta.persistence.GeneratedValue; 8 | import jakarta.persistence.GenerationType; 9 | import jakarta.persistence.Id; 10 | import jakarta.persistence.Table; 11 | 12 | 13 | @Table(name = "categories") 14 | @Entity 15 | public class Category { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | Long id; 20 | 21 | @Column(name = "category_name") 22 | @Enumerated(value = EnumType.STRING) 23 | CategoryName categoryName; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/AttendanceDate.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import lombok.Getter; 5 | import org.guzzing.studayserver.domain.calendar.controller.dto.request.validation.ValidAttendanceDate; 6 | 7 | @Getter 8 | @ValidAttendanceDate 9 | public class AttendanceDate { 10 | 11 | private String startDateOfAttendance; 12 | 13 | private String endDateOfAttendance; 14 | 15 | @NotBlank 16 | public AttendanceDate(String startDateOfAttendance, String endDateOfAttendance) { 17 | this.startDateOfAttendance = startDateOfAttendance; 18 | this.endDateOfAttendance = endDateOfAttendance; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/CaffeineCacheType.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CaffeineCacheType { 7 | REFRESH_TOKEN("refreshTokenCache", 30), 8 | LOGOUT_TOKEN("logoutTokenCache", 1), 9 | ACADEMY_BY_LOCATION("academyByLocation", 60); 10 | 11 | private static final int MAXIMUM_CACHE_SIZE = 10000; 12 | 13 | private final String cacheName; 14 | private final int expireAfterWrite; 15 | private final int maximumSize; 16 | 17 | CaffeineCacheType(String cacheName, int expireAfterWrite) { 18 | this.cacheName = cacheName; 19 | this.expireAfterWrite = expireAfterWrite; 20 | this.maximumSize = MAXIMUM_CACHE_SIZE; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/LessonGetResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.result.LessonGetResult; 4 | 5 | public record LessonGetResponse( 6 | Long lessonId, 7 | String subject, 8 | Integer capacity, 9 | String duration, 10 | Long totalFee 11 | ) { 12 | 13 | public static LessonGetResponse from(LessonGetResult lesson) { 14 | return new LessonGetResponse( 15 | lesson.lessonId(), 16 | lesson.subject(), 17 | lesson.capacity(), 18 | lesson.duration(), 19 | lesson.totalFee() 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/client/dto/GoogleUser.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.client.dto; 2 | 3 | import com.fasterxml.jackson.databind.PropertyNamingStrategies; 4 | import com.fasterxml.jackson.databind.annotation.JsonNaming; 5 | import lombok.Getter; 6 | import org.guzzing.studayserver.domain.member.model.vo.NickName; 7 | 8 | @Getter 9 | @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) 10 | public class GoogleUser { 11 | 12 | private String sub; 13 | private String email; 14 | private NickName name; 15 | 16 | public GoogleUser() { 17 | } 18 | 19 | public GoogleUser(String sub, String email, NickName name) { 20 | this.sub = sub; 21 | this.email = email; 22 | this.name = name; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/controller/request/ChildModifyRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.controller.request; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Size; 5 | import org.guzzing.studayserver.domain.child.service.param.ChildModifyParam; 6 | 7 | public record ChildModifyRequest( 8 | @NotBlank(message = "아이의 이름은 빈 값일 수 없습니다.") 9 | @Size(min = 1, max = 10, message = "아이 이름의 길이는 1-10자 사이여야 합니다.") 10 | String nickname, 11 | 12 | @NotBlank(message = "아이의 학년은 빈 값일 수 없습니다.") 13 | String grade 14 | ) { 15 | 16 | public ChildModifyParam toParam(Long memberId, Long childId) { 17 | return new ChildModifyParam(nickname, grade, memberId, childId); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/common/member/MemberIdAnnotationConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.common.member; 2 | 3 | import java.util.List; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | @RequiredArgsConstructor 10 | @Configuration 11 | public class MemberIdAnnotationConfig implements WebMvcConfigurer { 12 | 13 | private final MemberIdResolver memberIdResolver; 14 | 15 | @Override 16 | public void addArgumentResolvers(List resolvers) { 17 | resolvers.add(memberIdResolver); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/validation/ValidCategoryName.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Constraint(validatedBy = ValidCategoryNameValidator.class) 13 | public @interface ValidCategoryName { 14 | 15 | String message() default "유효하지 않은 학원 분야입니다."; 16 | 17 | Class[] groups() default {}; 18 | 19 | Class[] payload() default {}; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/repository/LikeJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.Academy; 5 | import org.guzzing.studayserver.domain.like.model.Like; 6 | import org.guzzing.studayserver.domain.member.model.Member; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | 9 | public interface LikeJpaRepository extends JpaRepository, LikeRepository { 10 | 11 | List findByMember(final Member member); 12 | 13 | long countByMember(final Member member); 14 | 15 | boolean existsByMemberAndAcademy(final Member member, final Academy academy); 16 | 17 | void deleteByMemberAndAcademy(final Member member, final Academy academy); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/repository/DashboardScheduleJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.dashboard.model.DashboardSchedule; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Modifying; 7 | import org.springframework.data.jpa.repository.Query; 8 | 9 | public interface DashboardScheduleJpaRepository extends JpaRepository { 10 | 11 | @Modifying(clearAutomatically = true) 12 | @Query(""" 13 | delete from DashboardSchedule ds 14 | where ds.dashboard.childId in :childIds 15 | """) 16 | void deleteByChildIds(final List childIds); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/ValidDateString.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Constraint(validatedBy = DateStringValidator.class) 13 | public @interface ValidDateString { 14 | 15 | String message() default "잘못된 날짜 형식입니다."; 16 | 17 | Class[] groups() default {}; 18 | 19 | Class[] payload() default {}; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/repository/LikeRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.Academy; 5 | import org.guzzing.studayserver.domain.like.model.Like; 6 | import org.guzzing.studayserver.domain.member.model.Member; 7 | 8 | public interface LikeRepository { 9 | 10 | Like save(final Like like); 11 | 12 | void deleteById(final long likeId); 13 | 14 | boolean existsById(final long id); 15 | 16 | List findByMember(final Member member); 17 | 18 | long countByMember(final Member member); 19 | 20 | boolean existsByMemberAndAcademy(final Member member, final Academy academy); 21 | 22 | void deleteByMemberAndAcademy(final Member member, final Academy academy); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/request/DashboardPostRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.NotNull; 4 | import jakarta.validation.constraints.Positive; 5 | import java.util.List; 6 | import org.guzzing.studayserver.domain.dashboard.controller.vo.Schedule; 7 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 8 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 9 | 10 | public record DashboardPostRequest( 11 | @Positive Long childId, 12 | @Positive Long academyId, 13 | @Positive Long lessonId, 14 | @NotNull List schedules, 15 | @NotNull PaymentInfo paymentInfo, 16 | @NotNull SimpleMemo simpleMemo 17 | ) { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/AcademyCalendarAccessServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service; 2 | 3 | import org.guzzing.studayserver.domain.calendar.service.dto.param.AcademyCalendarDeleteByDashboardParam; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class AcademyCalendarAccessServiceImpl implements AcademyCalendarAccessService { 8 | 9 | private final AcademyCalendarService academyCalendarService; 10 | 11 | public AcademyCalendarAccessServiceImpl(AcademyCalendarService academyCalendarService) { 12 | this.academyCalendarService = academyCalendarService; 13 | } 14 | 15 | public void deleteSchedule(AcademyCalendarDeleteByDashboardParam param) { 16 | academyCalendarService.deleteSchedulesByDashboard(param); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/service/ReviewCommandService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.service; 2 | 3 | import org.guzzing.studayserver.domain.review.model.Review; 4 | import org.guzzing.studayserver.domain.review.repository.ReviewRepository; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | @Service 9 | @Transactional 10 | public class ReviewCommandService { 11 | 12 | private final ReviewRepository reviewRepository; 13 | 14 | public ReviewCommandService( 15 | final ReviewRepository reviewRepository 16 | ) { 17 | this.reviewRepository = reviewRepository; 18 | } 19 | 20 | public Review saveReview(final Review review) { 21 | return reviewRepository.save(review); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/controller/dto/RegionGetNameRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.controller.dto; 2 | 3 | import jakarta.validation.constraints.DecimalMin; 4 | import jakarta.validation.constraints.NotNull; 5 | import org.guzzing.studayserver.domain.region.service.dto.location.RegionGetNameParam; 6 | 7 | public record RegionGetNameRequest( 8 | @NotNull(message = "Latitude cannot be null") 9 | @DecimalMin(value = "-90", message = "Invalid latitude") 10 | double lat, 11 | 12 | @NotNull(message = "Longitude cannot be null") 13 | @DecimalMin(value = "-180", message = "Invalid longitude") 14 | double lng 15 | ) { 16 | public RegionGetNameParam toRegionGetNameParam() { 17 | return new RegionGetNameParam( 18 | lat, 19 | lng 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/facade/dto/AcademiesByLocationFacadeParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.facade.dto; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.param.AcademyByLocationWithCursorParam; 4 | import org.guzzing.studayserver.domain.academy.util.Latitude; 5 | import org.guzzing.studayserver.domain.academy.util.Longitude; 6 | 7 | public record AcademiesByLocationFacadeParam( 8 | Latitude baseLatitude, 9 | Longitude baseLongitude, 10 | Long memberId, 11 | Long lastAcademyId 12 | ) { 13 | 14 | public AcademyByLocationWithCursorParam toAcademyByLocationWithCursorParam() { 15 | return new AcademyByLocationWithCursorParam( 16 | baseLatitude, 17 | baseLongitude, 18 | memberId, 19 | lastAcademyId 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/param/AcademiesByLocationWithScrollParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.param; 2 | 3 | import org.guzzing.studayserver.domain.academy.util.Latitude; 4 | import org.guzzing.studayserver.domain.academy.util.Longitude; 5 | 6 | public record AcademiesByLocationWithScrollParam( 7 | Latitude baseLatitude, 8 | Longitude baseLongitude, 9 | Long memberId, 10 | int pageNumber 11 | ) { 12 | 13 | public static AcademiesByLocationWithScrollParam of( 14 | Latitude baseLatitude, 15 | Longitude baseLongitude, 16 | Long memberId, 17 | int pageNumber) { 18 | return new AcademiesByLocationWithScrollParam( 19 | baseLatitude, 20 | baseLongitude, 21 | memberId, 22 | pageNumber); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/ValidLessonTime.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Documented 12 | @Constraint(validatedBy = LessonTimeValidator.class) 13 | @Target({ElementType.TYPE}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface ValidLessonTime { 16 | 17 | String message() default "수업시작과 끝나는 시간의 형식이 올바르지 않습니다."; 18 | 19 | Class[] groups() default {}; 20 | 21 | Class[] payload() default {}; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar_info/controller/request/CalendarYearMonthMarkRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.controller.request; 2 | 3 | import jakarta.validation.constraints.NotNull; 4 | import org.guzzing.studayserver.domain.calendar_info.service.param.CalendarYearMonthMarkParam; 5 | import org.hibernate.validator.constraints.Range; 6 | 7 | public record CalendarYearMonthMarkRequest( 8 | @Range(min = 2000, max = 2100) 9 | @NotNull 10 | Integer year, 11 | 12 | @Range(min = 1, max = 12) 13 | @NotNull 14 | Integer month 15 | ) { 16 | 17 | 18 | public CalendarYearMonthMarkParam toParam(Long memberId) { 19 | return new CalendarYearMonthMarkParam( 20 | memberId, 21 | year, 22 | month 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/service/result/MemberInformationResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.service.result; 2 | 3 | import java.util.List; 4 | 5 | public record MemberInformationResult( 6 | String nickname, 7 | String email, 8 | List childResults 9 | ) { 10 | 11 | public MemberInformationResult(String nickname, String email, 12 | List childResults) { 13 | this.nickname = nickname; 14 | this.email = email; 15 | this.childResults = List.copyOf(childResults); 16 | } 17 | 18 | public record MemberChildInformationResult( 19 | Long childId, 20 | String childName, 21 | String profileImageUrlPath, 22 | String schedule 23 | ) { 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/jwt/JwtHeaderUtil.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.jwt; 2 | 3 | 4 | import jakarta.servlet.http.HttpServletRequest; 5 | 6 | public class JwtHeaderUtil { 7 | 8 | private static final String HEADER_AUTHORIZATION = "Authorization"; 9 | private static final String TOKEN_PREFIX = "Bearer "; 10 | 11 | private JwtHeaderUtil() { 12 | } 13 | 14 | public static String getAccessToken(HttpServletRequest request) { 15 | 16 | String httpHeaderAuthorizationString = request.getHeader(HEADER_AUTHORIZATION); 17 | 18 | if (httpHeaderAuthorizationString == null || 19 | !httpHeaderAuthorizationString.startsWith(TOKEN_PREFIX)) { 20 | return null; 21 | } 22 | 23 | return httpHeaderAuthorizationString.substring(TOKEN_PREFIX.length()); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/academycategory/AcademyCategoryJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.academycategory; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.AcademyCategory; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | public interface AcademyCategoryJpaRepository extends JpaRepository, AcademyCategoryRepository { 10 | 11 | AcademyCategory save(AcademyCategory academyCategory); 12 | 13 | @Query("select ac.categoryId from AcademyCategory as ac where ac.academy.id =:academyId") 14 | List findCategoryIdsByAcademyId(@Param("academyId") Long academyId); 15 | 16 | void deleteAll(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/AcademiesByNameResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.response.AcademiesByName; 4 | 5 | public record AcademiesByNameResult( 6 | Long academyId, 7 | String academyName, 8 | String address, 9 | Double latitude, 10 | Double longitude 11 | ) { 12 | 13 | public static AcademiesByNameResult from(AcademiesByName academiesByName) { 14 | return new AcademiesByNameResult( 15 | academiesByName.getAcademyId(), 16 | academiesByName.getAcademyName(), 17 | academiesByName.getFullAddress(), 18 | academiesByName.getLatitude(), 19 | academiesByName.getLongitude() 20 | ); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/ValidAttendanceDate.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Documented 12 | @Constraint(validatedBy = AttendanceDateValidator.class) 13 | @Target({ElementType.TYPE}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface ValidAttendanceDate { 16 | 17 | String message() default "마지막 등원일이 시작 등원일 이전이거나 둘 사이의 일정이 3년을 넘어갑니다."; 18 | 19 | Class[] groups() default {}; 20 | 21 | Class[] payload() default {}; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/holiday/service/result/HolidayFindByYearMonthResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.holiday.service.result; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public record HolidayFindByYearMonthResult( 8 | List holidayResults 9 | ) { 10 | 11 | public static HolidayFindByYearMonthResult from(Map> holidayMap) { 12 | List holidayResults = holidayMap.entrySet().stream() 13 | .map(entry -> new HolidayResult(entry.getKey(), entry.getValue())) 14 | .toList(); 15 | 16 | return new HolidayFindByYearMonthResult(holidayResults); 17 | } 18 | 19 | public record HolidayResult( 20 | LocalDate date, 21 | List names 22 | ) { 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/controller/dto/RegionLocationResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.controller.dto; 2 | 3 | import org.guzzing.studayserver.domain.region.service.dto.location.RegionResult; 4 | 5 | public record RegionLocationResponse( 6 | long id, 7 | String sido, 8 | String sigungu, 9 | String upmyeondong, 10 | double latitude, 11 | double longitude 12 | ) { 13 | 14 | public static RegionLocationResponse from(final RegionResult regionResult) { 15 | return new RegionLocationResponse( 16 | regionResult.id(), 17 | regionResult.sido(), 18 | regionResult.sigungu(), 19 | regionResult.upmyeondong(), 20 | regionResult.point().getY(), 21 | regionResult.point().getX()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/service/dto/location/RegionResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.service.dto.location; 2 | 3 | import org.guzzing.studayserver.domain.region.model.Region; 4 | import org.locationtech.jts.geom.MultiPolygon; 5 | import org.locationtech.jts.geom.Point; 6 | 7 | public record RegionResult( 8 | long id, 9 | String sido, 10 | String sigungu, 11 | String upmyeondong, 12 | Point point, 13 | MultiPolygon area 14 | ) { 15 | 16 | public static RegionResult from(final Region region) { 17 | return new RegionResult( 18 | region.getId(), 19 | region.getSido(), 20 | region.getSigungu(), 21 | region.getUpmyeondong(), 22 | region.getPoint(), 23 | region.getArea()); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/repository/academytimetemplate/AcademyTimeTemplateRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.repository.academytimetemplate; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.model.AcademyTimeTemplate; 5 | import org.guzzing.studayserver.domain.calendar.repository.dto.AcademyTimeTemplateDateInfo; 6 | 7 | public interface AcademyTimeTemplateRepository { 8 | 9 | AcademyTimeTemplate save(AcademyTimeTemplate academyTimeTemplate); 10 | 11 | List findAcademyTimeTemplateByDashboardId(Long dashboardId); 12 | 13 | void deleteById(Long academyTimeTemplateId); 14 | 15 | AcademyTimeTemplate getById(Long academyTimeTemplateId); 16 | 17 | List findByChildIdIn(List childIds); 18 | 19 | void deleteAllByChildIds(List childIds); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/GeneratedLessonSchedule.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalDate; 5 | import java.time.LocalTime; 6 | 7 | public record GeneratedLessonSchedule( 8 | LocalDate scheduleDate, 9 | LocalTime lessonStartTime, 10 | LocalTime lessonEndTime, 11 | DayOfWeek dayOfWeek 12 | ) { 13 | 14 | public static GeneratedLessonSchedule of( 15 | LocalDate scheduleDate, 16 | LocalTime lessonStartTime, 17 | LocalTime lessonEndTime, 18 | DayOfWeek dayOfWeek 19 | ) { 20 | return new GeneratedLessonSchedule( 21 | scheduleDate, 22 | lessonStartTime, 23 | lessonEndTime, 24 | dayOfWeek 25 | ); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/param/AcademyByLocationWithCursorParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.param; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.request.AcademyByLocationWithCursorRepositoryRequest; 4 | import org.guzzing.studayserver.domain.academy.util.Latitude; 5 | import org.guzzing.studayserver.domain.academy.util.Longitude; 6 | 7 | public record AcademyByLocationWithCursorParam( 8 | Latitude baseLatitude, 9 | Longitude baseLongitude, 10 | Long memberId, 11 | Long lastAcademyId 12 | ) { 13 | public AcademyByLocationWithCursorRepositoryRequest toAcademyByLocationWithCursorRequest( 14 | String diagonal 15 | ) { 16 | return new AcademyByLocationWithCursorRepositoryRequest( 17 | diagonal, 18 | memberId, 19 | lastAcademyId 20 | ); 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/AcademiesByNameResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.result.AcademiesByNameResult; 4 | 5 | public record AcademiesByNameResponse( 6 | Long academyId, 7 | String academyName, 8 | String address, 9 | Double latitude, 10 | Double longitude 11 | ) { 12 | 13 | public static AcademiesByNameResponse from(AcademiesByNameResult academiesByNameResult) { 14 | return new AcademiesByNameResponse( 15 | academiesByNameResult.academyId(), 16 | academiesByNameResult.academyName(), 17 | academiesByNameResult.address(), 18 | academiesByNameResult.latitude(), 19 | academiesByNameResult.longitude() 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/RepeatPeriod.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalDate; 5 | import org.guzzing.studayserver.domain.calendar.model.Periodicity; 6 | 7 | public record RepeatPeriod( 8 | LocalDate startDateOfAttendance, 9 | LocalDate endDateOfAttendance, 10 | DayOfWeek dayOfWeek, 11 | Periodicity periodicity 12 | ) { 13 | 14 | public static RepeatPeriod of( 15 | LocalDate startDateOfAttendance, 16 | LocalDate endDateOfAttendance, 17 | DayOfWeek dayOfWeek, 18 | Periodicity periodicity 19 | ) { 20 | return new RepeatPeriod( 21 | startDateOfAttendance, 22 | endDateOfAttendance, 23 | dayOfWeek, 24 | periodicity 25 | ); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/vo/ScheduleInfos.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.vo; 2 | 3 | import java.util.List; 4 | 5 | public record ScheduleInfos( 6 | List schedules 7 | ) { 8 | 9 | public ScheduleInfos { 10 | validate(schedules); 11 | } 12 | 13 | private void validate(final List schedules) { 14 | schedules.forEach(scheduleInfo -> this.validateDuplicatedSchedules(scheduleInfo, schedules)); 15 | } 16 | 17 | private void validateDuplicatedSchedules(final ScheduleInfo schedule, final List schedules) { 18 | long count = schedules.stream() 19 | .filter(scheduleInfo -> schedule.dayOfWeek() == scheduleInfo.dayOfWeek()) 20 | .count(); 21 | 22 | if (count > 1) { 23 | throw new IllegalStateException("날짜가 중복됩니다."); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/service/ReviewReadService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.service; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.Academy; 4 | import org.guzzing.studayserver.domain.member.model.Member; 5 | import org.guzzing.studayserver.domain.review.repository.ReviewRepository; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Service 10 | @Transactional(readOnly = true) 11 | public class ReviewReadService { 12 | 13 | private final ReviewRepository reviewRepository; 14 | 15 | public ReviewReadService(final ReviewRepository reviewRepository) { 16 | this.reviewRepository = reviewRepository; 17 | } 18 | 19 | public boolean existsReview(final Member member, final Academy academy) { 20 | return reviewRepository.existsByMemberAndAcademy(member, academy); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/client/ClientStrategyHandler.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.client; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import org.guzzing.studayserver.global.common.auth.OAuth2Provider; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.reactive.function.client.WebClient; 8 | 9 | @Component 10 | public class ClientStrategyHandler { 11 | 12 | private final Map clients = new ConcurrentHashMap<>(); 13 | 14 | public ClientStrategyHandler(WebClient webClient) { 15 | clients.put(OAuth2Provider.GOOGLE.name(), new ClientGoogleStrategy(webClient)); 16 | clients.put(OAuth2Provider.KAKAO.name(), new ClientKakaoStrategy(webClient)); 17 | } 18 | 19 | public ClientStrategy getClientStrategy(String clientName) { 20 | return clients.get(clientName); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/schedule/ChildIncreaseGradeSchedule.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.schedule; 2 | 3 | import org.guzzing.studayserver.domain.child.model.Child; 4 | import org.guzzing.studayserver.domain.child.repository.ChildRepository; 5 | import org.springframework.scheduling.annotation.Scheduled; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | @Component 10 | public class ChildIncreaseGradeSchedule { 11 | 12 | private final ChildRepository childRepository; 13 | 14 | public ChildIncreaseGradeSchedule(ChildRepository childRepository) { 15 | this.childRepository = childRepository; 16 | } 17 | 18 | @Transactional 19 | @Scheduled(cron = "0 0 0 1 1 *") 20 | public void increaseGrade() { 21 | childRepository.findAll() 22 | .forEach(Child::increaseGrade); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/AcademyAccessService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service; 2 | 3 | 4 | import org.guzzing.studayserver.domain.academy.service.dto.result.AcademyAndLessonDetailResult; 5 | import org.guzzing.studayserver.domain.academy.service.dto.result.AcademyFeeInfo; 6 | import org.guzzing.studayserver.domain.dashboard.facade.vo.AcademyInfo; 7 | import org.guzzing.studayserver.domain.dashboard.facade.vo.LessonInfo; 8 | 9 | 10 | public interface AcademyAccessService { 11 | 12 | AcademyFeeInfo findAcademyFeeInfo(final Long academyId); 13 | 14 | void validateAcademy(final Long academyId); 15 | 16 | void validateLesson(final Long academyId, final Long lessonId); 17 | 18 | AcademyInfo findAcademyInfo(final Long academyId); 19 | 20 | LessonInfo findLessonInfo(final Long lessonId); 21 | 22 | AcademyAndLessonDetailResult getAcademyAndLessonDetail(final Long lessonId); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/ValidEnum.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.Constraint; 4 | import jakarta.validation.Payload; 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Documented 12 | @Constraint(validatedBy = ValidEnumValidator.class) 13 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface ValidEnum { 16 | 17 | String message() default "올바르지 않은 반복 주기 값입니다."; 18 | 19 | Class[] groups() default {}; 20 | 21 | Class[] payload() default {}; 22 | 23 | Class> enumClass(); 24 | 25 | boolean ignoreCase() default false; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/dto/DashboardGetResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.dto; 2 | 3 | import org.guzzing.studayserver.domain.dashboard.facade.vo.AcademyInfo; 4 | import org.guzzing.studayserver.domain.dashboard.facade.vo.ChildInfo; 5 | import org.guzzing.studayserver.domain.dashboard.facade.vo.LessonInfo; 6 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 7 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 8 | import org.guzzing.studayserver.domain.dashboard.service.vo.ScheduleInfos; 9 | 10 | public record DashboardGetResult( 11 | long dashboardId, 12 | ChildInfo childInfo, 13 | AcademyInfo academyInfo, 14 | LessonInfo lessonInfo, 15 | ScheduleInfos scheduleInfos, 16 | PaymentInfo paymentInfo, 17 | SimpleMemo simpleMemo, 18 | boolean isActive, 19 | boolean isDeleted 20 | ) { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/model/vo/academyinfo/AcademyInfoAboutScheduleDetailTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model.vo.academyinfo; 2 | 3 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class AcademyInfoAboutScheduleDetailTest { 8 | 9 | @Test 10 | void makeInvalidNameAcademyInfo_throwException() { 11 | //Then 12 | assertThatThrownBy( 13 | () -> AcademyInfo.of("", "000-0000-0000", ShuttleAvailability.AVAILABLE.name(), "예능(대)") 14 | ).isInstanceOf(IllegalArgumentException.class); 15 | } 16 | 17 | @Test 18 | void makeInvalidPhoneNumberAcademyInfo_throwException() { 19 | //Then 20 | assertThatThrownBy( 21 | () -> AcademyInfo.of("박세영 코딩학원", "123445667", ShuttleAvailability.AVAILABLE.name(), "예능(대)") 22 | ).isInstanceOf(IllegalArgumentException.class); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/model/ProfileImageUri.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.model; 2 | 3 | import static lombok.AccessLevel.PROTECTED; 4 | 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Embeddable; 7 | import jakarta.persistence.Transient; 8 | import java.text.MessageFormat; 9 | import lombok.Getter; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Getter 13 | @NoArgsConstructor(access = PROTECTED) 14 | @Embeddable 15 | public class ProfileImageUri { 16 | 17 | @Transient 18 | private static final String URL_PATH = "https://team09-resources-bucket.s3.ap-northeast-1.amazonaws.com/"; 19 | 20 | @Column(name = "image_uri", nullable = false) 21 | private String imageUri; 22 | 23 | public ProfileImageUri(final String imageUri) { 24 | this.imageUri = imageUri; 25 | } 26 | 27 | public String getImageUrl() { 28 | return MessageFormat.format("{0}{1}", URL_PATH, imageUri); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/dto/response/DashboardGetResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.dashboard.controller.vo.Schedule; 5 | import org.guzzing.studayserver.domain.dashboard.facade.vo.AcademyInfo; 6 | import org.guzzing.studayserver.domain.dashboard.facade.vo.ChildInfo; 7 | import org.guzzing.studayserver.domain.dashboard.facade.vo.LessonInfo; 8 | import org.guzzing.studayserver.domain.dashboard.model.dto.PaymentInfo; 9 | import org.guzzing.studayserver.domain.dashboard.model.vo.SimpleMemo; 10 | 11 | public record DashboardGetResponse( 12 | Long dashboardId, 13 | ChildInfo childInfo, 14 | AcademyInfo academyInfo, 15 | LessonInfo lessonInfo, 16 | List schedules, 17 | PaymentInfo paymentInfo, 18 | SimpleMemo simpleMemo, 19 | boolean isActive, 20 | boolean isDeleted 21 | ) { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/ReviewPercentGetResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.service.dto.result.ReviewPercentGetResult; 4 | 5 | public record ReviewPercentGetResponse( 6 | int kindnessPercent, 7 | int goodFacilityPercent, 8 | int cheapFeePercent, 9 | int goodManagementPercent, 10 | int lovelyTeachingPercent, 11 | int shuttleAvailabilityCount 12 | ) { 13 | 14 | public static ReviewPercentGetResponse from(ReviewPercentGetResult response) { 15 | return new ReviewPercentGetResponse( 16 | response.kindnessPercent(), 17 | response.goodFacilityPercent(), 18 | response.cheapFeePercent(), 19 | response.goodManagementPercent(), 20 | response.lovelyTeachingPercent(), 21 | response.shuttleAvailabilityCount() 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/listener/WithdrawProfileImageListener.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.listener; 2 | 3 | import org.guzzing.studayserver.domain.member.event.WithdrawEvent; 4 | import org.guzzing.studayserver.global.common.profile.ProfileImageService; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.transaction.event.TransactionalEventListener; 8 | 9 | @Component 10 | public class WithdrawProfileImageListener { 11 | 12 | private final ProfileImageService profileImageService; 13 | 14 | public WithdrawProfileImageListener(ProfileImageService profileImageService) { 15 | this.profileImageService = profileImageService; 16 | } 17 | 18 | @Async 19 | @TransactionalEventListener 20 | public void withdrawProfileImage(WithdrawEvent event) { 21 | event.getChildProfileImageUris() 22 | .forEach(profileImageService::deleteProfileImage); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyCalendarLoadToUpdateResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.time.LocalDate; 4 | import org.guzzing.studayserver.domain.calendar.model.AcademyTimeTemplate; 5 | 6 | public record AcademyCalendarLoadToUpdateResult( 7 | Long dashboardId, 8 | LocalDate startDateOfAttendance, 9 | LocalDate endDateOfAttendance, 10 | boolean isAlarmed, 11 | String memo 12 | ) { 13 | 14 | public static AcademyCalendarLoadToUpdateResult of( 15 | AcademyTimeTemplate academyTimeTemplate 16 | ) { 17 | return new AcademyCalendarLoadToUpdateResult( 18 | academyTimeTemplate.getDashboardId(), 19 | academyTimeTemplate.getStartDateOfAttendance(), 20 | academyTimeTemplate.getEndDateOfAttendance(), 21 | academyTimeTemplate.isAlarmed(), 22 | academyTimeTemplate.getMemo() 23 | ); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/repository/DashboardJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.repository; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.dashboard.model.Dashboard; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Modifying; 7 | import org.springframework.data.jpa.repository.Query; 8 | 9 | public interface DashboardJpaRepository extends 10 | JpaRepository, DashboardRepository, DashboardQuerydslRepository { 11 | 12 | @Query("SELECT dab FROM Dashboard AS dab " 13 | + "JOIN FETCH dab.dashboardSchedules dabschs " 14 | + "WHERE dab.id IN :dashboardIds") 15 | List findByIds(List dashboardIds); 16 | 17 | @Modifying(clearAutomatically = true) 18 | @Query(""" 19 | delete from Dashboard d 20 | where d.childId in :childIds 21 | """) 22 | void deleteByChildIds(List childIds); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/model/vo/Email.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.model.vo; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Embeddable; 5 | import lombok.AccessLevel; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Getter 10 | @Embeddable 11 | @NoArgsConstructor(access = AccessLevel.PROTECTED) 12 | public class Email { 13 | 14 | private static final String REGEX = "^[a-zA-Z0-9._%+-]+@([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,}$"; 15 | 16 | @Column(name = "email") 17 | private String value; 18 | 19 | public Email(String value) { 20 | validateValue(value); 21 | this.value = value; 22 | } 23 | 24 | private void validateValue(String value) { 25 | if (value == null || value.isBlank()) { 26 | throw new IllegalArgumentException("이메일은 빈 값일 수 없습니다."); 27 | } 28 | if (!value.matches(REGEX)) { 29 | throw new IllegalArgumentException("이메일 형식이 올바르지 않습니다."); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/like/service/dto/response/LikeGetResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.like.service.dto.response; 2 | 3 | import java.util.List; 4 | 5 | public record LikeGetResult( 6 | List likeAcademyInfos, 7 | long totalFee 8 | ) { 9 | 10 | private static final long DEFAULT_TOTAL_FEE = 0L; 11 | 12 | public static LikeGetResult of(final List likedAcademyFeeInfos) { 13 | return new LikeGetResult(likedAcademyFeeInfos, getTotalFee(likedAcademyFeeInfos)); 14 | } 15 | 16 | private static long getTotalFee(final List likeAcademyFeeInfos) { 17 | try { 18 | return likeAcademyFeeInfos.stream() 19 | .filter(likedAcademyFeeInfo -> likedAcademyFeeInfo.expectedFee() != null) 20 | .mapToLong(LikedAcademyFeeInfo::expectedFee) 21 | .sum(); 22 | } catch (NullPointerException e) { 23 | return DEFAULT_TOTAL_FEE; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/AcademyWithLikeByLocation.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.response.AcademyByLocationWithLikeRepositoryResponse; 4 | 5 | public record AcademyWithLikeByLocation( 6 | long academyId, 7 | String academyName, 8 | String fullAddress, 9 | String phoneNumber, 10 | double latitude, 11 | double longitude, 12 | String shuttleAvailable, 13 | boolean isLiked 14 | ) { 15 | public static AcademyWithLikeByLocation of(AcademyByLocationWithLikeRepositoryResponse response) { 16 | return new AcademyWithLikeByLocation( 17 | response.getAcademyId(), 18 | response.getAcademyName(), 19 | response.getFullAddress(), 20 | response.getPhoneNumber(), 21 | response.getLatitude(), 22 | response.getLongitude(), 23 | response.getShuttleAvailable(), 24 | response.isLiked() 25 | ); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/dto/result/AcademyCalendarDetailResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.dto.result; 2 | 3 | import java.time.LocalDate; 4 | import java.time.LocalTime; 5 | import org.guzzing.studayserver.domain.calendar.repository.dto.AcademyCalenderDetailInfo; 6 | 7 | public record AcademyCalendarDetailResult( 8 | Long dashboardId, 9 | LocalTime lessonStartTime, 10 | LocalTime lessonEndTime, 11 | String memo, 12 | LocalDate requestedDate 13 | ) { 14 | 15 | public static AcademyCalendarDetailResult from( 16 | AcademyCalenderDetailInfo academyCalenderDetailInfo, 17 | LocalDate requestedDate) { 18 | return new AcademyCalendarDetailResult( 19 | academyCalenderDetailInfo.getDashboardId(), 20 | academyCalenderDetailInfo.getLessonStartTime(), 21 | academyCalenderDetailInfo.getLessonEndTime(), 22 | academyCalenderDetailInfo.getMemo(), 23 | requestedDate 24 | ); 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/repository/DashboardQuerydslRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.repository; 2 | 3 | import static org.guzzing.studayserver.domain.dashboard.model.QDashboard.dashboard; 4 | 5 | import com.querydsl.jpa.impl.JPAQueryFactory; 6 | import java.util.List; 7 | import org.guzzing.studayserver.domain.dashboard.model.Dashboard; 8 | import org.springframework.stereotype.Repository; 9 | 10 | @Repository 11 | public class DashboardQuerydslRepositoryImpl implements 12 | DashboardQuerydslRepository { 13 | 14 | private final JPAQueryFactory jpaQueryFactory; 15 | 16 | public DashboardQuerydslRepositoryImpl(final JPAQueryFactory jpaQueryFactory) { 17 | this.jpaQueryFactory = jpaQueryFactory; 18 | } 19 | 20 | @Override 21 | public List findActiveOnlyByChildId(Long childId) { 22 | return jpaQueryFactory.selectFrom(dashboard) 23 | .where(dashboard.childId.eq(childId) 24 | .and(dashboard.isActive.isTrue())) 25 | .fetch(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/controller/vo/Schedule.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.controller.vo; 2 | 3 | import jakarta.validation.constraints.NotNull; 4 | import jakarta.validation.constraints.Positive; 5 | import java.time.LocalTime; 6 | import org.guzzing.studayserver.global.common.time.TimeConverter; 7 | import org.guzzing.studayserver.global.exception.DashboardException; 8 | 9 | public record Schedule( 10 | @Positive Integer dayOfWeek, 11 | @NotNull String startTime, 12 | @NotNull String endTime 13 | ) { 14 | 15 | public Schedule { 16 | validateTimeSuitability(startTime, endTime); 17 | } 18 | 19 | private void validateTimeSuitability( 20 | final String startTime, 21 | final String endTime 22 | ) { 23 | final LocalTime start = TimeConverter.getLocalTime(startTime); 24 | final LocalTime end = TimeConverter.getLocalTime(endTime); 25 | 26 | if (start.isAfter(end)) { 27 | throw new DashboardException("시작 시간이 종료 시간 보다 늦습니다."); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/review/controller/dto/request/ReviewPostRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.review.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.Positive; 4 | import org.guzzing.studayserver.domain.review.service.dto.request.ReviewPostParam; 5 | 6 | public record ReviewPostRequest( 7 | @Positive Long academyId, 8 | boolean kindness, 9 | boolean cheapFee, 10 | boolean goodFacility, 11 | boolean goodManagement, 12 | boolean lovelyTeaching, 13 | boolean shuttleAvailability 14 | ) { 15 | 16 | public static ReviewPostParam to(final Long memberId, final ReviewPostRequest request) { 17 | return new ReviewPostParam( 18 | memberId, 19 | request.academyId(), 20 | request.kindness(), 21 | request.cheapFee(), 22 | request.goodFacility(), 23 | request.goodManagement(), 24 | request.lovelyTeaching(), 25 | request.shuttleAvailability() 26 | ); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/model/ChildNickname.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.model; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Embeddable; 5 | import lombok.AccessLevel; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Embeddable 9 | @NoArgsConstructor(access = AccessLevel.PROTECTED) 10 | public class ChildNickname { 11 | 12 | public static final int NAME_MAX_LENGTH = 200; 13 | 14 | @Column(name = "nickname", nullable = false) 15 | private String value; 16 | 17 | public ChildNickname(String value) { 18 | validateName(value); 19 | this.value = value; 20 | } 21 | 22 | private void validateName(String name) { 23 | if (name == null || name.isBlank()) { 24 | throw new IllegalArgumentException("닉네임은 빈 값일 수 없습니다."); 25 | } 26 | if (NAME_MAX_LENGTH < name.length()) { 27 | throw new IllegalArgumentException(String.format("닉네임은 %d 글자를 넘을 수 없습니다.", NAME_MAX_LENGTH)); 28 | } 29 | } 30 | 31 | public String getValue() { 32 | return value; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/AcademyCalendarDetailRequestTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request; 2 | 3 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 4 | 5 | import org.junit.jupiter.api.DisplayName; 6 | import org.junit.jupiter.api.Test; 7 | 8 | class AcademyCalendarDetailRequestTest { 9 | 10 | @Test 11 | @DisplayName("아이디가 음수인 경우 예외를 던진다.") 12 | void construct_invalidLessonId_throwException() { 13 | assertThatThrownBy( 14 | () -> new AcademyCalendarDetailRequest( 15 | -1L, 16 | 1L) 17 | ).isInstanceOf(IllegalArgumentException.class); 18 | } 19 | 20 | @Test 21 | @DisplayName("아이 아이디가 음수 경우 예외를 던진다.") 22 | void construct_invalidChildrenID_throwException() { 23 | assertThatThrownBy( 24 | () -> new AcademyCalendarDetailRequest( 25 | 1L, 26 | -1L 27 | ) 28 | ).isInstanceOf(IllegalArgumentException.class); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar_info/service/result/CalendarFindSchedulesByDateIncompleteResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.service.result; 2 | 3 | import java.time.LocalTime; 4 | import org.guzzing.studayserver.domain.dashboard.service.dto.response.DashBoardFindByIdsResults.DashBoardFindByIdsResult; 5 | 6 | public record CalendarFindSchedulesByDateIncompleteResult( 7 | Long childId, 8 | String childImageUrl, 9 | Long academyScheduleId, 10 | LocalTime startTime, 11 | LocalTime endTime, 12 | Long lessonId 13 | ) { 14 | 15 | public static CalendarFindSchedulesByDateIncompleteResult of( 16 | ChildAcademyScheduleCombineResult schedule, DashBoardFindByIdsResult dashboard) { 17 | return new CalendarFindSchedulesByDateIncompleteResult( 18 | schedule.childId(), 19 | schedule.childImageUrl(), 20 | schedule.academyScheduleId(), 21 | schedule.startTime(), 22 | schedule.endTime(), 23 | dashboard.lessonId() 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/AcademyWithNotLikeByLocation.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.response.AcademyByLocationWithLikeRepositoryResponse; 4 | import org.guzzing.studayserver.domain.academy.repository.dto.response.AcademyByLocationWithNotLikeRepositoryResponse; 5 | 6 | public record AcademyWithNotLikeByLocation ( 7 | long academyId, 8 | String academyName, 9 | String fullAddress, 10 | String phoneNumber, 11 | double latitude, 12 | double longitude, 13 | String shuttleAvailable 14 | ) { 15 | public static AcademyWithNotLikeByLocation of(AcademyByLocationWithNotLikeRepositoryResponse response) { 16 | return new AcademyWithNotLikeByLocation( 17 | response.getAcademyId(), 18 | response.getAcademyName(), 19 | response.getFullAddress(), 20 | response.getPhoneNumber(), 21 | response.getLatitude(), 22 | response.getLongitude(), 23 | response.getShuttleAvailable() 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/AcademyAndLessonDetailResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.Lesson; 5 | import org.guzzing.studayserver.domain.academy.util.CategoryInfo; 6 | 7 | public record AcademyAndLessonDetailResult( 8 | String academyName, 9 | String address, 10 | String lessonName, 11 | Integer capacity, 12 | Long totalFee, 13 | List categories 14 | ) { 15 | 16 | public static AcademyAndLessonDetailResult from(Lesson lesson, List categoryIds) { 17 | return new AcademyAndLessonDetailResult( 18 | lesson.getAcademy().getAcademyName(), 19 | lesson.getAcademy().getFullAddress(), 20 | lesson.getCurriculum(), 21 | lesson.getCapacity(), 22 | lesson.getTotalFee(), 23 | categoryIds.stream() 24 | .map(CategoryInfo::getCategoryNameById) 25 | .toList() 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/ReviewPercentGetResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import org.guzzing.studayserver.domain.academy.model.ReviewCount; 4 | 5 | public record ReviewPercentGetResult( 6 | int kindnessPercent, 7 | int goodFacilityPercent, 8 | int cheapFeePercent, 9 | int goodManagementPercent, 10 | int lovelyTeachingPercent, 11 | int shuttleAvailabilityCount 12 | ) { 13 | 14 | public static ReviewPercentGetResult from(ReviewCount reviewCount) { 15 | return new ReviewPercentGetResult( 16 | reviewCount.makePercent(reviewCount.getKindnessCount()), 17 | reviewCount.makePercent(reviewCount.getGoodFacilityCount()), 18 | reviewCount.makePercent(reviewCount.getCheapFeeCount()), 19 | reviewCount.makePercent(reviewCount.getGoodManagementCount()), 20 | reviewCount.makePercent(reviewCount.getLovelyTeachingCount()), 21 | reviewCount.makePercent(reviewCount.getShuttleAvailabilityCount()) 22 | ); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/repository/JwtCacheRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.repository; 2 | 3 | import java.util.Optional; 4 | import org.guzzing.studayserver.global.config.CaffeineCacheType; 5 | import org.springframework.cache.Cache; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public class JwtCacheRepository { 11 | 12 | private final Cache cache; 13 | 14 | public JwtCacheRepository(CacheManager cacheManager) { 15 | this.cache = cacheManager.getCache(CaffeineCacheType.REFRESH_TOKEN.getCacheName()); 16 | } 17 | 18 | public String save(String accessToken, String refreshToken) { 19 | cache.put(accessToken, refreshToken); 20 | return refreshToken; 21 | } 22 | 23 | public Optional findRefreshToken(String accessToken) { 24 | String refreshToken = cache.get(accessToken, String.class); 25 | return Optional.ofNullable(refreshToken); 26 | } 27 | 28 | public void delete(String accessToken) { 29 | cache.evictIfPresent(accessToken); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/holiday/model/Holiday.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.holiday.model; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.GeneratedValue; 6 | import jakarta.persistence.GenerationType; 7 | import jakarta.persistence.Id; 8 | import jakarta.persistence.Table; 9 | import java.time.LocalDate; 10 | import lombok.AccessLevel; 11 | import lombok.NoArgsConstructor; 12 | 13 | @Entity 14 | @Table(name = "holidays") 15 | @NoArgsConstructor(access = AccessLevel.PROTECTED) 16 | public class Holiday { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | @Column(name = "date_name", nullable = false) 23 | private String dateName; 24 | 25 | @Column(name = "date", nullable = false) 26 | private LocalDate date; 27 | 28 | public Holiday(LocalDate date, String dateName) { 29 | this.dateName = dateName; 30 | this.date = date; 31 | } 32 | 33 | public String getDateName() { 34 | return dateName; 35 | } 36 | 37 | public LocalDate getDate() { 38 | return date; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/param/AcademyByLocationParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.param; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.request.AcademyByLocationWithCursorRepositoryRequest; 4 | import org.guzzing.studayserver.domain.academy.util.Latitude; 5 | import org.guzzing.studayserver.domain.academy.util.Longitude; 6 | import org.guzzing.studayserver.domain.academy.util.SqlFormatter; 7 | 8 | public record AcademyByLocationParam( 9 | Latitude northEastLatitude, 10 | Longitude northEastLongitude, 11 | Latitude southWestbaseLatitude, 12 | Longitude southWestLongitude, 13 | Long memberId, 14 | Long lastAcademyId 15 | ) { 16 | public AcademyByLocationWithCursorRepositoryRequest toAcademyByLocationWithCursorRequest( 17 | ) { 18 | return new AcademyByLocationWithCursorRepositoryRequest( 19 | SqlFormatter.makeDiagonalByLineString( 20 | northEastLatitude, 21 | northEastLongitude, 22 | southWestbaseLatitude, 23 | southWestLongitude 24 | ), 25 | memberId, 26 | lastAcademyId 27 | ); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/lesson/LessonRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.lesson; 2 | 3 | import jakarta.persistence.EntityNotFoundException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import org.guzzing.studayserver.domain.academy.model.Lesson; 7 | import org.guzzing.studayserver.domain.academy.repository.dto.LessonInfoToCreateDashboard; 8 | import org.guzzing.studayserver.global.error.response.ErrorCode; 9 | 10 | 11 | public interface LessonRepository { 12 | 13 | List findAllByAcademyId(Long academyId); 14 | 15 | List findAllLessonInfoByAcademyId(Long academyId); 16 | 17 | Lesson save(Lesson lesson); 18 | 19 | void deleteAll(); 20 | 21 | boolean existsById(final Long lessonId); 22 | 23 | Optional findById(final Long lessonId); 24 | 25 | Optional findLessonById(Long lessonId); 26 | 27 | default Lesson getLessonById(Long lessonId) { 28 | return findLessonById(lessonId).orElseThrow(() -> 29 | new EntityNotFoundException(ErrorCode.NOT_FOUND_ENTITY.getMessage())); 30 | } 31 | 32 | List findByIds(List lessonIds); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/ChildWithScheduleResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service; 2 | 3 | import java.time.LocalDate; 4 | import java.time.LocalTime; 5 | import org.guzzing.studayserver.domain.child.service.result.ChildrenFindResult.ChildFindResult; 6 | 7 | public record ChildWithScheduleResult( 8 | Long childId, 9 | String profileImageUrl, 10 | String nickname, 11 | String grade, 12 | LocalDate schedule_date, 13 | LocalTime lessonStartTime, 14 | LocalTime lessonEndTime, 15 | String academyName, 16 | String lessonSubject 17 | ) { 18 | 19 | public static ChildWithScheduleResult of(ChildFindResult childInfo, ChildDateScheduleResult schedule) { 20 | return new ChildWithScheduleResult( 21 | childInfo.childId(), 22 | childInfo.profileImageUrl(), 23 | childInfo.nickname(), 24 | childInfo.grade(), 25 | schedule.schedule_date(), 26 | schedule.lessonStartTime(), 27 | schedule.lessonEndTime(), 28 | schedule.academyName(), 29 | schedule.lessonSubject() 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/AcademyCalendarDetailRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request; 2 | 3 | import org.guzzing.studayserver.domain.calendar.facade.dto.AcademyCalendarDetailFacadeParam; 4 | 5 | public record AcademyCalendarDetailRequest( 6 | Long lessonId, 7 | Long childId 8 | ) { 9 | 10 | public AcademyCalendarDetailRequest { 11 | isValidId(lessonId); 12 | isValidId(childId); 13 | } 14 | 15 | public static AcademyCalendarDetailFacadeParam to( 16 | Long scheduleId, 17 | AcademyCalendarDetailRequest academyCalendarDetailRequest 18 | ) { 19 | return new AcademyCalendarDetailFacadeParam( 20 | academyCalendarDetailRequest.lessonId(), 21 | academyCalendarDetailRequest.childId(), 22 | scheduleId 23 | ); 24 | } 25 | 26 | private static void isValidId(Long lessonId) { 27 | if (lessonId == null) { 28 | throw new IllegalArgumentException("id는 null일 수 없습니다."); 29 | } 30 | if (lessonId < 0) { 31 | throw new IllegalArgumentException("id는 음수일 수 없습니다."); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar_info/service/result/ChildAcademyScheduleCombineResult.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.service.result; 2 | 3 | import java.time.LocalTime; 4 | import org.guzzing.studayserver.domain.calendar.service.dto.result.AcademyScheduleFindByDateResults.AcademyScheduleFindByDateResult; 5 | import org.guzzing.studayserver.domain.member.service.result.MemberInformationResult.MemberChildInformationResult; 6 | 7 | public record ChildAcademyScheduleCombineResult( 8 | Long childId, 9 | String childImageUrl, 10 | Long academyScheduleId, 11 | LocalTime startTime, 12 | LocalTime endTime, 13 | Long dashboardId 14 | ) { 15 | 16 | public static ChildAcademyScheduleCombineResult of(MemberChildInformationResult child, 17 | AcademyScheduleFindByDateResult academySchedule) { 18 | return new ChildAcademyScheduleCombineResult( 19 | child.childId(), 20 | child.profileImageUrlPath(), 21 | academySchedule.academyScheduleId(), 22 | academySchedule.startTime(), 23 | academySchedule.endTime(), 24 | academySchedule.dashboardId() 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/vo/ScheduleInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service.vo; 2 | 3 | import static org.guzzing.studayserver.domain.dashboard.model.vo.Repeatance.NONE; 4 | import static org.guzzing.studayserver.domain.dashboard.model.vo.Repeatance.WEEKLY; 5 | 6 | import java.time.DayOfWeek; 7 | import org.guzzing.studayserver.domain.dashboard.model.vo.Repeatance; 8 | import org.guzzing.studayserver.global.exception.DashboardException; 9 | 10 | public record ScheduleInfo( 11 | DayOfWeek dayOfWeek, 12 | String startTime, 13 | String endTime, 14 | Repeatance repeatance 15 | ) { 16 | 17 | public ScheduleInfo { 18 | validateRepeatanceDayOfWeek(repeatance, dayOfWeek); 19 | } 20 | 21 | private void validateRepeatanceDayOfWeek( 22 | final Repeatance repeatance, 23 | final DayOfWeek dayOfWeek 24 | ) { 25 | if (dayOfWeek != null && !isWeeklyRepeatance(repeatance)) { 26 | throw new DashboardException("요일 설정을 할 수 없는 반복 타입입니다."); 27 | } 28 | } 29 | 30 | private boolean isWeeklyRepeatance(Repeatance repeatance) { 31 | return repeatance == WEEKLY || repeatance == NONE; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/dashboard/model/vo/RepeatanceTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.vo; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 5 | 6 | import org.guzzing.studayserver.global.exception.DashboardException; 7 | import org.junit.jupiter.api.DisplayName; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class RepeatanceTest { 11 | 12 | @Test 13 | @DisplayName("반복 주기에 대한 문자열로 반복 enum을 구한다.") 14 | void of_ValidRepeatanceValue_ReturnRepeatance() { 15 | // Given 16 | final String value = "NONE"; 17 | 18 | // When 19 | final Repeatance result = Repeatance.of(value); 20 | 21 | // Then 22 | assertThat(result).isEqualTo(Repeatance.NONE); 23 | } 24 | 25 | @Test 26 | @DisplayName("반복 주기가 아닌 문자열로 반복 enum을 구할 수 없다.") 27 | void of_InvalidRepeatanceValue_ThrowException() { 28 | // Given 29 | final String value = "가나다"; 30 | 31 | // When & Then 32 | assertThatThrownBy(() -> Repeatance.of(value)) 33 | .isInstanceOf(DashboardException.class) 34 | .hasMessage("설정한 반복 주기와 일치하는 주기가 없습니다."); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/request/AcademyByLocationWithScrollRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.request; 2 | 3 | import jakarta.validation.constraints.DecimalMin; 4 | import jakarta.validation.constraints.NotNull; 5 | import jakarta.validation.constraints.PositiveOrZero; 6 | import org.guzzing.studayserver.domain.academy.service.dto.param.AcademiesByLocationWithScrollParam; 7 | import org.guzzing.studayserver.domain.academy.util.Latitude; 8 | import org.guzzing.studayserver.domain.academy.util.Longitude; 9 | 10 | public record AcademyByLocationWithScrollRequest( 11 | @NotNull(message = "Latitude cannot be null") 12 | @DecimalMin(value = "-90", message = "Invalid latitude") 13 | Double lat, 14 | 15 | @NotNull(message = "Longitude cannot be null") 16 | @DecimalMin(value = "-180", message = "Invalid longitude") 17 | Double lng, 18 | 19 | @PositiveOrZero 20 | int pageNumber 21 | ) { 22 | 23 | public AcademiesByLocationWithScrollParam to(Long memberId) { 24 | return new AcademiesByLocationWithScrollParam( 25 | Latitude.of(lat), 26 | Longitude.of(lng), 27 | memberId, 28 | pageNumber 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/facade/vo/AcademyInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.facade.vo; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | import org.guzzing.studayserver.domain.academy.model.Academy; 6 | import org.guzzing.studayserver.domain.academy.util.CategoryInfo; 7 | 8 | public record AcademyInfo( 9 | long academyId, 10 | String academyName, 11 | String contact, 12 | String fullAddress, 13 | String shuttleAvailability, 14 | long expectedFee, 15 | LocalDate updatedDate, 16 | List categories 17 | ) { 18 | 19 | public static AcademyInfo from(final Academy entity, final List categoryIds) { 20 | final List categories = categoryIds.stream() 21 | .map(CategoryInfo::getCategoryNameById) 22 | .toList(); 23 | 24 | return new AcademyInfo( 25 | entity.getId(), 26 | entity.getAcademyName(), 27 | entity.getContact(), 28 | entity.getFullAddress(), 29 | entity.getShuttleAvailability(), 30 | entity.getMaxEducationFee(), 31 | entity.getUpdatedDate(), 32 | categories); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/ValidEnumValidator.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.ConstraintValidator; 4 | import jakarta.validation.ConstraintValidatorContext; 5 | 6 | public class ValidEnumValidator implements ConstraintValidator { 7 | 8 | private Class> enumClass; 9 | private boolean ignoreCase; 10 | 11 | @Override 12 | public void initialize(ValidEnum constraintAnnotation) { 13 | this.enumClass = constraintAnnotation.enumClass(); 14 | this.ignoreCase = constraintAnnotation.ignoreCase(); 15 | } 16 | 17 | @Override 18 | public boolean isValid(String value, ConstraintValidatorContext context) { 19 | if (value == null) { 20 | return true; 21 | } 22 | 23 | Enum[] enumValues = enumClass.getEnumConstants(); 24 | 25 | for (Enum enumValue : enumValues) { 26 | if (ignoreCase && enumValue.name().equalsIgnoreCase(value)) { 27 | return true; 28 | } else if (enumValue.name().equals(value)) { 29 | return true; 30 | } 31 | } 32 | 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/validation/ValidCategoryNameValidator.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.validation; 2 | 3 | import jakarta.validation.ConstraintValidator; 4 | import jakarta.validation.ConstraintValidatorContext; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import org.guzzing.studayserver.domain.academy.util.CategoryInfo; 8 | 9 | public class ValidCategoryNameValidator implements ConstraintValidator> { 10 | 11 | @Override 12 | public void initialize(ValidCategoryName constraintAnnotation) { 13 | } 14 | 15 | @Override 16 | public boolean isValid(List value, ConstraintValidatorContext context) { 17 | if (value == null || value.isEmpty()) { 18 | return false; 19 | } 20 | 21 | for (String areaOfExpertise : value) { 22 | if (!isValidAreaOfExpertise(areaOfExpertise)) { 23 | return false; 24 | } 25 | } 26 | 27 | return true; 28 | } 29 | 30 | private boolean isValidAreaOfExpertise(String categoryName) { 31 | return Arrays.stream(CategoryInfo.values()) 32 | .anyMatch(enumValue -> enumValue.getCategoryName().equals(categoryName)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/repository/DashboardRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.repository; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import org.guzzing.studayserver.domain.dashboard.model.Dashboard; 6 | import org.guzzing.studayserver.global.exception.DashboardException; 7 | import org.springframework.data.jpa.repository.Query; 8 | 9 | public interface DashboardRepository { 10 | 11 | Dashboard save(final Dashboard dashboard); 12 | 13 | default Dashboard findDashboardById(final Long dashboardId) { 14 | return this.findById(dashboardId) 15 | .orElseThrow(() -> new DashboardException("존재하지 않는 대시보드입니다.")); 16 | } 17 | 18 | Optional findById(final Long dashboardId); 19 | 20 | @Query("SELECT d FROM Dashboard d WHERE d.childId = :childId AND d.isActive = true AND d.isDeleted = false ") 21 | List findActiveOnlyByChildId(final Long childId); 22 | 23 | @Query("SELECT d FROM Dashboard d WHERE d.childId = :childId AND d.isDeleted = false ") 24 | List findAllByChildId(final Long childId); 25 | 26 | List findAll(); 27 | 28 | List findByIds(List dashboardIds); 29 | 30 | void deleteByChildIds(List childIds); 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/calendar_info/service/util/DateUtilityTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar_info.service.util; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.stream.Stream; 6 | import org.junit.jupiter.params.ParameterizedTest; 7 | import org.junit.jupiter.params.provider.Arguments; 8 | import org.junit.jupiter.params.provider.MethodSource; 9 | 10 | class DateUtilityTest { 11 | 12 | @ParameterizedTest 13 | @MethodSource("datesForLastDayOfMonthProvider") 14 | void testLastDayOfMonth(int year, int month, int expectedLastDay) { 15 | // When 16 | int lastDay = DateUtility.getLastDayOfMonth(year, month); 17 | 18 | // Then 19 | assertThat(lastDay).isEqualTo(expectedLastDay); 20 | } 21 | 22 | static Stream datesForLastDayOfMonthProvider() { 23 | return Stream.of( 24 | Arguments.of(2021, 1, 31), 25 | Arguments.of(2021, 2, 28), 26 | Arguments.of(2020, 2, 29), 27 | Arguments.of(2021, 4, 30), 28 | Arguments.of(2021, 6, 30), 29 | Arguments.of(2021, 9, 30), 30 | Arguments.of(2021, 11, 30), 31 | Arguments.of(2021, 12, 31) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/result/LessonInfoToCreateDashboardResults.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.result; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.repository.dto.LessonInfoToCreateDashboard; 5 | 6 | public record LessonInfoToCreateDashboardResults( 7 | List lessonInfoToCreateDashboardResults 8 | ) { 9 | 10 | public static LessonInfoToCreateDashboardResults from( 11 | List lessonInfoToCreateDashboards) { 12 | return new LessonInfoToCreateDashboardResults( 13 | lessonInfoToCreateDashboards.stream() 14 | .map(LessonInfoToCreateDashboardResult::from) 15 | .toList() 16 | ); 17 | } 18 | 19 | public record LessonInfoToCreateDashboardResult( 20 | Long lessonId, 21 | String subject 22 | ) { 23 | 24 | public static LessonInfoToCreateDashboardResult from(LessonInfoToCreateDashboard lessonInfoToCreateDashboard) { 25 | return new LessonInfoToCreateDashboardResult( 26 | lessonInfoToCreateDashboard.getId(), 27 | lessonInfoToCreateDashboard.getCurriculum() 28 | ); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/vo/Address.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model.vo; 2 | 3 | import io.micrometer.common.util.StringUtils; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Embeddable; 6 | import java.util.Objects; 7 | import lombok.Getter; 8 | import org.springframework.util.Assert; 9 | 10 | @Getter 11 | @Embeddable 12 | public class Address { 13 | 14 | @Column(name = "full_address", nullable = false) 15 | private String fullAddress; 16 | 17 | protected Address(final String address) { 18 | Assert.isTrue(StringUtils.isNotBlank(address), "주소 정보는 반드시 주어져야 합니다."); 19 | this.fullAddress = address; 20 | } 21 | 22 | protected Address() { 23 | } 24 | 25 | public static Address of(final String address) { 26 | return new Address(address); 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) { 32 | return true; 33 | } 34 | if (o == null || getClass() != o.getClass()) { 35 | return false; 36 | } 37 | Address address = (Address) o; 38 | return Objects.equals(fullAddress, address.fullAddress); 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return Objects.hash(fullAddress); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/dto/param/AcademyFilterWithScrollParam.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service.dto.param; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.repository.dto.AcademyFilterCondition; 5 | import org.guzzing.studayserver.domain.academy.util.CategoryInfo; 6 | import org.guzzing.studayserver.domain.academy.util.Latitude; 7 | import org.guzzing.studayserver.domain.academy.util.Longitude; 8 | import org.guzzing.studayserver.domain.academy.util.SqlFormatter; 9 | 10 | public record AcademyFilterWithScrollParam( 11 | Latitude baseLatitude, 12 | Longitude baseLongitude, 13 | List categories, 14 | Long desiredMinAmount, 15 | Long desiredMaxAmount, 16 | int pageNumber 17 | ) { 18 | 19 | public static AcademyFilterCondition to(AcademyFilterWithScrollParam param, 20 | String pointFormat) { 21 | return new AcademyFilterCondition( 22 | pointFormat, 23 | SqlFormatter.makeWhereInString( 24 | param.categories.stream() 25 | .map(CategoryInfo::getCategoryIdByName) 26 | .toList()), 27 | param.desiredMinAmount, 28 | param.desiredMaxAmount 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/util/Latitude.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.util; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.util.Assert; 7 | 8 | import java.util.Objects; 9 | 10 | @Getter 11 | @NoArgsConstructor(access = AccessLevel.PROTECTED) 12 | public class Latitude { 13 | private double value; 14 | 15 | public static final double KOREA_NORTHERNMOST_POINT = 43; 16 | public static final double KOREA_SOUTHERNMOST_POINT = 33; 17 | 18 | private Latitude(double value) { 19 | Assert.isTrue(value <= KOREA_NORTHERNMOST_POINT && value >= KOREA_SOUTHERNMOST_POINT, 20 | String.format( "위도(latitude)는 %s보다 크고, %s보다 작아야 합니다", KOREA_SOUTHERNMOST_POINT, KOREA_NORTHERNMOST_POINT)); 21 | this.value = value; 22 | } 23 | 24 | public static Latitude of(double value) { 25 | return new Latitude(value); 26 | } 27 | 28 | @Override 29 | public boolean equals(Object o) { 30 | if (this == o) return true; 31 | if (o == null || getClass() != o.getClass()) return false; 32 | Latitude latitude = (Latitude) o; 33 | return Double.compare(latitude.value, value) == 0; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Objects.hash(value); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/model/vo/FeeInfo.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.model.vo; 2 | 3 | import static lombok.AccessLevel.PROTECTED; 4 | 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Embeddable; 7 | import java.time.LocalDate; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | 11 | @Getter 12 | @NoArgsConstructor(access = PROTECTED) 13 | @Embeddable 14 | public class FeeInfo { 15 | 16 | @Column(name = "education_fee", nullable = true) 17 | private Long educationFee; 18 | 19 | @Column(name = "book_fee", nullable = true) 20 | private Long bookFee; 21 | 22 | @Column(name = "shuttle_fee", nullable = true) 23 | private Long shuttleFee; 24 | 25 | @Column(name = "etc_fee", nullable = true) 26 | private Long etcFee; 27 | 28 | @Column(name = "payment_day", nullable = true) 29 | private LocalDate paymentDay; 30 | 31 | public FeeInfo( 32 | final Long educationFee, 33 | final Long bookFee, 34 | final Long shuttleFee, 35 | final Long etcFee, 36 | final LocalDate paymentDay 37 | ) { 38 | this.educationFee = educationFee; 39 | this.bookFee = bookFee; 40 | this.shuttleFee = shuttleFee; 41 | this.etcFee = etcFee; 42 | this.paymentDay = paymentDay; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/service/LessonReadService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.service; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.model.Lesson; 5 | import org.guzzing.studayserver.domain.academy.repository.lesson.LessonRepository; 6 | import org.guzzing.studayserver.domain.academy.service.dto.result.LessonFindByIdsResults; 7 | import org.guzzing.studayserver.domain.academy.service.dto.result.LessonFindByIdsResults.LessonFindByIdsResult; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | public class LessonReadService { 12 | 13 | private final LessonRepository lessonRepository; 14 | 15 | public LessonReadService(LessonRepository lessonRepository) { 16 | this.lessonRepository = lessonRepository; 17 | } 18 | 19 | 20 | public LessonFindByIdsResults findByIds(List lessonIds) { 21 | List lessons = lessonRepository.findByIds(lessonIds); 22 | 23 | List lessonFindByIdsResults = lessons.stream() 24 | .map(l -> new LessonFindByIdsResult( 25 | l.getId(), 26 | l.getAcademy().getAcademyName(), 27 | l.getSubject() 28 | )).toList(); 29 | 30 | return new LessonFindByIdsResults(lessonFindByIdsResults); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/controller/dto/RegionResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.controller.dto; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.List; 5 | import org.guzzing.studayserver.domain.region.service.dto.beopjungdong.SidoResult; 6 | import org.guzzing.studayserver.domain.region.service.dto.beopjungdong.SigunguResult; 7 | import org.guzzing.studayserver.domain.region.service.dto.beopjungdong.UpmyeondongResult; 8 | 9 | public record RegionResponse( 10 | String targetRegion, 11 | List subRegion, 12 | int subRegionCount 13 | ) { 14 | 15 | public static RegionResponse from(final SigunguResult sigunguResult) { 16 | return new RegionResponse(sigunguResult.sido(), sigunguResult.sigungus(), sigunguResult.sigunguCount()); 17 | } 18 | 19 | public static RegionResponse from(final UpmyeondongResult upmyeondongResult) { 20 | return new RegionResponse( 21 | MessageFormat.format("{0} {1}", upmyeondongResult.sido(), upmyeondongResult.sigungu()), 22 | upmyeondongResult.upmyeondongs(), 23 | upmyeondongResult.upmyeondongCount()); 24 | } 25 | 26 | public static RegionResponse from(final SidoResult sidoResult) { 27 | return new RegionResponse(sidoResult.nation(), sidoResult.sidos(), sidoResult.sidoCount()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/LessonInfoToCreateDashboardResponses.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.service.dto.result.LessonInfoToCreateDashboardResults; 5 | 6 | public record LessonInfoToCreateDashboardResponses( 7 | List lessonInfos 8 | ) { 9 | 10 | public static LessonInfoToCreateDashboardResponses from(LessonInfoToCreateDashboardResults results) { 11 | return new LessonInfoToCreateDashboardResponses( 12 | results.lessonInfoToCreateDashboardResults() 13 | .stream() 14 | .map(LessonInfoToCreateDashboardResponse::from) 15 | .toList() 16 | ); 17 | } 18 | 19 | public record LessonInfoToCreateDashboardResponse( 20 | Long lessonId, 21 | String subject 22 | ) { 23 | 24 | public static LessonInfoToCreateDashboardResponse from( 25 | LessonInfoToCreateDashboardResults. 26 | LessonInfoToCreateDashboardResult result) { 27 | return new LessonInfoToCreateDashboardResponse( 28 | result.lessonId(), 29 | result.subject() 30 | ); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademiesByLocationWithScrollRepositoryResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.AcademyWithLikeByLocation; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public record AcademiesByLocationWithScrollRepositoryResponse( 11 | Map> academiesByLocation, 12 | boolean hasNext 13 | ) { 14 | 15 | public static AcademiesByLocationWithScrollRepositoryResponse of( 16 | List academiesByLocation, 17 | boolean hasNext 18 | ) { 19 | Map> academyIdWithCategories = new ConcurrentHashMap<>(); 20 | 21 | academiesByLocation.forEach(academyByLocationWithScroll -> academyIdWithCategories.computeIfAbsent( 22 | AcademyWithLikeByLocation.of(academyByLocationWithScroll), 23 | k -> new ArrayList<>()) 24 | .add(academyByLocationWithScroll.getCategoryId())); 25 | 26 | return new AcademiesByLocationWithScrollRepositoryResponse( 27 | academyIdWithCategories, 28 | hasNext 29 | ); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/util/Longitude.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.util; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.util.Assert; 7 | 8 | import java.util.Objects; 9 | 10 | @Getter 11 | @NoArgsConstructor(access = AccessLevel.PROTECTED) 12 | public class Longitude { 13 | private double value; 14 | 15 | public static final double KOREA_NORTHERNMOST_POINT = 132; 16 | public static final double KOREA_SOUTHERNMOST_POINT = 124; 17 | 18 | private Longitude(double value) { 19 | Assert.isTrue(value <= KOREA_NORTHERNMOST_POINT && value >= KOREA_SOUTHERNMOST_POINT, 20 | String.format( "경도(longitude)는 %s보다 크고, %s보다 작아야 합니다", KOREA_SOUTHERNMOST_POINT, KOREA_NORTHERNMOST_POINT)); 21 | this.value = value; 22 | } 23 | 24 | public static Longitude of(double value) { 25 | return new Longitude(value); 26 | } 27 | 28 | @Override 29 | public boolean equals(Object o) { 30 | if (this == o) return true; 31 | if (o == null || getClass() != o.getClass()) return false; 32 | Longitude longitude = (Longitude) o; 33 | return Double.compare(longitude.value, value) == 0; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Objects.hash(value); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/controller/dto/request/validation/AttendanceDateValidator.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.controller.dto.request.validation; 2 | 3 | import jakarta.validation.ConstraintValidator; 4 | import jakarta.validation.ConstraintValidatorContext; 5 | import java.time.LocalDate; 6 | import java.time.format.DateTimeParseException; 7 | import org.guzzing.studayserver.domain.calendar.controller.dto.request.AttendanceDate; 8 | 9 | public class AttendanceDateValidator implements ConstraintValidator { 10 | 11 | private static final int MAX_DIFFERENCE_YEAR = 3; 12 | 13 | @Override 14 | public void initialize(ValidAttendanceDate constraintAnnotation) { 15 | } 16 | 17 | @Override 18 | public boolean isValid(AttendanceDate attendanceDate, ConstraintValidatorContext context) { 19 | if (attendanceDate == null) { 20 | return true; 21 | } 22 | 23 | try { 24 | LocalDate startDate = LocalDate.parse(attendanceDate.getStartDateOfAttendance()); 25 | LocalDate endDate = LocalDate.parse(attendanceDate.getEndDateOfAttendance()); 26 | 27 | return !endDate.isAfter(startDate.plusYears(MAX_DIFFERENCE_YEAR)) && !endDate.isBefore(startDate); 28 | } catch (DateTimeParseException e) { 29 | return false; 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/repository/RegionRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.repository; 2 | 3 | import jakarta.persistence.EntityNotFoundException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import org.guzzing.studayserver.domain.region.model.Region; 7 | import org.locationtech.jts.geom.Point; 8 | 9 | public interface RegionRepository { 10 | 11 | List findSigunguBySido(final String sido); 12 | 13 | List findUpmyeondongBySidoAndSigungu(final String sido, final String sigungu); 14 | 15 | Optional findBySidoAndSigunguAndUpmyeondong(final String sido, final String sigungu, 16 | final String upmyeondong); 17 | 18 | default Region getBySidoAndSigunguAndUpmyeondong(final String sido, final String sigungu, 19 | final String upmyeondong) { 20 | return this.findBySidoAndSigunguAndUpmyeondong(sido, sigungu, upmyeondong) 21 | .orElseThrow(() -> new EntityNotFoundException("해당 지역에 해당하는 법정동 지역이 없습니다.")); 22 | } 23 | 24 | Optional findByAreaContainingPoint(final Point point); 25 | 26 | default Region getByAreaContainingPoint(final Point point) { 27 | return this.findByAreaContainingPoint(point) 28 | .orElseThrow(() -> new EntityNotFoundException("해당 위경도에 해당하는 법정동 지역이 없습니다.")); 29 | } 30 | 31 | Region save(Region region); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/AcademyCategory.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model; 2 | 3 | import static jakarta.persistence.FetchType.LAZY; 4 | 5 | import jakarta.persistence.Column; 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.GeneratedValue; 8 | import jakarta.persistence.GenerationType; 9 | import jakarta.persistence.Id; 10 | import jakarta.persistence.JoinColumn; 11 | import jakarta.persistence.ManyToOne; 12 | import jakarta.persistence.Table; 13 | import lombok.Getter; 14 | 15 | @Getter 16 | @Table(name = "academy_categories") 17 | @Entity 18 | public class AcademyCategory { 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | Long id; 23 | 24 | @ManyToOne(fetch = LAZY) 25 | @JoinColumn(name = "academy_id") 26 | Academy academy; 27 | 28 | @Column(name = "category_id") 29 | Long categoryId; 30 | 31 | protected AcademyCategory() { 32 | } 33 | 34 | private AcademyCategory( 35 | final Academy academy, 36 | final Long categoryId) { 37 | this.academy = academy; 38 | this.categoryId = categoryId; 39 | } 40 | 41 | public static AcademyCategory of( 42 | final Academy academy, 43 | final Long categoryId) { 44 | return new AcademyCategory( 45 | academy, 46 | categoryId); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/model/vo/Location.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model.vo; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Embeddable; 5 | import java.util.Objects; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | @Embeddable 10 | public class Location { 11 | 12 | @Column(name = "latitude", nullable = false) 13 | private double latitude; 14 | @Column(name = "longitude", nullable = false) 15 | private double longitude; 16 | 17 | protected Location(final double latitude, final double longitude) { 18 | this.latitude = latitude; 19 | this.longitude = longitude; 20 | } 21 | 22 | protected Location() { 23 | } 24 | 25 | public static Location of(final double latitude, final double longitude) { 26 | return new Location(latitude, longitude); 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) { 32 | return true; 33 | } 34 | if (o == null || getClass() != o.getClass()) { 35 | return false; 36 | } 37 | Location location = (Location) o; 38 | return Double.compare(location.latitude, latitude) == 0 && Double.compare(location.longitude, longitude) == 0; 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return Objects.hash(latitude, longitude); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/holiday/service/HolidayService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.holiday.service; 2 | 3 | import java.time.LocalDate; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import org.guzzing.studayserver.domain.holiday.model.Holiday; 9 | import org.guzzing.studayserver.domain.holiday.repository.HolidayRepository; 10 | import org.guzzing.studayserver.domain.holiday.service.result.HolidayFindByYearMonthResult; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | @Service 15 | public class HolidayService { 16 | 17 | private final HolidayRepository holidayRepository; 18 | 19 | public HolidayService(HolidayRepository holidayRepository) { 20 | this.holidayRepository = holidayRepository; 21 | } 22 | 23 | @Transactional(readOnly = true) 24 | public HolidayFindByYearMonthResult findByYearMonth(int year, int month) { 25 | List holidays = holidayRepository.findByYearMonth(year, month); 26 | 27 | Map> holidayMap = new HashMap<>(); 28 | 29 | holidays.forEach(h -> 30 | holidayMap.computeIfAbsent(h.getDate(), k -> new ArrayList<>()).add(h.getDateName()) 31 | ); 32 | 33 | return HolidayFindByYearMonthResult.from(holidayMap); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademyByLocationWithCursorRepositoryResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.AcademyWithLikeByLocation; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public record AcademyByLocationWithCursorRepositoryResponse( 11 | Map> academiesByLocation, 12 | Long lastAcademyId, 13 | boolean hasNext 14 | ) { 15 | 16 | public static AcademyByLocationWithCursorRepositoryResponse of( 17 | List academiesByLocation, 18 | Long lastAcademyId, 19 | boolean hasNext 20 | ) { 21 | Map> academyIdWithCategories = new ConcurrentHashMap<>(); 22 | 23 | academiesByLocation.forEach(academyByLocation -> academyIdWithCategories.computeIfAbsent( 24 | AcademyWithLikeByLocation.of(academyByLocation), 25 | k -> new ArrayList<>()) 26 | .add(academyByLocation.getCategoryId())); 27 | 28 | return new AcademyByLocationWithCursorRepositoryResponse( 29 | academyIdWithCategories, 30 | lastAcademyId, 31 | hasNext 32 | ); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/lesson/LessonJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.lesson; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import org.guzzing.studayserver.domain.academy.model.Lesson; 6 | import org.guzzing.studayserver.domain.academy.repository.dto.LessonInfoToCreateDashboard; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.data.repository.query.Param; 10 | 11 | public interface LessonJpaRepository extends JpaRepository, LessonRepository { 12 | 13 | @Query("select l from Lesson as l join fetch l.academy as ac where l.academy.id =:academyId") 14 | List findAllByAcademyId(@Param("academyId") Long academyId); 15 | 16 | @Query("select l from Lesson as l join fetch l.academy as ac where l.id = :lessonId") 17 | Optional findLessonById(@Param(value = "lessonId") Long lessonId); 18 | 19 | @Query("select l.id as id, l.curriculum as curriculum from Lesson as l where l.academy.id =:academyId") 20 | List findAllLessonInfoByAcademyId(@Param("academyId") Long academyId); 21 | 22 | @Query("SELECT ls FROM Lesson AS ls " 23 | + "JOIN FETCH ls.academy aca " 24 | + "WHERE ls.id IN :lessonIds") 25 | List findByIds(List lessonIds); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/service/scheduler/AcademyScheduleMaker.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.service.scheduler; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalDate; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import org.guzzing.studayserver.domain.calendar.service.dto.RepeatPeriod; 8 | 9 | public interface AcademyScheduleMaker { 10 | 11 | default List generateSchedules(RepeatPeriod repeatPeriod) { 12 | LocalDate startDate = repeatPeriod.startDateOfAttendance(); 13 | LocalDate endDate = repeatPeriod.endDateOfAttendance(); 14 | List createdDates = new ArrayList<>(); 15 | 16 | int offsetDays = calculateOffsetDays(startDate, repeatPeriod.dayOfWeek()); 17 | LocalDate currentRepeatedDate = startDate.plusDays(offsetDays); 18 | 19 | while (!currentRepeatedDate.isAfter(endDate)) { 20 | createdDates.add(currentRepeatedDate); 21 | currentRepeatedDate = getNextRepeatedDate(currentRepeatedDate); 22 | } 23 | 24 | return createdDates; 25 | } 26 | 27 | default int calculateOffsetDays(LocalDate startDate, DayOfWeek targetDayOfWeek) { 28 | int offsetDays = targetDayOfWeek.getValue() - startDate.getDayOfWeek().getValue(); 29 | return offsetDays >= 0 ? offsetDays : 7 + offsetDays; 30 | } 31 | 32 | LocalDate getNextRepeatedDate(LocalDate baseDate); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/region/repository/RegionJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.region.repository; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import org.guzzing.studayserver.domain.region.model.Region; 6 | import org.locationtech.jts.geom.Point; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.data.repository.query.Param; 10 | 11 | public interface RegionJpaRepository extends JpaRepository, RegionRepository { 12 | 13 | @Query("select distinct(r.address.sigungu) from Region r where r.address.sido = :sido") 14 | List findSigunguBySido(final String sido); 15 | 16 | @Query("select distinct(r.address.upmyeondong) from Region r where r.address.sido = :sido and r.address.sigungu = :sigungu") 17 | List findUpmyeondongBySidoAndSigungu(final String sido, final String sigungu); 18 | 19 | @Query("select r from Region r where r.address.sido = :sido and r.address.sigungu = :sigungu and r.address.upmyeondong = :upmyeondong") 20 | Optional findBySidoAndSigunguAndUpmyeondong(final String sido, final String sigungu, 21 | final String upmyeondong); 22 | 23 | @Override 24 | @Query("select r from Region r where ST_Contains(r.area, :point)") 25 | Optional findByAreaContainingPoint(@Param("point") final Point point); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/controller/dto/response/AcademyGetResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.controller.dto.response; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.academy.facade.dto.AcademyDetailFacadeResult; 5 | 6 | public record AcademyGetResponse( 7 | String academyName, 8 | String contact, 9 | String address, 10 | String shuttleAvailability, 11 | Long expectedFee, 12 | String updatedDate, 13 | List categories, 14 | LessonGetResponses lessonGetResponses, 15 | ReviewPercentGetResponse reviewPercentGetResponse, 16 | boolean isLiked 17 | ) { 18 | 19 | public static AcademyGetResponse from(AcademyDetailFacadeResult academyGetResult) { 20 | return new AcademyGetResponse( 21 | academyGetResult.academyName(), 22 | academyGetResult.contact(), 23 | academyGetResult.fullAddress(), 24 | academyGetResult.shuttleAvailability(), 25 | academyGetResult.expectedFee(), 26 | academyGetResult.updatedDate(), 27 | academyGetResult.categories(), 28 | 29 | LessonGetResponses.from(academyGetResult.lessonGetResults()), 30 | ReviewPercentGetResponse.from(academyGetResult.reviewPercentGetResult()), 31 | academyGetResult.isLiked() 32 | ); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/org/guzzing/studayserver/domain/academy/model/LessonTest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.model; 2 | 3 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 4 | 5 | import org.guzzing.studayserver.testutil.fixture.academy.AcademyFixture; 6 | import org.junit.jupiter.api.DisplayName; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class LessonTest { 10 | 11 | @Test 12 | @DisplayName("수업을 등록할 때 학원이 없으면 예외를 던진다.") 13 | void makeLesson_nullAcademy_throwException() { 14 | //Then 15 | assertThatThrownBy( 16 | () -> Lesson.of(null, "자바와 객체지향", "자바와 객체지향으로 떠나자", "20", "1개월", "100000") 17 | ).isInstanceOf(IllegalArgumentException.class); 18 | } 19 | 20 | @Test 21 | @DisplayName("수업 정원이 음수인 경우 예외를 던진다.") 22 | void makeLesson_minusCapacity_throwException() { 23 | //Then 24 | assertThatThrownBy( 25 | () -> Lesson.of(AcademyFixture.academySungnam(), "자바와 객체지향", "자바와 객체지향으로 떠나자", "-100", "1개월", "100000") 26 | ).isInstanceOf(IllegalArgumentException.class); 27 | } 28 | 29 | @Test 30 | @DisplayName("강의료가 음수인 경우 예외를 던진다. ") 31 | void makeLesson_minusTotalFee_throwException() { 32 | //Then 33 | assertThatThrownBy( 34 | () -> Lesson.of(AcademyFixture.academySungnam(), "자바와 객체지향", "자바와 객체지향으로 떠나자", "20", "1개월", "-100000") 35 | ).isInstanceOf(IllegalArgumentException.class); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/calendar/repository/academytimetemplate/AcademyTimeTemplateJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.calendar.repository.academytimetemplate; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.calendar.model.AcademyTimeTemplate; 5 | import org.guzzing.studayserver.domain.calendar.repository.dto.AcademyTimeTemplateDateInfo; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Modifying; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | public interface AcademyTimeTemplateJpaRepository extends JpaRepository, 12 | AcademyTimeTemplateRepository { 13 | 14 | AcademyTimeTemplate save(AcademyTimeTemplate academyTimeTemplate); 15 | 16 | List findAcademyTimeTemplateByDashboardId(Long dashboardId); 17 | 18 | void deleteById(Long academyTimeTemplateId); 19 | 20 | AcademyTimeTemplate getById(Long academyTimeTemplateId); 21 | 22 | @Query("select att.id from AcademyTimeTemplate att where att.childId in :childIds") 23 | List findByChildIdIn(List childIds); 24 | 25 | @Transactional 26 | @Modifying(clearAutomatically = true) 27 | @Query("delete from AcademyTimeTemplate att where att.childId in :childIds") 28 | void deleteAllByChildIds(List childIds); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/academy/repository/dto/response/AcademyByLocationWithCursorNotLikeRepositoryResponse.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.academy.repository.dto.response; 2 | 3 | import org.guzzing.studayserver.domain.academy.repository.dto.AcademyWithNotLikeByLocation; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public record AcademyByLocationWithCursorNotLikeRepositoryResponse( 11 | Map> academiesByLocation, 12 | Long lastAcademyId, 13 | boolean hasNext 14 | ) { 15 | 16 | public static AcademyByLocationWithCursorNotLikeRepositoryResponse of( 17 | List academiesByLocation, 18 | Long lastAcademyId, 19 | boolean hasNext 20 | ) { 21 | Map> academyIdWithCategories = new ConcurrentHashMap<>(); 22 | 23 | academiesByLocation.forEach(academyByLocation -> academyIdWithCategories.computeIfAbsent( 24 | AcademyWithNotLikeByLocation.of(academyByLocation), 25 | k -> new ArrayList<>()) 26 | .add(academyByLocation.getCategoryId())); 27 | 28 | return new AcademyByLocationWithCursorNotLikeRepositoryResponse( 29 | academyIdWithCategories, 30 | lastAcademyId, 31 | hasNext 32 | ); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/client/dto/KakaoUser.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.client.dto; 2 | 3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy; 4 | import com.fasterxml.jackson.databind.annotation.JsonNaming; 5 | import lombok.Getter; 6 | import org.guzzing.studayserver.domain.member.model.vo.NickName; 7 | 8 | 9 | @Getter 10 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) 11 | public class KakaoUser { 12 | 13 | private Long id; 14 | private Properties properties; 15 | private KakaoAccount kakaoAccount; 16 | 17 | public KakaoUser() { 18 | } 19 | 20 | public KakaoUser(Long id, Properties properties, KakaoAccount kakaoAccount) { 21 | this.id = id; 22 | this.properties = properties; 23 | this.kakaoAccount = kakaoAccount; 24 | } 25 | 26 | @Getter 27 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) 28 | public static class Properties { 29 | 30 | private NickName nickname; 31 | 32 | public Properties() { 33 | } 34 | 35 | public Properties(NickName nickname) { 36 | this.nickname = nickname; 37 | } 38 | 39 | } 40 | 41 | @Getter 42 | public static class KakaoAccount { 43 | 44 | private String email; 45 | 46 | public KakaoAccount() { 47 | } 48 | 49 | public KakaoAccount(String email) { 50 | this.email = email; 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/auth/listener/WithdrawAuthTokenListener.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.auth.listener; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | import org.guzzing.studayserver.domain.auth.jwt.AuthToken; 5 | import org.guzzing.studayserver.domain.auth.jwt.AuthTokenProvider; 6 | import org.guzzing.studayserver.domain.auth.jwt.JwtHeaderUtil; 7 | import org.guzzing.studayserver.domain.auth.service.AuthService; 8 | import org.guzzing.studayserver.domain.member.event.WithdrawEvent; 9 | import org.springframework.scheduling.annotation.Async; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.transaction.event.TransactionalEventListener; 12 | 13 | @Component 14 | public class WithdrawAuthTokenListener { 15 | 16 | private final AuthService authService; 17 | private final AuthTokenProvider authTokenProvider; 18 | 19 | public WithdrawAuthTokenListener(AuthService authService, AuthTokenProvider authTokenProvider) { 20 | this.authService = authService; 21 | this.authTokenProvider = authTokenProvider; 22 | } 23 | 24 | @Async 25 | @TransactionalEventListener 26 | public void withdrawAuthToken(WithdrawEvent event) { 27 | HttpServletRequest request = event.getRequest(); 28 | String accessToken = JwtHeaderUtil.getAccessToken(request); 29 | AuthToken authToken = authTokenProvider.convertAuthToken(accessToken); 30 | 31 | authService.logout(authToken); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/global/config/CaffeineCacheConfig.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.global.config; 2 | 3 | import com.github.benmanes.caffeine.cache.Caffeine; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.concurrent.TimeUnit; 7 | import org.springframework.cache.CacheManager; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.cache.caffeine.CaffeineCache; 10 | import org.springframework.cache.support.SimpleCacheManager; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | @EnableCaching 15 | @Configuration 16 | public class CaffeineCacheConfig { 17 | 18 | @Bean 19 | public CacheManager cacheManager() { 20 | SimpleCacheManager cacheManager = new SimpleCacheManager(); 21 | 22 | List caches = Arrays.stream(CaffeineCacheType.values()) 23 | .map(caffeineCacheType -> new CaffeineCache( 24 | caffeineCacheType.getCacheName(), 25 | Caffeine.newBuilder() 26 | .expireAfterWrite(caffeineCacheType.getExpireAfterWrite(), TimeUnit.DAYS) 27 | .maximumSize(caffeineCacheType.getMaximumSize()) 28 | .build() 29 | )) 30 | .toList(); 31 | 32 | cacheManager.setCaches(caches); 33 | 34 | return cacheManager; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/dashboard/service/DashboardReadService.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.dashboard.service; 2 | 3 | import java.util.List; 4 | import org.guzzing.studayserver.domain.dashboard.model.Dashboard; 5 | import org.guzzing.studayserver.domain.dashboard.repository.DashboardRepository; 6 | import org.guzzing.studayserver.domain.dashboard.service.dto.response.DashBoardFindByIdsResults; 7 | import org.guzzing.studayserver.domain.dashboard.service.dto.response.DashBoardFindByIdsResults.DashBoardFindByIdsResult; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | @Service 12 | public class DashboardReadService { 13 | 14 | private final DashboardRepository dashboardRepository; 15 | 16 | public DashboardReadService(DashboardRepository dashboardRepository) { 17 | this.dashboardRepository = dashboardRepository; 18 | } 19 | 20 | @Transactional(readOnly = true) 21 | public DashBoardFindByIdsResults findByIds(List dashboardIds) { 22 | List dashboards = dashboardRepository.findByIds(dashboardIds); 23 | 24 | List dashBoardFindByIdsResults = dashboards.stream() 25 | .map(d -> new DashBoardFindByIdsResult( 26 | d.getId(), 27 | d.getLessonId() 28 | )).toList(); 29 | 30 | return new DashBoardFindByIdsResults(dashBoardFindByIdsResults); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/member/controller/request/MemberRegisterRequest.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.member.controller.request; 2 | 3 | import jakarta.validation.Valid; 4 | import jakarta.validation.constraints.Email; 5 | import jakarta.validation.constraints.NotBlank; 6 | import jakarta.validation.constraints.NotNull; 7 | import jakarta.validation.constraints.Size; 8 | import java.util.List; 9 | import org.guzzing.studayserver.domain.child.controller.request.ChildCreateRequest; 10 | import org.guzzing.studayserver.domain.child.service.param.ChildCreateParam; 11 | import org.guzzing.studayserver.domain.member.service.param.MemberRegisterParam; 12 | 13 | public record MemberRegisterRequest( 14 | @NotBlank(message = "이름은 빈 값일 수 없습니다.") 15 | @Size(min = 1, max = 10, message = "이름의 길이는 1-10자 사이여야 합니다.") 16 | String nickname, 17 | 18 | @NotBlank(message = "이메일은 빈 값일 수 없습니다.") 19 | @Email(message = "올바른 이메일 형식이어야 합니다.") 20 | String email, 21 | 22 | @NotNull 23 | @Size(min = 1, max = 5, message = "아이는 최소 1명에서 최대 5명까지 등록이 가능합니다.") 24 | @Valid 25 | List children 26 | ) { 27 | 28 | public MemberRegisterParam toParam() { 29 | List childParams = 30 | this.children.stream() 31 | .map(ChildCreateRequest::toParam) 32 | .toList(); 33 | 34 | return new MemberRegisterParam(nickname, email, childParams); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/org/guzzing/studayserver/domain/child/service/ChildWithScheduleMappingDummyEntity.java: -------------------------------------------------------------------------------- 1 | package org.guzzing.studayserver.domain.child.service; 2 | 3 | import jakarta.persistence.ColumnResult; 4 | import jakarta.persistence.ConstructorResult; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.GeneratedValue; 7 | import jakarta.persistence.GenerationType; 8 | import jakarta.persistence.Id; 9 | import jakarta.persistence.SqlResultSetMapping; 10 | import java.time.LocalDate; 11 | import java.time.LocalTime; 12 | import lombok.Getter; 13 | 14 | @Getter 15 | @Entity 16 | @SqlResultSetMapping( 17 | name = "ChildWithScheduleResultSetMapping", 18 | classes = @ConstructorResult( 19 | targetClass = ChildDateScheduleResult.class, 20 | columns = { 21 | @ColumnResult(name = "child_id", type = Long.class), 22 | @ColumnResult(name = "schedule_date", type = LocalDate.class), 23 | @ColumnResult(name = "lesson_start_time", type = LocalTime.class), 24 | @ColumnResult(name = "lesson_end_time", type = LocalTime.class), 25 | @ColumnResult(name = "academy_name", type = String.class), 26 | @ColumnResult(name = "lesson_subject", type = String.class) 27 | } 28 | ) 29 | ) 30 | public class ChildWithScheduleMappingDummyEntity { 31 | 32 | @Id 33 | @GeneratedValue(strategy = GenerationType.IDENTITY) 34 | private Long id; 35 | } 36 | --------------------------------------------------------------------------------