diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 7d56331..a6b4d0e 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -8,8 +8,6 @@ jobs: build: runs-on: ubuntu-latest - permissions: - contents: read steps: - uses: actions/checkout@v4 @@ -22,5 +20,11 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + - name: Set YML + run: | + echo $DATA_KEY_YML | base64 --decode > src/main/resources/application-data.yml + env: + DATA_KEY_YML: ${{ secrets.APPLICATION_DATA_YML }} + - name: Build with Gradle Wrapper run: ./gradlew build diff --git a/.github/workflows/prod-ci.yml b/.github/workflows/prod-ci.yml index c6a5f88..4fc594f 100644 --- a/.github/workflows/prod-ci.yml +++ b/.github/workflows/prod-ci.yml @@ -20,6 +20,12 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + - name: Set YML + run: | + echo $DATA_KEY_YML | base64 --decode > src/main/resources/application-data.yml + env: + DATA_KEY_YML: ${{ secrets.APPLICATION_DATA_YML }} + - name: Build with Gradle Wrapper run: ./gradlew build diff --git a/.gitignore b/.gitignore index e17772e..4b6d690 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,4 @@ nb-configuration.xml ############################## src/main/resources/application-prod-db.yml src/main/resources/application-jwt.yml +src/main/resources/application-data.yml diff --git a/build.gradle b/build.gradle index 4416840..8300652 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,9 @@ dependencies { implementation 'com.opencsv:opencsv:5.5.2' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0' + implementation 'com.opencsv:opencsv:5.5.2' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta' diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 8e195ce..1d5e92c 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -27,6 +27,6 @@ chmod +x $JAR_NAME echo "> $JAR_NAME 실행" nohup java -jar \ - -Dspring.config.location=/home/ubuntu/prod/application-prod-db.yml,/home/ubuntu/prod/application-jwt.yml \ + -Dspring.config.location=/home/ubuntu/prod/application-prod-db.yml,/home/ubuntu/prod/application-jwt.yml,/home/ubuntu/prod/application-data.yml \ -Dspring.profiles.active=prod \ $REPOSITORY/$JAR_NAME 2>&1 & \ No newline at end of file diff --git a/src/main/java/com/gamsa/activity/controller/ActivityController.java b/src/main/java/com/gamsa/activity/controller/ActivityController.java index 13e3fa5..2a80f63 100644 --- a/src/main/java/com/gamsa/activity/controller/ActivityController.java +++ b/src/main/java/com/gamsa/activity/controller/ActivityController.java @@ -3,17 +3,14 @@ import com.gamsa.activity.constant.Category; import com.gamsa.activity.dto.ActivityDetailResponse; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.dto.ActivityFindSliceResponse; -import com.gamsa.activity.dto.ActivitySaveRequest; import com.gamsa.activity.service.ActivityService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -33,27 +30,24 @@ public Slice findSlice( @RequestParam(required = false) Integer sidoCode, @RequestParam(defaultValue = "false") boolean teenPossibleOnly, @RequestParam(defaultValue = "false") boolean beforeDeadlineOnly, + @RequestParam(required = false) String keyword, + @RequestBody(required = false) ActivityFindDistanceOrderRequest distanceOrderRequest, Pageable pageable) { - ActivityFilterRequest request = ActivityFilterRequest.builder() + ActivityFilterRequest filterRequest = ActivityFilterRequest.builder() .category(Category.fromValuesForSlice(category)) .sidoGunguCode(sidoGunguCode) .sidoCode(sidoCode) .teenPossibleOnly(teenPossibleOnly) .beforeDeadlineOnly(beforeDeadlineOnly) + .keyword(keyword) .build(); - return activityService.findSlice(request, pageable); + return activityService.findSlice(filterRequest, distanceOrderRequest, pageable); } @GetMapping("{activity-id}") public ActivityDetailResponse findById(@PathVariable("activity-id") Long activityId) { return activityService.findById(activityId); } - - @PostMapping - public ResponseEntity save(@RequestBody ActivitySaveRequest saveRequest) { - activityService.save(saveRequest); - return new ResponseEntity<>(HttpStatus.CREATED); - } } diff --git a/src/main/java/com/gamsa/activity/dto/ActivityApiResponse.java b/src/main/java/com/gamsa/activity/dto/ActivityApiResponse.java deleted file mode 100644 index 0d86386..0000000 --- a/src/main/java/com/gamsa/activity/dto/ActivityApiResponse.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gamsa.activity.dto; - -import com.gamsa.activity.constant.Category; -import lombok.Builder; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@Builder -@RequiredArgsConstructor -public class ActivityApiResponse { - - private final Long actId; - private final String actTitle; - private final String actLocation; - private final String description; - private final LocalDateTime noticeStartDate; - private final LocalDateTime noticeEndDate; - private final LocalDateTime actStartDate; - private final LocalDateTime actEndDate; - private final int actStartTime; - private final int actEndTime; - private final int recruitTotalNum; - private final boolean adultPossible; - private final boolean teenPossible; - private final boolean groupPossible; - private final int actWeek; - private final String actManager; - private final String actPhone; - private final String url; - private final Category category; - private final String instituteName; - private final Integer sidoGunguCode; - - public ActivitySaveRequest toSaveRequest(long instituteId) { - return ActivitySaveRequest.builder() - .actId(actId) - .actTitle(actTitle) - .actLocation(actLocation) - .description(description) - .noticeStartDate(noticeStartDate) - .noticeEndDate(noticeEndDate) - .actStartDate(actStartDate) - .actEndDate(actEndDate) - .actStartTime(actStartTime) - .actEndTime(actEndTime) - .recruitTotalNum(recruitTotalNum) - .adultPossible(adultPossible) - .teenPossible(teenPossible) - .groupPossible(groupPossible) - .actWeek(actWeek) - .actManager(actManager) - .actPhone(actPhone) - .url(url) - .category(category) - .instituteId(instituteId) - .sidoGunguCode(sidoGunguCode) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/com/gamsa/activity/dto/ActivityDetailResponse.java b/src/main/java/com/gamsa/activity/dto/ActivityDetailResponse.java index ac421ac..c44f92d 100644 --- a/src/main/java/com/gamsa/activity/dto/ActivityDetailResponse.java +++ b/src/main/java/com/gamsa/activity/dto/ActivityDetailResponse.java @@ -3,7 +3,7 @@ import com.gamsa.activity.constant.Category; import com.gamsa.activity.domain.Activity; -import com.gamsa.review.dto.QuestionResponse; +import com.gamsa.review.domain.Question; import lombok.Builder; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -31,6 +31,8 @@ public class ActivityDetailResponse { private final boolean adultPossible; private final boolean teenPossible; private final boolean groupPossible; + private final BigDecimal latitude; + private final BigDecimal longitude; private final int actWeek; private final String actManager; private final String actPhone; @@ -39,7 +41,7 @@ public class ActivityDetailResponse { private final InstituteDetailResponse institute; private final DistrictDetailResponse sidoGungu; - public static ActivityDetailResponse from(Activity activity, Map scores) { + public static ActivityDetailResponse from(Activity activity, Map scores) { return ActivityDetailResponse.builder() .actId(activity.getActId()) .actTitle(activity.getActTitle()) @@ -55,6 +57,8 @@ public static ActivityDetailResponse from(Activity activity, Map coordinates) { + return InstituteSaveRequest.builder() .name(name) .location(location) .sidoCode(sidoCode) .sidoGunguCode(sidoGunguCode) - .longitude(coordinates.get("longitude")) - .latitude(coordinates.get("latitude")) + .longitude(coordinates.getOrDefault("longitude", new BigDecimal(1))) + .latitude(coordinates.getOrDefault("latitude", new BigDecimal(1))) .phone(phone) .build(); } diff --git a/src/main/java/com/gamsa/activity/dto/InstituteDetailResponse.java b/src/main/java/com/gamsa/activity/dto/InstituteDetailResponse.java index effb689..77ddd8c 100644 --- a/src/main/java/com/gamsa/activity/dto/InstituteDetailResponse.java +++ b/src/main/java/com/gamsa/activity/dto/InstituteDetailResponse.java @@ -1,11 +1,17 @@ package com.gamsa.activity.dto; import com.gamsa.activity.domain.Institute; -import java.math.BigDecimal; +import com.gamsa.review.domain.Question; +import com.gamsa.review.dto.ReviewResponse; import lombok.Builder; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + @Getter @Builder @RequiredArgsConstructor @@ -17,15 +23,22 @@ public class InstituteDetailResponse { private final BigDecimal latitude; private final BigDecimal longitude; private final String phone; + private final List scores; + + public static InstituteDetailResponse from(Institute institute, Map scores) { + List reviewResponses = scores.entrySet().stream() + .map(entry -> ReviewResponse.from(entry.getKey(), entry.getValue())) + .collect(Collectors.toList()); + - public static InstituteDetailResponse from(Institute institute) { return InstituteDetailResponse.builder() - .instituteId(institute.getInstituteId()) - .name(institute.getName()) - .location(institute.getLocation()) - .latitude(institute.getLatitude()) - .longitude(institute.getLongitude()) - .phone(institute.getPhone()) - .build(); + .instituteId(institute.getInstituteId()) + .name(institute.getName()) + .location(institute.getLocation()) + .latitude(institute.getLatitude()) + .longitude(institute.getLongitude()) + .phone(institute.getPhone()) + .scores(reviewResponses) + .build(); } } diff --git a/src/main/java/com/gamsa/activity/entity/ActivityJpaEntity.java b/src/main/java/com/gamsa/activity/entity/ActivityJpaEntity.java index 7dc92b5..1b01a7f 100644 --- a/src/main/java/com/gamsa/activity/entity/ActivityJpaEntity.java +++ b/src/main/java/com/gamsa/activity/entity/ActivityJpaEntity.java @@ -14,6 +14,7 @@ import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; +import java.math.BigDecimal; import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -79,13 +80,19 @@ public class ActivityJpaEntity extends BaseEntity { @Column(name = "online_possible") private boolean onlinePossible; + @Column(name = "latitude", precision = 10, scale = 8) + private BigDecimal latitude; + + @Column(name = "longitude", precision = 11, scale = 8) + private BigDecimal longitude; + @Column(name = "act_week") private int actWeek; @Column(name = "act_manager", length = 255) private String actManager; - @Column(name = "act_phone", length = 12) + @Column(name = "act_phone", length = 25) private String actPhone; @Column(name = "url", length = 255) @@ -105,54 +112,58 @@ public class ActivityJpaEntity extends BaseEntity { public static ActivityJpaEntity from(Activity activity) { return ActivityJpaEntity.builder() - .actId(activity.getActId()) - .actTitle(activity.getActTitle()) - .actLocation(activity.getActLocation()) - .description(activity.getDescription()) - .noticeStartDate(activity.getNoticeStartDate()) - .noticeEndDate(activity.getNoticeEndDate()) - .actStartDate(activity.getActStartDate()) - .actEndDate(activity.getActEndDate()) - .actStartTime(activity.getActStartTime()) - .actEndTime(activity.getActEndTime()) - .recruitTotalNum(activity.getRecruitTotalNum()) - .adultPossible(activity.isAdultPossible()) - .teenPossible(activity.isTeenPossible()) - .groupPossible(activity.isGroupPossible()) - .actWeek(activity.getActWeek()) - .actManager(activity.getActManager()) - .actPhone(activity.getActPhone()) - .url(activity.getUrl()) - .category(activity.getCategory()) - .institute(InstituteJpaEntity.from(activity.getInstitute())) - .sidoGungu(DistrictJpaEntity.from(activity.getSidoGungu())) - .build(); + .actId(activity.getActId()) + .actTitle(activity.getActTitle()) + .actLocation(activity.getActLocation()) + .description(activity.getDescription()) + .noticeStartDate(activity.getNoticeStartDate()) + .noticeEndDate(activity.getNoticeEndDate()) + .actStartDate(activity.getActStartDate()) + .actEndDate(activity.getActEndDate()) + .actStartTime(activity.getActStartTime()) + .actEndTime(activity.getActEndTime()) + .recruitTotalNum(activity.getRecruitTotalNum()) + .adultPossible(activity.isAdultPossible()) + .teenPossible(activity.isTeenPossible()) + .groupPossible(activity.isGroupPossible()) + .longitude(activity.getLongitude()) + .latitude(activity.getLatitude()) + .actWeek(activity.getActWeek()) + .actManager(activity.getActManager()) + .actPhone(activity.getActPhone()) + .url(activity.getUrl()) + .category(activity.getCategory()) + .institute(InstituteJpaEntity.from(activity.getInstitute())) + .sidoGungu(DistrictJpaEntity.from(activity.getSidoGungu())) + .build(); } public Activity toModel() { return Activity.builder() - .actId(actId) - .actTitle(actTitle) - .actLocation(actLocation) - .description(description) - .noticeStartDate(noticeStartDate) - .noticeEndDate(noticeEndDate) - .actStartDate(actStartDate) - .actEndDate(actEndDate) - .actStartTime(actStartTime) - .actEndTime(actEndTime) - .recruitTotalNum(recruitTotalNum) - .adultPossible(adultPossible) - .teenPossible(teenPossible) - .groupPossible(groupPossible) - .actWeek(actWeek) - .actManager(actManager) - .actPhone(actPhone) - .url(url) - .category(category) - .institute(institute.toModel()) - .sidoGungu(sidoGungu.toModel()) - .build(); + .actId(actId) + .actTitle(actTitle) + .actLocation(actLocation) + .description(description) + .noticeStartDate(noticeStartDate) + .noticeEndDate(noticeEndDate) + .actStartDate(actStartDate) + .actEndDate(actEndDate) + .actStartTime(actStartTime) + .actEndTime(actEndTime) + .recruitTotalNum(recruitTotalNum) + .adultPossible(adultPossible) + .teenPossible(teenPossible) + .groupPossible(groupPossible) + .longitude(longitude) + .latitude(latitude) + .actWeek(actWeek) + .actManager(actManager) + .actPhone(actPhone) + .url(url) + .category(category) + .institute(institute.toModel()) + .sidoGungu(sidoGungu.toModel()) + .build(); } } diff --git a/src/main/java/com/gamsa/activity/entity/DistrictJpaEntity.java b/src/main/java/com/gamsa/activity/entity/DistrictJpaEntity.java index 8d72266..c2503a1 100644 --- a/src/main/java/com/gamsa/activity/entity/DistrictJpaEntity.java +++ b/src/main/java/com/gamsa/activity/entity/DistrictJpaEntity.java @@ -6,9 +6,12 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; -import lombok.*; - import java.math.BigDecimal; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder @@ -25,10 +28,10 @@ public class DistrictJpaEntity extends BaseEntity { @Column(name = "sido_code", nullable = false) private int sidoCode; - @Column(name = "latitude") + @Column(name = "latitude", precision = 10, scale = 8) private BigDecimal latitude; - @Column(name = "longitude") + @Column(name = "longitude", precision = 11, scale = 8) private BigDecimal longitude; @Column(name = "sido_name", length = 15, nullable = false) @@ -46,6 +49,8 @@ public static DistrictJpaEntity from(District district) { .sidoCode(district.getSidoCode()) .sidoName(district.getSidoName()) .gunguName(district.getGunguName()) + .latitude(district.getLatitude()) + .longitude(district.getLongitude()) .sido(district.isSido()) .build(); } @@ -56,6 +61,8 @@ public District toModel() { .sidoCode(getSidoCode()) .sidoName(getSidoName()) .gunguName(getGunguName()) + .latitude(getLatitude()) + .longitude(getLongitude()) .sido(isSido()) .build(); } diff --git a/src/main/java/com/gamsa/activity/entity/InstituteJpaEntity.java b/src/main/java/com/gamsa/activity/entity/InstituteJpaEntity.java index 3dcb812..5ab41b0 100644 --- a/src/main/java/com/gamsa/activity/entity/InstituteJpaEntity.java +++ b/src/main/java/com/gamsa/activity/entity/InstituteJpaEntity.java @@ -2,21 +2,10 @@ import com.gamsa.activity.domain.Institute; import com.gamsa.common.entity.BaseEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; +import jakarta.persistence.*; +import lombok.*; + import java.math.BigDecimal; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; @Getter @Builder @@ -37,40 +26,40 @@ public class InstituteJpaEntity extends BaseEntity { @Column(name = "location", length = 255) private String location; - @Column(name = "latitude") + @Column(name = "latitude", precision = 10, scale = 8) private BigDecimal latitude; - @Column(name = "longitude") + @Column(name = "longitude", precision = 11, scale = 8) private BigDecimal longitude; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "sido_gungu_code", referencedColumnName = "sido_gungu_code") private DistrictJpaEntity sidoGungu; - @Column(name = "phone", length = 12) + @Column(name = "phone", length = 25) private String phone; public static InstituteJpaEntity from(Institute institute) { return InstituteJpaEntity.builder() - .instituteId(institute.getInstituteId()) - .name(institute.getName()) - .location(institute.getLocation()) - .latitude(institute.getLatitude()) - .longitude(institute.getLongitude()) - .sidoGungu(DistrictJpaEntity.from(institute.getSidoGungu())) - .phone(institute.getPhone()) - .build(); + .instituteId(institute.getInstituteId()) + .name(institute.getName()) + .location(institute.getLocation()) + .latitude(institute.getLatitude()) + .longitude(institute.getLongitude()) + .sidoGungu(DistrictJpaEntity.from(institute.getSidoGungu())) + .phone(institute.getPhone()) + .build(); } public Institute toModel() { return Institute.builder() - .instituteId(instituteId) - .name(name) - .location(location) - .latitude(latitude) - .longitude(longitude) - .sidoGungu(sidoGungu.toModel()) - .phone(phone) - .build(); + .instituteId(instituteId) + .name(name) + .location(location) + .latitude(latitude) + .longitude(longitude) + .sidoGungu(sidoGungu.toModel()) + .phone(phone) + .build(); } } diff --git a/src/main/java/com/gamsa/activity/repository/ActivityCustomRepository.java b/src/main/java/com/gamsa/activity/repository/ActivityCustomRepository.java index 862b484..ac0f9b7 100644 --- a/src/main/java/com/gamsa/activity/repository/ActivityCustomRepository.java +++ b/src/main/java/com/gamsa/activity/repository/ActivityCustomRepository.java @@ -1,6 +1,7 @@ package com.gamsa.activity.repository; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.entity.ActivityJpaEntity; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -9,4 +10,8 @@ public interface ActivityCustomRepository { Slice findSlice(ActivityFilterRequest request, Pageable pageable); + Slice findSliceDistanceOrder( + ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, + Pageable pageable); } diff --git a/src/main/java/com/gamsa/activity/repository/ActivityCustomRepositoryImpl.java b/src/main/java/com/gamsa/activity/repository/ActivityCustomRepositoryImpl.java index 003d7fd..1242d85 100644 --- a/src/main/java/com/gamsa/activity/repository/ActivityCustomRepositoryImpl.java +++ b/src/main/java/com/gamsa/activity/repository/ActivityCustomRepositoryImpl.java @@ -3,14 +3,19 @@ import static com.gamsa.activity.entity.QActivityJpaEntity.activityJpaEntity; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.entity.ActivityJpaEntity; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.NumberTemplate; import com.querydsl.core.types.dsl.PathBuilder; import com.querydsl.jpa.impl.JPAQueryFactory; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -37,6 +42,45 @@ public Slice findSlice(ActivityFilterRequest request, Pageabl return checkLastPage(pageable, results); } + @Override + public Slice findSliceDistanceOrder( + ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, + Pageable pageable) { + + final double EARTH_RADIUS_KM = 6371.0; // 지구 반지름 (km) + final BigDecimal latitude = distanceOrderRequest.getLatitude(); + final BigDecimal longitude = distanceOrderRequest.getLongitude(); + final int distanceKm = distanceOrderRequest.getDistanceKm(); + + BooleanBuilder filterBuilder = ActivityFilterBuilder.createFilter(filterRequest); + + // 하버사인 공식 구현 + NumberTemplate distanceExpression = Expressions.numberTemplate(Double.class, + "({0} * acos(cos(radians({1})) * cos(radians({2})) * cos(radians({3}) - radians({4})) + sin(radians({1})) * sin(radians({2}))))", + EARTH_RADIUS_KM, + latitude, + activityJpaEntity.latitude, + longitude, + activityJpaEntity.longitude + ); + + List results = jpaQueryFactory + .select(activityJpaEntity, distanceExpression.as("distance")) + .from(activityJpaEntity) + .where(filterBuilder.and(distanceExpression.loe(distanceKm))) + .orderBy(distanceExpression.asc()) + .orderBy(activityJpaEntity.actId.asc()) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize() + 1) + .fetch() + .stream() + .map(v -> v.get(activityJpaEntity)) + .collect(Collectors.toList()); + + return checkLastPage(pageable, results); + } + // 무한스크롤 처리 private Slice checkLastPage(Pageable pageable, List results) { diff --git a/src/main/java/com/gamsa/activity/repository/ActivityFilterBuilder.java b/src/main/java/com/gamsa/activity/repository/ActivityFilterBuilder.java index c9b83e9..33f6bc2 100644 --- a/src/main/java/com/gamsa/activity/repository/ActivityFilterBuilder.java +++ b/src/main/java/com/gamsa/activity/repository/ActivityFilterBuilder.java @@ -17,6 +17,7 @@ public static BooleanBuilder createFilter(ActivityFilterRequest request) { eqSidoCode(filterBuilder, request.getSidoCode()); isTeenPossibleOnly(filterBuilder, request.isTeenPossibleOnly()); isDeadlineEndOnly(filterBuilder, request.isBeforeDeadlineOnly()); + containsKeyword(filterBuilder, request.getKeyword()); return filterBuilder; } @@ -50,4 +51,10 @@ public static void isDeadlineEndOnly(BooleanBuilder filterBuilder, boolean befor filterBuilder.and(activityJpaEntity.noticeEndDate.after(LocalDateTime.now())); } } + + public static void containsKeyword(BooleanBuilder filterBuilder, String keyword) { + if (keyword != null) { + filterBuilder.and(activityJpaEntity.actTitle.contains(keyword)); + } + } } diff --git a/src/main/java/com/gamsa/activity/repository/ActivityRepository.java b/src/main/java/com/gamsa/activity/repository/ActivityRepository.java index ad9e60e..e722e24 100644 --- a/src/main/java/com/gamsa/activity/repository/ActivityRepository.java +++ b/src/main/java/com/gamsa/activity/repository/ActivityRepository.java @@ -2,6 +2,7 @@ import com.gamsa.activity.domain.Activity; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import java.util.Optional; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; @@ -10,7 +11,12 @@ public interface ActivityRepository { void save(Activity activity); - Slice findSlice(ActivityFilterRequest request, Pageable pageable); + Slice findSlice(ActivityFilterRequest filterRequest, Pageable pageable); + + Slice findSliceDistanceOrder( + ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, + Pageable pageable); Optional findById(Long activityId); } diff --git a/src/main/java/com/gamsa/activity/repository/ActivityRepositoryImpl.java b/src/main/java/com/gamsa/activity/repository/ActivityRepositoryImpl.java index b2ec5f1..0121f7e 100644 --- a/src/main/java/com/gamsa/activity/repository/ActivityRepositoryImpl.java +++ b/src/main/java/com/gamsa/activity/repository/ActivityRepositoryImpl.java @@ -2,6 +2,7 @@ import com.gamsa.activity.domain.Activity; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.entity.ActivityJpaEntity; import java.util.Optional; import lombok.RequiredArgsConstructor; @@ -26,6 +27,16 @@ public Slice findSlice(ActivityFilterRequest request, Pageable pageabl .map(ActivityJpaEntity::toModel); } + @Override + public Slice findSliceDistanceOrder( + ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, + Pageable pageable) { + return activityJpaRepository.findSliceDistanceOrder(filterRequest, distanceOrderRequest, + pageable) + .map(ActivityJpaEntity::toModel); + } + @Override public Optional findById(Long activityId) { return activityJpaRepository.findById(activityId) diff --git a/src/main/java/com/gamsa/activity/repository/DistrictJpaRepository.java b/src/main/java/com/gamsa/activity/repository/DistrictJpaRepository.java index 8120bae..9b5cfd3 100644 --- a/src/main/java/com/gamsa/activity/repository/DistrictJpaRepository.java +++ b/src/main/java/com/gamsa/activity/repository/DistrictJpaRepository.java @@ -1,9 +1,10 @@ package com.gamsa.activity.repository; import com.gamsa.activity.entity.DistrictJpaEntity; +import org.springframework.data.jpa.repository.JpaRepository; + import java.util.List; import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; public interface DistrictJpaRepository extends JpaRepository { diff --git a/src/main/java/com/gamsa/activity/service/ActivityService.java b/src/main/java/com/gamsa/activity/service/ActivityService.java index 5d197b6..050ca97 100644 --- a/src/main/java/com/gamsa/activity/service/ActivityService.java +++ b/src/main/java/com/gamsa/activity/service/ActivityService.java @@ -6,54 +6,48 @@ import com.gamsa.activity.domain.Institute; import com.gamsa.activity.dto.ActivityDetailResponse; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.dto.ActivityFindSliceResponse; import com.gamsa.activity.dto.ActivitySaveRequest; import com.gamsa.activity.exception.ActivityException; import com.gamsa.activity.repository.ActivityRepository; -import com.gamsa.activity.repository.DistrictRepository; -import com.gamsa.activity.repository.InstituteRepository; +import com.gamsa.review.domain.Question; import com.gamsa.review.dto.QuestionResponse; import com.gamsa.review.service.QuestionService; import com.gamsa.review.service.ReviewService; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; - @RequiredArgsConstructor @Service public class ActivityService { private final ActivityRepository activityRepository; - private final InstituteRepository instituteRepository; - private final DistrictRepository districtRepository; private final QuestionService questionService; private final ReviewService reviewService; - public void save(ActivitySaveRequest saveRequest) { - // 중복 여부 확인 - activityRepository.findById(saveRequest.getActId()) - .ifPresent(activity -> { - throw new ActivityException(ActivityErrorCode.ACTIVITY_ALREADY_EXISTS); - }); - // 기관 존재 확인 - Institute institute = instituteRepository.findById(saveRequest.getInstituteId()) - .orElseThrow(() -> new ActivityException(ActivityErrorCode.INSTITUTE_NOT_EXISTS)); + public void save(ActivitySaveRequest saveRequest, Institute institute, District district) { + activityRepository.save(saveRequest.toModel(institute, district)); + } - // 시도, 군구 존재 확인 - District sidoGungu = districtRepository.findBySidoGunguCode(saveRequest.getSidoGunguCode()) - .orElseThrow(() -> new ActivityException(ActivityErrorCode.DISTRICT_NOT_EXISTS)); + public Slice findSlice(ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, + Pageable pageable) { - activityRepository.save(saveRequest.toModel(institute, sidoGungu)); - } + Slice activities; + // 가까운순 정렬 + if (pageable.getSort().toString().contains("distance")) { + activities = activityRepository + .findSliceDistanceOrder(filterRequest, distanceOrderRequest, pageable); + } else { + activities = activityRepository.findSlice(filterRequest, pageable); + } - public Slice findSlice(ActivityFilterRequest request, - Pageable pageable) { - Slice activities = activityRepository.findSlice(request, pageable); return activities.map(ActivityFindSliceResponse::from); } @@ -62,10 +56,10 @@ public ActivityDetailResponse findById(Long activityId) { .orElseThrow(() -> new ActivityException(ActivityErrorCode.ACTIVITY_NOT_EXISTS)); - Map scores = new HashMap<>(); + Map scores = new HashMap<>(); long instituteId = activity.getInstitute().getInstituteId(); - questionService.findAllResponse().forEach(question -> { + questionService.findAll().forEach(question -> { BigDecimal score = reviewService.getAverageScore(instituteId, question.getQuestionId()); scores.put(question, score); }); diff --git a/src/main/java/com/gamsa/activity/service/DistrictService.java b/src/main/java/com/gamsa/activity/service/DistrictService.java index 11ce1f3..f4c1676 100644 --- a/src/main/java/com/gamsa/activity/service/DistrictService.java +++ b/src/main/java/com/gamsa/activity/service/DistrictService.java @@ -1,18 +1,18 @@ package com.gamsa.activity.service; -import com.gamsa.activity.constant.ActivityErrorCode; import com.gamsa.activity.domain.District; import com.gamsa.activity.dto.DistrictFindAllResponse; import com.gamsa.activity.dto.DistrictSaveRequest; -import com.gamsa.activity.exception.ActivityException; import com.gamsa.activity.repository.DistrictRepository; - -import java.math.BigDecimal; -import java.util.*; - import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + @RequiredArgsConstructor @Service public class DistrictService { @@ -20,10 +20,6 @@ public class DistrictService { private final DistrictRepository districtRepository; public void save(DistrictSaveRequest saveRequest) { - districtRepository.findBySidoGunguCode(saveRequest.getSidoGunguCode()) - .ifPresent(district -> { - throw new ActivityException(ActivityErrorCode.DISTRICT_ALREADY_EXISTS); - }); districtRepository.save(saveRequest.toModel()); } @@ -34,8 +30,8 @@ public void save(DistrictSaveRequest saveRequest) { */ public List findAllSido() { return districtRepository.findAllBysido(true).stream() - .map(DistrictFindAllResponse::from) - .toList(); + .map(DistrictFindAllResponse::from) + .toList(); } /** @@ -45,16 +41,30 @@ public List findAllSido() { */ public List findAllGungu() { return districtRepository.findAllBysido(false).stream() - .map(DistrictFindAllResponse::from) - .toList(); + .map(DistrictFindAllResponse::from) + .toList(); } public Map findCoordinates(int gunguCode) { - District find = districtRepository.findBySidoGunguCode(gunguCode) - .orElseThrow(NoSuchElementException::new); - Map coordinates = new HashMap<>(); - coordinates.put("longitude", find.getLongitude()); - coordinates.put("latitude", find.getLatitude()); - return coordinates; + if (gunguCode == 0) { + Map defaultCoordinates = new HashMap<>(); + defaultCoordinates.put("longitude", null); // 기본값으로 null 저장 + defaultCoordinates.put("latitude", null); + return defaultCoordinates; + } + + return districtRepository.findBySidoGunguCode(gunguCode) + .map(district -> { + Map coordinates = new HashMap<>(); + coordinates.put("longitude", district.getLongitude()); + coordinates.put("latitude", district.getLatitude()); + return coordinates; + }) + .orElseThrow(() -> new NoSuchElementException("District not found for gunguCode: " + gunguCode)); + } + + public District findBySidoGunguCode(int gunguCode) { + return districtRepository.findBySidoGunguCode(gunguCode) + .orElseThrow(() -> new NoSuchElementException("District not found for gunguCode: " + gunguCode)); } } diff --git a/src/main/java/com/gamsa/activity/service/InstituteService.java b/src/main/java/com/gamsa/activity/service/InstituteService.java index e0f1779..f36ee01 100644 --- a/src/main/java/com/gamsa/activity/service/InstituteService.java +++ b/src/main/java/com/gamsa/activity/service/InstituteService.java @@ -2,13 +2,16 @@ import com.gamsa.activity.constant.ActivityErrorCode; import com.gamsa.activity.domain.District; +import com.gamsa.activity.domain.Institute; import com.gamsa.activity.dto.InstituteSaveRequest; import com.gamsa.activity.exception.ActivityException; import com.gamsa.activity.repository.DistrictRepository; import com.gamsa.activity.repository.InstituteRepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +@Slf4j @RequiredArgsConstructor @Service public class InstituteService { @@ -18,17 +21,21 @@ public class InstituteService { public void save(InstituteSaveRequest saveRequest) { instituteRepository.findByName(saveRequest.getName()) - .ifPresent(institute -> { - throw new ActivityException(ActivityErrorCode.INSTITUTE_ALREADY_EXISTS); - }); + .ifPresentOrElse( + institute -> log.warn("Institute already exists: {}", saveRequest.getName()), + () -> { + District district = districtRepository.findBySidoGunguCode(saveRequest.getSidoGunguCode()) + .orElseThrow(() -> new ActivityException(ActivityErrorCode.DISTRICT_NOT_EXISTS)); - District district = districtRepository.findBySidoGunguCode(saveRequest.getSidoGunguCode()) - .orElseThrow(() -> new ActivityException(ActivityErrorCode.DISTRICT_NOT_EXISTS)); - - instituteRepository.save(saveRequest.toModel(district)); + log.info("Saving new institute for district: {}", district); + instituteRepository.save(saveRequest.toModel(district)); + } + ); } - public Long findByName(String name) { - return instituteRepository.findByName(name).orElseThrow(() -> new ActivityException(ActivityErrorCode.INSTITUTE_NOT_EXISTS)).getInstituteId(); + public Institute findByName(String name) { + log.info("Searching for institute by name: {}", name); + return instituteRepository.findByName(name) + .orElseThrow(() -> new ActivityException(ActivityErrorCode.INSTITUTE_NOT_EXISTS)); } } diff --git a/src/main/java/com/gamsa/dataupdate/AppConfig.java b/src/main/java/com/gamsa/dataupdate/AppConfig.java new file mode 100644 index 0000000..43171ae --- /dev/null +++ b/src/main/java/com/gamsa/dataupdate/AppConfig.java @@ -0,0 +1,14 @@ +package com.gamsa.dataupdate; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class AppConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gamsa/dataupdate/DataUpdateErrorCode.java b/src/main/java/com/gamsa/dataupdate/DataUpdateErrorCode.java index f24851f..f5e3f79 100644 --- a/src/main/java/com/gamsa/dataupdate/DataUpdateErrorCode.java +++ b/src/main/java/com/gamsa/dataupdate/DataUpdateErrorCode.java @@ -10,11 +10,6 @@ public enum DataUpdateErrorCode { OPENAPI_NOT_RESPOND(504, "Open API가 응답하지 않습니다."), OPENAPI_ERROR(504, "Open API의 반환 값을 처리할 수 없습니다."), - - // 카카오 API 오류 - KAKAOLOCALAPI_NOT_RESPOND(504, "카카오 API가 정상적으로 응답하지 않습니다."), - KAKAOLOCALAPT_ERROR(504, "카카오 API의 반환 값을 처리할 수 없습니다."), - // 내부 처리 오류 INVALID_CSV(500, "주어진 CSV 파일을 처리할 수 없습니다"), INVALID_FILE_SOURCE(500, "주어진 파일 경로가 올바르지 않습니다."); diff --git a/src/main/java/com/gamsa/dataupdate/DataUpdateScheduler.java b/src/main/java/com/gamsa/dataupdate/DataUpdateScheduler.java index 2ae1229..d6b11a8 100644 --- a/src/main/java/com/gamsa/dataupdate/DataUpdateScheduler.java +++ b/src/main/java/com/gamsa/dataupdate/DataUpdateScheduler.java @@ -1,26 +1,26 @@ package com.gamsa.dataupdate; import com.gamsa.dataupdate.service.ActivityDataUpdateService; +import java.time.LocalDate; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.time.LocalDate; - @Component @RequiredArgsConstructor public class DataUpdateScheduler { private final ActivityDataUpdateService activityDataUpdateService; - @Value("${spring.openapi.days}") + @Value("${openapi.days}") private int days; - @Scheduled(cron = "0 1 0 * * *") + @Scheduled(cron = "0 0 0 * * *") public void runActivityDataUpdate() { LocalDate today = LocalDate.now(); LocalDate endDate = today.plusDays(days); activityDataUpdateService.update(today, endDate); } + } diff --git a/src/main/java/com/gamsa/dataupdate/service/ActivityDataUpdateService.java b/src/main/java/com/gamsa/dataupdate/service/ActivityDataUpdateService.java index 27568d8..4bfda00 100644 --- a/src/main/java/com/gamsa/dataupdate/service/ActivityDataUpdateService.java +++ b/src/main/java/com/gamsa/dataupdate/service/ActivityDataUpdateService.java @@ -1,5 +1,7 @@ package com.gamsa.dataupdate.service; +import com.gamsa.activity.domain.District; +import com.gamsa.activity.domain.Institute; import com.gamsa.activity.dto.ActivitySaveRequest; import com.gamsa.activity.dto.InstituteSaveRequest; import com.gamsa.activity.service.ActivityService; @@ -7,42 +9,77 @@ import com.gamsa.activity.service.InstituteService; import com.gamsa.dataupdate.utils.ActivityDataUtils; import com.gamsa.dataupdate.utils.KakaoLocalUtils; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.List; +@Slf4j @RequiredArgsConstructor @Service public class ActivityDataUpdateService { private final ActivityService activityService; private final ActivityDataUtils activityDataUtils; + private final DistrictService districtService; + private final InstituteService instituteService; private final KakaoLocalUtils kakaoLocalUtils; - DistrictService districtService; - InstituteService instituteService; - public void update(LocalDate startDate, LocalDate endDate) { List programList = activityDataUtils.getVolunteerParticipationList(startDate, endDate); - List saveRequests = programList.stream() - .map(activityDataUtils::getInstituteApiResponse) - .map(instituteApiResponse -> { - return instituteApiResponse.toSaveRequest(kakaoLocalUtils.getCoordinateByAddress(instituteApiResponse.getLocation()) - .orElse(districtService.findCoordinates(instituteApiResponse.getSidoGunguCode()))); - }) - .toList(); + log.info("Fetched program list: {}", programList); + + programList.forEach(programNo -> { + try { + saveInstitute(programNo); + saveActivity(programNo); + } catch (Exception e) { + log.warn("Failed to process program number {}: {}", programNo, e.getMessage()); + } + }); + } + + @Transactional + public void saveInstitute(String programNo) { + try { + var instituteApiResponse = activityDataUtils.getInstituteApiResponse(programNo); + InstituteSaveRequest saveRequest = instituteApiResponse.toSaveRequest( + kakaoLocalUtils.getCoordinateByAddress(instituteApiResponse.getLocation()).orElse( + districtService.findCoordinates(instituteApiResponse.getSidoGunguCode()))); + instituteService.save(saveRequest); + } catch (Exception e) { + log.warn("Failed to save institute for program number {}: {}", programNo, e.getMessage()); + throw e; + } + } + + @Transactional + public void saveActivity(String programNo) { + try { + ActivitySaveRequest saveRequest = activityDataUtils.getVolunteerDetail(programNo); + + // Institute 조회 및 검증 + Institute institute = instituteService.findByName(saveRequest.getInstituteName()); + if (institute == null) { + log.warn("Institute with name {} not found for program number {}", saveRequest.getInstituteName(), programNo); + throw new IllegalArgumentException("Institute not found: " + saveRequest.getInstituteName()); + } - saveRequests.forEach(instituteService::save); + // District 조회 및 검증 + District district = districtService.findBySidoGunguCode(saveRequest.getSidoGunguCode()); + if (district == null) { + log.warn("District with sidoGunguCode {} not found for program number {}", saveRequest.getSidoGunguCode(), programNo); + throw new IllegalArgumentException("District not found: " + saveRequest.getSidoGunguCode()); + } - List activitySaveRequests = programList.stream() - .map(activityDataUtils::getVolunteerDetail) - .map(activityApiResponse -> { - return activityApiResponse.toSaveRequest(instituteService.findByName(activityApiResponse.getInstituteName())); - }) - .toList(); + activityService.save(saveRequest, institute, district); - activitySaveRequests.forEach(activityService::save); + } catch (Exception e) { + log.warn("Failed to save activity for program number {}: {}", programNo, e.getMessage()); + throw e; + } } } \ No newline at end of file diff --git a/src/main/java/com/gamsa/dataupdate/service/DistrictDataUpdateService.java b/src/main/java/com/gamsa/dataupdate/service/DistrictDataUpdateService.java index f0b6261..896cbb4 100644 --- a/src/main/java/com/gamsa/dataupdate/service/DistrictDataUpdateService.java +++ b/src/main/java/com/gamsa/dataupdate/service/DistrictDataUpdateService.java @@ -4,32 +4,37 @@ import com.gamsa.activity.service.DistrictService; import com.gamsa.dataupdate.DataUpdateErrorCode; import com.gamsa.dataupdate.DataUpdateException; +import com.gamsa.dataupdate.utils.InputStreamUtils; import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvValidationException; import jakarta.annotation.PostConstruct; import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; - import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; @Service -@Component @RequiredArgsConstructor public class DistrictDataUpdateService { private final DistrictService districtService; + private static final Logger logger = LoggerFactory.getLogger(DistrictDataUpdateService.class); - @Value("{data.csvpath}") + @Value("${data.csvpath}") private String csvPath; @PostConstruct public void DistrictInit() { - if (!isDataChanged()) loadDataFromCSV(csvPath); + logger.info("DistrictInit : path = {}", csvPath); + + loadDataFromCSV(csvPath); } private boolean isDataChanged() { @@ -41,17 +46,21 @@ private boolean isDataChanged() { @Transactional public void loadDataFromCSV(String csvPath) { try { - ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(csvPath).getFile()); + ClassPathResource resource = new ClassPathResource(csvPath); + InputStream inputStream = resource.getInputStream(); + File file = InputStreamUtils.convertInputStreamToFile(inputStream); FileReader fileReader = new FileReader(file); CSVReader csvReader = new CSVReader(fileReader); + logger.info("csvReader : {}", csvReader); + csvReader.readNext(); String[] nextRecord; + while ((nextRecord = csvReader.readNext()) != null) { DistrictSaveRequest districtSaveRequest = DistrictSaveRequest.builder() - .sidoGunguCode(Integer.getInteger(nextRecord[0])) - .sidoCode(Integer.getInteger(nextRecord[1])) + .sidoGunguCode(Integer.parseInt(nextRecord[0])) + .sidoCode(Integer.parseInt(nextRecord[1])) .sidoName(nextRecord[2]) .gunguName(nextRecord[3]) .latitude(new BigDecimal(nextRecord[4])) @@ -65,6 +74,8 @@ public void loadDataFromCSV(String csvPath) { throw new DataUpdateException(DataUpdateErrorCode.INVALID_FILE_SOURCE); } catch (CsvValidationException e) { throw new DataUpdateException(DataUpdateErrorCode.INVALID_CSV); + } catch (Exception e) { + logger.info("Error :{}", e.getMessage()); } } } diff --git a/src/main/java/com/gamsa/dataupdate/utils/ActivityDataUtils.java b/src/main/java/com/gamsa/dataupdate/utils/ActivityDataUtils.java index 8ff1018..5f634ec 100644 --- a/src/main/java/com/gamsa/dataupdate/utils/ActivityDataUtils.java +++ b/src/main/java/com/gamsa/dataupdate/utils/ActivityDataUtils.java @@ -3,35 +3,39 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.gamsa.activity.constant.Category; -import com.gamsa.activity.dto.ActivityApiResponse; +import com.gamsa.activity.dto.ActivitySaveRequest; import com.gamsa.activity.dto.InstituteApiResponse; import com.gamsa.dataupdate.DataUpdateErrorCode; import com.gamsa.dataupdate.DataUpdateException; -import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +@Slf4j @Component -@RequiredArgsConstructor public class ActivityDataUtils { @Value(value = "${openapi.key}") private String openapiKey; - @Value(value = "${openapi.url}") - private String openapiUrl; + private final String openapiUrl = "http://openapi.1365.go.kr/openapi/service/rest/VolunteerPartcptnService/"; @Value(value = "${openapi.volurl}") private String volUrl; - private final RestTemplate restTemplate = new RestTemplate(); + private final RestTemplate restTemplate; + + public ActivityDataUtils(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); @@ -61,10 +65,11 @@ public List getVolunteerParticipationList(LocalDate startDate, LocalDate ObjectMapper objectMapper = new ObjectMapper(); JsonNode rootNode = objectMapper.readTree(jsonContent); - JsonNode itemsNode = rootNode.path("response").path("body").path("items"); + JsonNode itemsNode = rootNode.path("response").path("body").path("items").path("item"); numOfItem = itemsNode.size(); + for (JsonNode item : itemsNode) { String programNo = item.path("progrmRegistNo").asText(); volunteerList.add(programNo); @@ -73,7 +78,7 @@ public List getVolunteerParticipationList(LocalDate startDate, LocalDate pageNo++; } catch (Exception e) { - System.out.println(e.getMessage()); + log.error(e.getMessage()); throw new DataUpdateException(DataUpdateErrorCode.OPENAPI_ERROR); } } else { @@ -93,6 +98,9 @@ public InstituteApiResponse getInstituteApiResponse(String programNo) { ResponseEntity response = restTemplate.getForEntity(uriBuilder.toUriString(), String.class); + log.info("Request URI: " + uriBuilder.toUriString()); + log.info("Response URI: " + response.getBody()); + if (response.getStatusCode().is2xxSuccessful()) { try { String jsonContent = response.getBody(); @@ -102,8 +110,9 @@ public InstituteApiResponse getInstituteApiResponse(String programNo) { JsonNode item = rootNode.path("response").path("body").path("items").path("item"); - System.out.println(item); - InstituteApiResponse instituteApiResponse = InstituteApiResponse.builder() + log.info(item.toString()); + + return InstituteApiResponse.builder() .name(item.path("mnnstNm").asText()) .location(item.path("postAdres").asText()) .sidoCode(item.path("sidoCd").asInt()) @@ -111,10 +120,8 @@ public InstituteApiResponse getInstituteApiResponse(String programNo) { .phone(item.path("telno").asText()) .build(); - return instituteApiResponse; - } catch (Exception e) { - System.out.println(e.getMessage()); + log.error(e.getMessage()); throw new DataUpdateException(DataUpdateErrorCode.OPENAPI_ERROR); } } else { @@ -122,7 +129,7 @@ public InstituteApiResponse getInstituteApiResponse(String programNo) { } } - public ActivityApiResponse getVolunteerDetail(String programNo) { + public ActivitySaveRequest getVolunteerDetail(String programNo) { String url = openapiUrl + "/getVltrPartcptnItem"; UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url) @@ -140,39 +147,38 @@ public ActivityApiResponse getVolunteerDetail(String programNo) { JsonNode item = rootNode.path("response").path("body").path("items").path("item"); - ActivityApiResponse activityApiResponse = ActivityApiResponse.builder() - .actId((long) item.path("progrmRegistNo").asInt()) + return ActivitySaveRequest.builder() + .actId(Long.parseLong(programNo)) .actTitle(item.path("progrmSj").asText()) .actLocation(item.path("actPlace").asText()) .description(item.path("progrmCn").asText()) - .noticeStartDate(LocalDate.parse(String.valueOf(item.path("noticeBgnde").asInt()), formatter).atStartOfDay()) - .noticeEndDate(LocalDate.parse(String.valueOf(item.path("noticeEndde").asInt()), formatter).atStartOfDay()) - .actStartDate(LocalDate.parse(String.valueOf(item.path("progrmBgnde").asInt()), formatter).atStartOfDay()) - .actEndDate(LocalDate.parse(String.valueOf(item.path("progrmBgnde").asInt()), formatter).atStartOfDay()) + .noticeStartDate(LocalDate.parse(item.path("noticeBgnde").asText(), formatter).atStartOfDay()) + .noticeEndDate(LocalDate.parse(item.path("noticeEndde").asText(), formatter).atStartOfDay()) + .actStartDate(LocalDate.parse(item.path("progrmBgnde").asText(), formatter).atStartOfDay()) + .actEndDate(LocalDate.parse(item.path("progrmBgnde").asText(), formatter).atStartOfDay()) .actStartTime(item.path("actBeginTm").asInt()) .actEndTime(item.path("actEndTm").asInt()) .recruitTotalNum(item.path("rcritNmpr").asInt()) - .adultPossible(item.path("adultPosblAt").asText() == "Y" ? true : false) - .teenPossible(item.path("yngbgsPosblAt").asText() == "Y" ? true : false) - .groupPossible(item.path("grpPosblAt").asText() == "Y" ? true : false) - .actWeek(item.path("actWkdy").asInt()) + .actLocation(item.path("areaAddress1").asText()) + .latitude(new BigDecimal(item.path("areaLalo1").asText().split(",")[0])) + .longitude(new BigDecimal(item.path("areaLalo1").asText().split(",")[1])) + .adultPossible(item.path("adultPosblAt").asText("").equals("Y")) + .teenPossible(item.path("yngbgsPosblAt").asText("").equals("Y")) + .groupPossible(item.path("grpPosblAt").asText("").equals("Y")).actWeek(item.path("actWkdy").asInt()) .actManager(item.path("nanmmbyNmAdmn").asText()) .actPhone(item.path("telno").asText()) .url(volUrl + item.path("progrmRegistNo").asText()) - .instituteName(item.path("mnnstNm").asText()) .category(getCategory(item.path("srvcClCode").asText())) + .instituteName(item.path("mnnstNm").asText()) .sidoGunguCode(item.path("gugunCd").asInt()) - .build(); - return activityApiResponse; - } catch (Exception e) { - System.out.println(e.getMessage()); + log.error(e.getMessage()); throw new DataUpdateException(DataUpdateErrorCode.OPENAPI_ERROR); } } else { - System.out.println("Error: " + response.getStatusCode()); + log.error("Error: " + response.getStatusCode()); throw new DataUpdateException(DataUpdateErrorCode.OPENAPI_NOT_RESPOND); } } diff --git a/src/main/java/com/gamsa/dataupdate/utils/InputStreamUtils.java b/src/main/java/com/gamsa/dataupdate/utils/InputStreamUtils.java new file mode 100644 index 0000000..a4aada0 --- /dev/null +++ b/src/main/java/com/gamsa/dataupdate/utils/InputStreamUtils.java @@ -0,0 +1,32 @@ +package com.gamsa.dataupdate.utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class InputStreamUtils { + + public static File convertInputStreamToFile(InputStream inputStream) throws IOException { + + File tempFile = File.createTempFile(String.valueOf(inputStream.hashCode()), ".tmp"); + tempFile.deleteOnExit(); + + copyInputStreamToFile(inputStream, tempFile); + + return tempFile; + } + + private static void copyInputStreamToFile(InputStream inputStream, File file) { + try (FileOutputStream outputStream = new FileOutputStream(file)) { + int read; + byte[] bytes = new byte[1024]; + + while ((read = inputStream.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/gamsa/dataupdate/utils/KakaoLocalUtils.java b/src/main/java/com/gamsa/dataupdate/utils/KakaoLocalUtils.java index ca42e83..a963182 100644 --- a/src/main/java/com/gamsa/dataupdate/utils/KakaoLocalUtils.java +++ b/src/main/java/com/gamsa/dataupdate/utils/KakaoLocalUtils.java @@ -1,5 +1,6 @@ package com.gamsa.dataupdate.utils; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -7,6 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; import java.math.BigDecimal; import java.util.HashMap; @@ -14,17 +16,26 @@ import java.util.Map; import java.util.Optional; +@Slf4j @Component public class KakaoLocalUtils { @Value("${kakao.localkey}") private String kakaoKey; - private final RestTemplate restTemplate = new RestTemplate(); + private final RestTemplate restTemplate; + + public KakaoLocalUtils(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } public Optional> getCoordinateByAddress(String address) { // 요청 URL 생성 - String url = "https://dapi.kakao.com/v2/local/search/address.json?query=" + address; + String url = UriComponentsBuilder.fromHttpUrl("https://dapi.kakao.com/v2/local/search/address.json") + .queryParam("query", address) + .build() + .toUriString(); + // 헤더 설정 HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "KakaoAK " + kakaoKey); @@ -34,26 +45,29 @@ public Optional> getCoordinateByAddress(String address) ResponseEntity response = restTemplate.exchange( url, HttpMethod.GET, entity, Map.class); - // 응답 처리 - if (response.getStatusCode().is2xxSuccessful()) { - Map result = response.getBody(); - if (result != null && result.containsKey("documents")) { - // 첫 번째 결과의 x, y 좌표 반환 - var documents = (List>) result.get("documents"); - if (!documents.isEmpty()) { - Map firstDoc = documents.getFirst(); - BigDecimal x = new BigDecimal(firstDoc.get("x").toString()); - BigDecimal y = new BigDecimal(firstDoc.get("y").toString()); - - Map coordinates = new HashMap<>(); - coordinates.put("longitude", x); - coordinates.put("latitude", y); - return Optional.of(coordinates); + try { + // 응답 처리 + if (response.getStatusCode().is2xxSuccessful()) { + + Map result = response.getBody(); + if (result != null && result.containsKey("documents")) { + // 첫 번째 결과의 x, y 좌표 반환 + var documents = (List>) result.get("documents"); + if (!documents.isEmpty()) { + Map firstDoc = documents.getFirst(); + BigDecimal x = new BigDecimal(firstDoc.get("x").toString()); + BigDecimal y = new BigDecimal(firstDoc.get("y").toString()); + + Map coordinates = new HashMap<>(); + coordinates.put("longitude", x); + coordinates.put("latitude", y); + return Optional.of(coordinates); + } } } + } catch (Exception e) { + log.error("API 요청 실패: " + response.getStatusCode() + e.getMessage()); } - - System.out.println("API 요청 실패: " + response.getStatusCode()); return Optional.empty(); } } diff --git a/src/main/java/com/gamsa/history/dto/HistoryFindSliceResponse.java b/src/main/java/com/gamsa/history/dto/HistoryFindSliceResponse.java index 9b3c9de..eaeccf6 100644 --- a/src/main/java/com/gamsa/history/dto/HistoryFindSliceResponse.java +++ b/src/main/java/com/gamsa/history/dto/HistoryFindSliceResponse.java @@ -1,16 +1,12 @@ package com.gamsa.history.dto; -import com.gamsa.activity.dto.ActivityDetailResponse; +import com.gamsa.activity.dto.ActivityFindSliceResponse; import com.gamsa.history.constant.ActivityStatus; import com.gamsa.history.domain.History; -import com.gamsa.review.dto.QuestionResponse; import lombok.Builder; import lombok.Getter; import lombok.RequiredArgsConstructor; -import java.math.BigDecimal; -import java.util.Map; - @Getter @Builder @RequiredArgsConstructor @@ -18,17 +14,17 @@ public class HistoryFindSliceResponse { private final long historyId; private final long avatarId; - private final ActivityDetailResponse activity; + private final ActivityFindSliceResponse activity; private final ActivityStatus activityStatus; private final boolean reviewed; - public static HistoryFindSliceResponse from(History history, Map scores) { + public static HistoryFindSliceResponse from(History history) { return HistoryFindSliceResponse.builder() .historyId(history.getHistoryId()) .avatarId(history.getAvatar().getAvatarId()) .activityStatus(history.getActivityStatus()) .reviewed(history.isReviewed()) - .activity(ActivityDetailResponse.from(history.getActivity(), scores)) + .activity(ActivityFindSliceResponse.from(history.getActivity())) .build(); } } diff --git a/src/main/java/com/gamsa/history/service/HistoryService.java b/src/main/java/com/gamsa/history/service/HistoryService.java index 2c0bcf7..f6f4f97 100644 --- a/src/main/java/com/gamsa/history/service/HistoryService.java +++ b/src/main/java/com/gamsa/history/service/HistoryService.java @@ -8,18 +8,12 @@ import com.gamsa.history.dto.HistoryFindSliceResponse; import com.gamsa.history.dto.HistorySaveRequest; import com.gamsa.history.repository.HistoryRepository; -import com.gamsa.review.dto.QuestionResponse; -import com.gamsa.review.service.QuestionService; -import com.gamsa.review.service.ReviewService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; -import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Map; import java.util.NoSuchElementException; @RequiredArgsConstructor @@ -28,8 +22,6 @@ public class HistoryService { private final HistoryRepository historyRepository; private final AvatarRepository avatarRepository; private final ActivityRepository activityRepository; - private final QuestionService questionService; - private final ReviewService reviewService; public void save(HistorySaveRequest saveRequest, Long userId) { @@ -49,17 +41,7 @@ public Slice findSliceByAvatarId(Long userId, Pageable .findSliceByAvatarId(avatar.getAvatarId(), pageable); histories.forEach(this::checkDate); - return histories.map(history -> { - Map scores = new HashMap<>(); - long instituteId = history.getActivity().getInstitute().getInstituteId(); - - questionService.findAllResponse().forEach(question -> { - BigDecimal score = reviewService.getAverageScore(instituteId, question.getQuestionId()); - scores.put(question, score); - }); - - return HistoryFindSliceResponse.from(history, scores); - }); + return histories.map(HistoryFindSliceResponse::from); } public void delete(long historyId) { diff --git a/src/main/java/com/gamsa/review/controller/ReviewController.java b/src/main/java/com/gamsa/review/controller/ReviewController.java index d6646c8..1df238c 100644 --- a/src/main/java/com/gamsa/review/controller/ReviewController.java +++ b/src/main/java/com/gamsa/review/controller/ReviewController.java @@ -2,16 +2,16 @@ import com.gamsa.common.utils.ExtractUserIdFromJwt; +import com.gamsa.review.dto.ReviewResponse; import com.gamsa.review.dto.ReviewSaveRequest; import com.gamsa.review.service.ReviewService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RequiredArgsConstructor @RestController @@ -22,10 +22,16 @@ public class ReviewController { @PostMapping public ResponseEntity saveReview(@RequestBody ReviewSaveRequest saveRequest, - HttpServletRequest request) { + HttpServletRequest request) { Long userId = ExtractUserIdFromJwt.extract(request); reviewService.saveReview(userId, saveRequest); return new ResponseEntity<>(HttpStatus.CREATED); } + + @GetMapping("{history-id}") + public List getAllReviews(@PathVariable("history-id") Long historyId) { + + return reviewService.getReview(historyId); + } } diff --git a/src/main/java/com/gamsa/review/dto/QuestionResponse.java b/src/main/java/com/gamsa/review/dto/QuestionResponse.java index a56fb82..e355fd5 100644 --- a/src/main/java/com/gamsa/review/dto/QuestionResponse.java +++ b/src/main/java/com/gamsa/review/dto/QuestionResponse.java @@ -13,8 +13,8 @@ public class QuestionResponse { public static QuestionResponse from(Question question) { return QuestionResponse.builder() - .questionId(question.getQuestionId()) - .content(question.getContent()) - .build(); + .questionId(question.getQuestionId()) + .content(question.getContent()) + .build(); } } diff --git a/src/main/java/com/gamsa/review/repository/AnswerRepositoryImpl.java b/src/main/java/com/gamsa/review/repository/AnswerRepositoryImpl.java new file mode 100644 index 0000000..140d703 --- /dev/null +++ b/src/main/java/com/gamsa/review/repository/AnswerRepositoryImpl.java @@ -0,0 +1,17 @@ +package com.gamsa.review.repository; + +import com.gamsa.review.domain.Answer; +import com.gamsa.review.entity.AnswerJpaEntity; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@RequiredArgsConstructor +@Repository +public class AnswerRepositoryImpl implements AnswerRepository { + private final AnswerJpaRepository answerJpaRepository; + + @Override + public void save(Answer answer) { + answerJpaRepository.save(AnswerJpaEntity.from(answer)); + } +} diff --git a/src/main/java/com/gamsa/review/repository/ReviewJpaRepository.java b/src/main/java/com/gamsa/review/repository/ReviewJpaRepository.java index a3b0bb2..ac0e8d7 100644 --- a/src/main/java/com/gamsa/review/repository/ReviewJpaRepository.java +++ b/src/main/java/com/gamsa/review/repository/ReviewJpaRepository.java @@ -4,8 +4,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; +import java.util.Optional; public interface ReviewJpaRepository extends JpaRepository { - List findByInstituteInstituteIdAndAnswersQuestionQuestionId(Long instituteId, Long questionId); + List findByInstituteInstituteIdAndAnswersQuestionQuestionId(Long instituteId, int questionId); + Optional findByHistoryHistoryId(long historyHistoryId); } diff --git a/src/main/java/com/gamsa/review/repository/ReviewRepository.java b/src/main/java/com/gamsa/review/repository/ReviewRepository.java index f3e2c88..cf8e495 100644 --- a/src/main/java/com/gamsa/review/repository/ReviewRepository.java +++ b/src/main/java/com/gamsa/review/repository/ReviewRepository.java @@ -3,10 +3,13 @@ import com.gamsa.review.domain.Review; import java.util.List; +import java.util.Optional; public interface ReviewRepository { void save(Review review); - List findReviews(Long instituteId, Long questionId); + List findReviews(Long instituteId, int questionId); + + Optional findHistoryReview(Long historyId); } diff --git a/src/main/java/com/gamsa/review/repository/ReviewRepositoryImpl.java b/src/main/java/com/gamsa/review/repository/ReviewRepositoryImpl.java index 734552e..6b3344e 100644 --- a/src/main/java/com/gamsa/review/repository/ReviewRepositoryImpl.java +++ b/src/main/java/com/gamsa/review/repository/ReviewRepositoryImpl.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @RequiredArgsConstructor @Repository @@ -18,9 +19,14 @@ public void save(Review review) { } @Override - public List findReviews(Long instituteId, Long questionId) { - return reviewJpaRepository.findByInstituteInstituteIdAndAnswersQuestionQuestionId(instituteId, questionId).stream().map(ReviewJpaEntity::toModel).toList(); + public List findReviews(Long instituteId, int questionId) { + return reviewJpaRepository.findByInstituteInstituteIdAndAnswersQuestionQuestionId(instituteId, questionId).stream() + .map(ReviewJpaEntity::toModel).toList(); } + @Override + public Optional findHistoryReview(Long historyId) { + return reviewJpaRepository.findByHistoryHistoryId(historyId).map(ReviewJpaEntity::toModel); + } } diff --git a/src/main/java/com/gamsa/review/service/QuestionService.java b/src/main/java/com/gamsa/review/service/QuestionService.java index a9ccda6..c14fb70 100644 --- a/src/main/java/com/gamsa/review/service/QuestionService.java +++ b/src/main/java/com/gamsa/review/service/QuestionService.java @@ -1,11 +1,13 @@ package com.gamsa.review.service; +import com.gamsa.review.domain.Question; import com.gamsa.review.dto.QuestionResponse; import com.gamsa.review.repository.QuestionRepository; -import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @RequiredArgsConstructor @Service public class QuestionService { @@ -14,8 +16,11 @@ public class QuestionService { public List findAllResponse() { return questionRepository.findAllQuestion().stream() - .map(QuestionResponse::from) - .toList(); + .map(QuestionResponse::from) + .toList(); } + public List findAll() { + return questionRepository.findAllQuestion(); + } } diff --git a/src/main/java/com/gamsa/review/service/ReviewService.java b/src/main/java/com/gamsa/review/service/ReviewService.java index c8e6501..26b315a 100644 --- a/src/main/java/com/gamsa/review/service/ReviewService.java +++ b/src/main/java/com/gamsa/review/service/ReviewService.java @@ -7,6 +7,7 @@ import com.gamsa.review.domain.Answer; import com.gamsa.review.domain.Question; import com.gamsa.review.domain.Review; +import com.gamsa.review.dto.ReviewResponse; import com.gamsa.review.dto.ReviewSaveRequest; import com.gamsa.review.repository.AnswerRepository; import com.gamsa.review.repository.QuestionRepository; @@ -72,7 +73,7 @@ public void saveReview(Long userId, ReviewSaveRequest saveRequest) { answers.forEach(answerRepository::save); } - public BigDecimal getAverageScore(long instituteId, long questionId) { + public BigDecimal getAverageScore(long instituteId, int questionId) { OptionalDouble averageScore = reviewRepository.findReviews(instituteId, questionId) .stream() .flatMap(review -> review.getAnswers().stream()) @@ -86,4 +87,12 @@ public BigDecimal getAverageScore(long instituteId, long questionId) { return BigDecimal.ZERO; } } + + public List getReview(long historyId) { + + return reviewRepository.findHistoryReview(historyId) + .orElseThrow(NoSuchElementException::new) + .getAnswers().stream().map(answer -> ReviewResponse.from(answer.getQuestion(), new BigDecimal(answer.getScore()))) + .toList(); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 4b7f737..562a0a9 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -16,6 +16,9 @@ spring: jwt: secret: kghobnakghwoigabsdlkbghaoigqhegowebnhlkwehgaoiwehtoaweqnbzoiwnyzbvwow expiration-time: 86400000 + config: + import: + - application-data.yml logging: level: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 6f7cd83..99e5b99 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -3,6 +3,7 @@ spring: import: - application-jwt.yml - application-prod-db.yml + - application-data.yml logging: level: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e2c4134..202f78a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,17 +3,3 @@ spring: name: gamja-bongsa profiles: active: dev - -kakao: - user-info-url: https://kapi.kakao.com/v2/user/me - localkey: - -data: - csvpath: "district_and_coordinate_kr.csv" - -openapi: - key: - url: "http://openapi.1365.go.kr/openapi/service/rest/VolunteerPartcptnService/" - volurl: "https://www.1365.go.kr/vols/1572247904127/partcptn/timeCptn.do?type=show&progrmRegistNo=" - days: 7 - diff --git a/src/main/resources/district_and_coordinate_kr.csv b/src/main/resources/district_and_coordinate_kr.csv index e00fee1..0693937 100644 --- a/src/main/resources/district_and_coordinate_kr.csv +++ b/src/main/resources/district_and_coordinate_kr.csv @@ -1,41 +1,11 @@ sidoGunguCode,sidoCode,sidoName,gunguName,latitude,longitude,sido 3000000,6110000,서울특별시,종로구,37.59491732,126.9773213,FALSE -3410000,6270000,대구광역시,중구,37.56014356,126.9959681,FALSE -3650000,6300000,대전광역시,중구,37.56014356,126.9959681,FALSE -3250000,6260000,부산광역시,중구,37.56014356,126.9959681,FALSE 3010000,6110000,서울특별시,중구,37.56014356,126.9959681,FALSE -3690000,6310000,울산광역시,중구,37.56014356,126.9959681,FALSE -3490000,6280000,인천광역시,중구,37.56014356,126.9959681,FALSE -3410000,6270000,대구광역시,중구,35.10547776,129.0315402,FALSE -3650000,6300000,대전광역시,중구,35.10547776,129.0315402,FALSE 3250000,6260000,부산광역시,중구,35.10547776,129.0315402,FALSE -3010000,6110000,서울특별시,중구,35.10547776,129.0315402,FALSE -3690000,6310000,울산광역시,중구,35.10547776,129.0315402,FALSE -3490000,6280000,인천광역시,중구,35.10547776,129.0315402,FALSE 3410000,6270000,대구광역시,중구,35.86653529,128.5936058,FALSE -3650000,6300000,대전광역시,중구,35.86653529,128.5936058,FALSE -3250000,6260000,부산광역시,중구,35.86653529,128.5936058,FALSE -3010000,6110000,서울특별시,중구,35.86653529,128.5936058,FALSE -3690000,6310000,울산광역시,중구,35.86653529,128.5936058,FALSE -3490000,6280000,인천광역시,중구,35.86653529,128.5936058,FALSE -3410000,6270000,대구광역시,중구,37.46753391,126.4805605,FALSE -3650000,6300000,대전광역시,중구,37.46753391,126.4805605,FALSE -3250000,6260000,부산광역시,중구,37.46753391,126.4805605,FALSE -3010000,6110000,서울특별시,중구,37.46753391,126.4805605,FALSE -3690000,6310000,울산광역시,중구,37.46753391,126.4805605,FALSE 3490000,6280000,인천광역시,중구,37.46753391,126.4805605,FALSE -3410000,6270000,대구광역시,중구,36.28086015,127.4110573,FALSE 3650000,6300000,대전광역시,중구,36.28086015,127.4110573,FALSE -3250000,6260000,부산광역시,중구,36.28086015,127.4110573,FALSE -3010000,6110000,서울특별시,중구,36.28086015,127.4110573,FALSE -3690000,6310000,울산광역시,중구,36.28086015,127.4110573,FALSE -3490000,6280000,인천광역시,중구,36.28086015,127.4110573,FALSE -3410000,6270000,대구광역시,중구,35.57104934,129.3082429,FALSE -3650000,6300000,대전광역시,중구,35.57104934,129.3082429,FALSE -3250000,6260000,부산광역시,중구,35.57104934,129.3082429,FALSE -3010000,6110000,서울특별시,중구,35.57104934,129.3082429,FALSE 3690000,6310000,울산광역시,중구,35.57104934,129.3082429,FALSE -3490000,6280000,인천광역시,중구,35.57104934,129.3082429,FALSE 3020000,6110000,서울특별시,용산구,37.53138497,126.979907,FALSE 3030000,6110000,서울특별시,성동구,37.55102969,127.0410585,FALSE 3040000,6110000,서울특별시,광진구,37.54670608,127.0857435,FALSE @@ -49,10 +19,8 @@ 3120000,6110000,서울특별시,서대문구,37.57778531,126.9390631,FALSE 3130000,6110000,서울특별시,마포구,37.55931349,126.90827,FALSE 3140000,6110000,서울특별시,양천구,37.52478941,126.8554777,FALSE -3360000,6260000,부산광역시,강서구,37.56123543,126.822807,FALSE 3150000,6110000,서울특별시,강서구,37.56123543,126.822807,FALSE 3360000,6260000,부산광역시,강서구,35.13834787,128.8924006,FALSE -3150000,6110000,서울특별시,강서구,35.13834787,128.8924006,FALSE 3160000,6110000,서울특별시,구로구,37.49440543,126.8563006,FALSE 3170000,6110000,서울특별시,금천구,37.46056756,126.9008202,FALSE 3180000,6110000,서울특별시,영등포구,37.52230829,126.9101695,FALSE @@ -62,110 +30,28 @@ 3220000,6110000,서울특별시,강남구,37.49664389,127.0629852,FALSE 3230000,6110000,서울특별시,송파구,37.50561924,127.115295,FALSE 3240000,6110000,서울특별시,강동구,37.55045024,127.1470118,FALSE -3600000,6290000,광주광역시,서구,35.10383663,129.0149537,FALSE -3430000,6270000,대구광역시,서구,35.10383663,129.0149537,FALSE -3660000,6300000,대전광역시,서구,35.10383663,129.0149537,FALSE 3260000,6260000,부산광역시,서구,35.10383663,129.0149537,FALSE -3560000,6280000,인천광역시,서구,35.10383663,129.0149537,FALSE -3600000,6290000,광주광역시,서구,35.87500167,128.5496976,FALSE 3430000,6270000,대구광역시,서구,35.87500167,128.5496976,FALSE -3660000,6300000,대전광역시,서구,35.87500167,128.5496976,FALSE -3260000,6260000,부산광역시,서구,35.87500167,128.5496976,FALSE -3560000,6280000,인천광역시,서구,35.87500167,128.5496976,FALSE -3600000,6290000,광주광역시,서구,37.55780443,126.6563778,FALSE -3430000,6270000,대구광역시,서구,37.55780443,126.6563778,FALSE -3660000,6300000,대전광역시,서구,37.55780443,126.6563778,FALSE -3260000,6260000,부산광역시,서구,37.55780443,126.6563778,FALSE 3560000,6280000,인천광역시,서구,37.55780443,126.6563778,FALSE 3600000,6290000,광주광역시,서구,35.13569311,126.8507191,FALSE -3430000,6270000,대구광역시,서구,35.13569311,126.8507191,FALSE -3660000,6300000,대전광역시,서구,35.13569311,126.8507191,FALSE -3260000,6260000,부산광역시,서구,35.13569311,126.8507191,FALSE -3560000,6280000,인천광역시,서구,35.13569311,126.8507191,FALSE -3600000,6290000,광주광역시,서구,36.28023963,127.3451041,FALSE -3430000,6270000,대구광역시,서구,36.28023963,127.3451041,FALSE 3660000,6300000,대전광역시,서구,36.28023963,127.3451041,FALSE -3260000,6260000,부산광역시,서구,36.28023963,127.3451041,FALSE -3560000,6280000,인천광역시,서구,36.28023963,127.3451041,FALSE -3590000,6290000,광주광역시,동구,35.12918632,129.0445856,FALSE -3420000,6270000,대구광역시,동구,35.12918632,129.0445856,FALSE -3640000,6300000,대전광역시,동구,35.12918632,129.0445856,FALSE 3270000,6260000,부산광역시,동구,35.12918632,129.0445856,FALSE -3710000,6310000,울산광역시,동구,35.12918632,129.0445856,FALSE -3500000,6280000,인천광역시,동구,35.12918632,129.0445856,FALSE -3590000,6290000,광주광역시,동구,35.93442633,128.6856599,FALSE 3420000,6270000,대구광역시,동구,35.93442633,128.6856599,FALSE -3640000,6300000,대전광역시,동구,35.93442633,128.6856599,FALSE -3270000,6260000,부산광역시,동구,35.93442633,128.6856599,FALSE -3710000,6310000,울산광역시,동구,35.93442633,128.6856599,FALSE -3500000,6280000,인천광역시,동구,35.93442633,128.6856599,FALSE -3590000,6290000,광주광역시,동구,37.48298658,126.6397466,FALSE -3420000,6270000,대구광역시,동구,37.48298658,126.6397466,FALSE -3640000,6300000,대전광역시,동구,37.48298658,126.6397466,FALSE -3270000,6260000,부산광역시,동구,37.48298658,126.6397466,FALSE -3710000,6310000,울산광역시,동구,37.48298658,126.6397466,FALSE 3500000,6280000,인천광역시,동구,37.48298658,126.6397466,FALSE 3590000,6290000,광주광역시,동구,35.11738023,126.9494643,FALSE -3420000,6270000,대구광역시,동구,35.11738023,126.9494643,FALSE -3640000,6300000,대전광역시,동구,35.11738023,126.9494643,FALSE -3270000,6260000,부산광역시,동구,35.11738023,126.9494643,FALSE -3710000,6310000,울산광역시,동구,35.11738023,126.9494643,FALSE -3500000,6280000,인천광역시,동구,35.11738023,126.9494643,FALSE -3590000,6290000,광주광역시,동구,36.32392023,127.4750374,FALSE -3420000,6270000,대구광역시,동구,36.32392023,127.4750374,FALSE -3640000,6300000,대전광역시,동구,36.32392023,127.4750374,FALSE -3270000,6260000,부산광역시,동구,36.32392023,127.4750374,FALSE -3710000,6310000,울산광역시,동구,36.32392023,127.4750374,FALSE -3500000,6280000,인천광역시,동구,36.32392023,127.4750374,FALSE -3590000,6290000,광주광역시,동구,35.52557365,129.4260655,FALSE -3420000,6270000,대구광역시,동구,35.52557365,129.4260655,FALSE -3640000,6300000,대전광역시,동구,35.52557365,129.4260655,FALSE -3270000,6260000,부산광역시,동구,35.52557365,129.4260655,FALSE +3420000,6270000,대전광역시,동구,36.32392023,127.4750374,FALSE 3710000,6310000,울산광역시,동구,35.52557365,129.4260655,FALSE -3500000,6280000,인천광역시,동구,35.52557365,129.4260655,FALSE 3280000,6260000,부산광역시,영도구,35.07868795,129.0648096,FALSE 3290000,6260000,부산광역시,부산진구,35.16524411,129.0430603,FALSE 3300000,6260000,부산광역시,동래구,35.20621244,129.0792201,FALSE -3610000,6290000,광주광역시,남구,35.12613679,129.0940064,FALSE -3440000,6270000,대구광역시,남구,35.12613679,129.0940064,FALSE 3310000,6260000,부산광역시,남구,35.12613679,129.0940064,FALSE -3700000,6310000,울산광역시,남구,35.12613679,129.0940064,FALSE -3510000,6280000,인천광역시,남구,35.12613679,129.0940064,FALSE -3610000,6290000,광주광역시,남구,35.83517716,128.5853296,FALSE 3440000,6270000,대구광역시,남구,35.83517716,128.5853296,FALSE -3310000,6260000,부산광역시,남구,35.83517716,128.5853296,FALSE -3700000,6310000,울산광역시,남구,35.83517716,128.5853296,FALSE -3510000,6280000,인천광역시,남구,35.83517716,128.5853296,FALSE -3610000,6290000,광주광역시,남구,37.45259578,126.6646585,FALSE -3440000,6270000,대구광역시,남구,37.45259578,126.6646585,FALSE -3310000,6260000,부산광역시,남구,37.45259578,126.6646585,FALSE -3700000,6310000,울산광역시,남구,37.45259578,126.6646585,FALSE 3510000,6280000,인천광역시,미추홀구,37.45259578,126.6646585,FALSE 3610000,6290000,광주광역시,남구,35.09405825,126.8567181,FALSE -3440000,6270000,대구광역시,남구,35.09405825,126.8567181,FALSE -3310000,6260000,부산광역시,남구,35.09405825,126.8567181,FALSE -3700000,6310000,울산광역시,남구,35.09405825,126.8567181,FALSE -3510000,6280000,인천광역시,남구,35.09405825,126.8567181,FALSE -3610000,6290000,광주광역시,남구,35.51604996,129.3282023,FALSE -3440000,6270000,대구광역시,남구,35.51604996,129.3282023,FALSE -3310000,6260000,부산광역시,남구,35.51604996,129.3282023,FALSE 3700000,6310000,울산광역시,남구,35.51604996,129.3282023,FALSE -3510000,6280000,인천광역시,남구,35.51604996,129.3282023,FALSE -3620000,6290000,광주광역시,북구,35.22922961,129.0234398,FALSE -3450000,6270000,대구광역시,북구,35.22922961,129.0234398,FALSE 3320000,6260000,부산광역시,북구,35.22922961,129.0234398,FALSE -3720000,6310000,울산광역시,북구,35.22922961,129.0234398,FALSE -3620000,6290000,광주광역시,북구,35.92892237,128.5772044,FALSE 3450000,6270000,대구광역시,북구,35.92892237,128.5772044,FALSE -3320000,6260000,부산광역시,북구,35.92892237,128.5772044,FALSE -3720000,6310000,울산광역시,북구,35.92892237,128.5772044,FALSE 3620000,6290000,광주광역시,북구,35.19324611,126.9254865,FALSE -3450000,6270000,대구광역시,북구,35.19324611,126.9254865,FALSE -3320000,6260000,부산광역시,북구,35.19324611,126.9254865,FALSE -3720000,6310000,울산광역시,북구,35.19324611,126.9254865,FALSE -3620000,6290000,광주광역시,북구,35.61005392,129.3798105,FALSE -3450000,6270000,대구광역시,북구,35.61005392,129.3798105,FALSE -3320000,6260000,부산광역시,북구,35.61005392,129.3798105,FALSE 3720000,6310000,울산광역시,북구,35.61005392,129.3798105,FALSE 3330000,6260000,부산광역시,해운대구,35.19385339,129.1535934,FALSE 3340000,6260000,부산광역시,사하구,35.0893484,128.974349,FALSE @@ -187,27 +73,30 @@ 3670000,6300000,대전광역시,유성구,36.37679049,127.3332564,FALSE 3680000,6300000,대전광역시,대덕구,36.41217868,127.4401518,FALSE 3730000,6310000,울산광역시,울주군,35.54661673,129.1869255,FALSE -3750000,3740000,경기도,수원시 장안구,37.31396569,127.0034517,FALSE -3760000,3740000,경기도,수원시 권선구,37.26053016,126.9797438,FALSE -3770000,3740000,경기도,수원시 팔달구,37.27746363,127.0162387,FALSE -5610000,3740000,경기도,수원시 영통구,37.27499039,127.0566989,FALSE -3790000,3780000,경기도,성남시 수정구,37.43516624,127.1041452,FALSE -3800000,3780000,경기도,성남시 중원구,37.43343323,127.1639099,FALSE -3810000,3780000,경기도,성남시 분당구,37.37930157,127.106064,FALSE +3740000,6410000,경기도,수원시,37.31396569,127.0034517,FALSE +3750000,6410000,경기도,수원시 장안구,37.31396569,127.0034517,FALSE +3760000,6410000,경기도,수원시 권선구,37.26053016,126.9797438,FALSE +3770000,6410000,경기도,수원시 팔달구,37.27746363,127.0162387,FALSE +5610000,6410000,경기도,수원시 영통구,37.27499039,127.0566989,FALSE +3790000,6410000,경기도,성남시,37.42000600,127.12581800,FALSE +3790000,6410000,경기도,성남시 수정구,37.43516624,127.1041452,FALSE +3800000,6410000,경기도,성남시 중원구,37.43343323,127.1639099,FALSE +3810000,6410000,경기도,성남시 분당구,37.37930157,127.106064,FALSE 3820000,6410000,경기도,의정부시,37.73619211,127.0684231,FALSE 3830000,6410000,경기도,안양시,37.40413345,126.9113856,FALSE -3840000,3830000,경기도,안양시 만안구,37.40413345,126.9113856,FALSE -3850000,3830000,경기도,안양시 동안구,37.40039183,126.9555027,FALSE +3840000,6410000,경기도,안양시 만안구,37.40413345,126.9113856,FALSE +3850000,6410000,경기도,안양시 동안구,37.40039183,126.9555027,FALSE 3860000,6410000,경기도,부천시,37.50425833,126.7887109,FALSE 3900000,6410000,경기도,광명시,37.44515907,126.8647013,FALSE 3910000,6410000,경기도,평택시,37.01183071,126.9877007,FALSE 3920000,6410000,경기도,동두천시,37.91653761,127.0779127,FALSE -5550000,3930000,경기도,안산시 상록구,37.31600383,126.870815,FALSE -5560000,3930000,경기도,안산시 단원구,37.28192491,126.6940412,FALSE -3960000,3940000,경기도,고양시 일산구,37.67986514,126.7975582,FALSE -3950000,3940000,경기도,고양시 덕양구,37.65580987,126.8786321,FALSE -3960100,3940000,경기도,고양시 일산동구,37.67986514,126.7975582,FALSE -4100100,3940000,경기도,고양시 일산서구,37.68020512,126.7279835,FALSE +5550000,6410000,경기도,안산시 상록구,37.31600383,126.870815,FALSE +5560000,6410000,경기도,안산시 단원구,37.28192491,126.6940412,FALSE +3960000,6410000,경기도,고양시,37.65790200,126.83248100,FALSE +3960000,6410000,경기도,고양시 일산구,37.67986514,126.7975582,FALSE +3950000,6410000,경기도,고양시 덕양구,37.65580987,126.8786321,FALSE +3960100,6410000,경기도,고양시 일산동구,37.67986514,126.7975582,FALSE +4100100,6410000,경기도,고양시 일산서구,37.68020512,126.7279835,FALSE 3970000,6410000,경기도,과천시,37.43384529,127.0026795,FALSE 3980000,6410000,경기도,구리시,37.59922149,127.1312299,FALSE 3990000,6410000,경기도,남양주시,37.66252981,127.2436606,FALSE @@ -217,9 +106,9 @@ 4030000,6410000,경기도,의왕시,37.36238774,126.9896255,FALSE 4040000,6410000,경기도,하남시,37.52281418,127.2059438,FALSE 4050000,6410000,경기도,용인시,37.2033319,127.2529331,FALSE -5620000,4050000,경기도,용인시 처인구,37.2033319,127.2529331,FALSE -5630000,4050000,경기도,용인시 기흥구,37.26742665,127.1213215,FALSE -5640000,4050000,경기도,용인시 수지구,37.33344743,127.0715511,FALSE +5620000,6410000,경기도,용인시 처인구,37.2033319,127.2529331,FALSE +5630000,6410000,경기도,용인시 기흥구,37.26742665,127.1213215,FALSE +5640000,6410000,경기도,용인시 수지구,37.33344743,127.0715511,FALSE 4060000,6410000,경기도,파주시,37.85619198,126.8107502,FALSE 4070000,6410000,경기도,이천시,37.20977588,127.4810141,FALSE 4080000,6410000,경기도,안성시,37.03502705,127.3027223,FALSE @@ -233,31 +122,45 @@ 4160000,6410000,경기도,가평군,37.81843317,127.4501921,FALSE 4170000,6410000,경기도,양평군,37.51805585,127.5792645,FALSE 4181000,6530000,강원특별자치도,춘천시,37.88979679,127.7398684,FALSE +4180000,6530000,강원도,춘천시,37.88979679,127.7398684,FALSE 4191000,6530000,강원특별자치도,원주시,37.30822288,127.9295253,FALSE +4190000,6530000,강원도,원주시,37.30822288,127.9295253,FALSE 4201000,6530000,강원특별자치도,강릉시,37.70910197,128.8323789,FALSE +4200000,6530000,강원도,강릉시,37.70910197,128.8323789,FALSE 4211000,6530000,강원특별자치도,동해시,37.5066814,129.0555688,FALSE +4210000,6530000,강원도,동해시,37.5066814,129.0555688,FALSE 4221000,6530000,강원특별자치도,태백시,37.17231241,128.9800726,FALSE +4220000,6530000,강원도,태백시,37.17231241,128.9800726,FALSE 4231000,6530000,강원특별자치도,속초시,38.17603138,128.519541,FALSE +4230000,6530000,강원도,속초시,38.17603138,128.519541,FALSE 4241000,6530000,강원특별자치도,삼척시,37.27748089,129.12171,FALSE +4240000,6530000,강원도,삼척시,37.27748089,129.12171,FALSE 4251000,6530000,강원특별자치도,홍천군,37.74504907,128.0742609,FALSE +4250000,6530000,강원도,홍천군,37.74504907,128.0742609,FALSE 4261000,6530000,강원특별자치도,횡성군,37.50914207,128.0770674,FALSE +4260000,6530000,강원도,횡성군,37.50914207,128.0770674,FALSE 4271000,6530000,강원특별자치도,영월군,37.20411361,128.500296,FALSE +4270000,6530000,강원도,영월군,37.20411361,128.500296,FALSE 4281000,6530000,강원특별자치도,평창군,37.55683921,128.48259,FALSE +4280000,6530000,강원도,평창군,37.55683921,128.48259,FALSE 4291000,6530000,강원특별자치도,정선군,37.37868629,128.7390632,FALSE +4290000,6530000,강원도,정선군,37.37868629,128.7390632,FALSE 4301000,6530000,강원특별자치도,철원군,38.23908523,127.3989244,FALSE +4300000,6530000,강원도,철원군,38.23908523,127.3989244,FALSE 4311000,6530000,강원특별자치도,화천군,38.13842628,127.6851657,FALSE +4310000,6530000,강원도,화천군,38.13842628,127.6851657,FALSE 4321000,6530000,강원특별자치도,양구군,38.17560879,128.0002064,FALSE +4320000,6530000,강원도,양구군,38.17560879,128.0002064,FALSE 4331000,6530000,강원특별자치도,인제군,38.06460026,128.2647272,FALSE +4330000,6530000,강원도,인제군,38.06460026,128.2647272,FALSE 4341000,6530000,강원특별자치도,고성군,38.36275363,128.4111555,FALSE -5420000,6480000,경상남도,고성군,38.36275363,128.4111555,FALSE -4341000,6530000,강원특별자치도,고성군,35.01630447,128.2906632,FALSE +4340000,6530000,강원도,고성군,38.36275363,128.4111555,FALSE 5420000,6480000,경상남도,고성군,35.01630447,128.2906632,FALSE -4351000,6530000,강원특별자치도,양양군,38.00448634,128.5950086,FALSE 5720000,6430000,충청북도,청주시 상당구,36.59211242,127.5848802,FALSE -4370000,4360000,충청북도,청주시 상당구,36.59211242,127.5848802,FALSE +4370000,6430000,충청북도,청주시 상당구,36.59211242,127.5848802,FALSE 5725000,6430000,충청북도,청주시 서원구,36.54726305,127.4384007,FALSE 5730000,6430000,충청북도,청주시 흥덕구,36.64696076,127.3692749,FALSE -4380000,4360000,충청북도,청주시 흥덕구,36.64696076,127.3692749,FALSE +4380000,6430000,충청북도,청주시 흥덕구,36.64696076,127.3692749,FALSE 5735000,6430000,충청북도,청주시 청원구,36.72057891,127.4913176,FALSE 4390000,6430000,충청북도,충주시,37.01519694,127.8956623,FALSE 4400000,6430000,충청북도,제천시,37.05991183,128.1409593,FALSE @@ -270,8 +173,8 @@ 4470000,6430000,충청북도,음성군,36.97622261,127.6142068,FALSE 4480000,6430000,충청북도,단양군,36.99445276,128.3878416,FALSE 4490000,6440000,충청남도,천안시,36.76411722,127.2208946,FALSE -5650000,4490000,충청남도,천안시 동남구,36.76411722,127.2208946,FALSE -5660000,4490000,충청남도,천안시 서북구,36.89271067,127.1618094,FALSE +5650000,6440000,충청남도,천안시 동남구,36.76411722,127.2208946,FALSE +5660000,6440000,충청남도,천안시 서북구,36.89271067,127.1618094,FALSE 4500000,6440000,충청남도,공주시,36.47981976,127.0752191,FALSE 4510000,6440000,충청남도,보령시,36.34024523,126.594247,FALSE 4520000,6440000,충청남도,아산시,36.80731633,126.9800756,FALSE @@ -287,21 +190,37 @@ 4610000,6440000,충청남도,예산군,36.67062867,126.7843109,FALSE 4620000,6440000,충청남도,태안군,36.7036613,126.2809571,FALSE 4641000,6540000,전북특별자치도,전주시,35.79209428,127.1195036,FALSE -4651000,4641000,전북특별자치도,전주시 완산구,35.79209428,127.1195036,FALSE -4661000,4641000,전북특별자치도,전주시 덕진구,35.85870118,127.1129157,FALSE +4640000,6540000,전라북도,전주시,35.79209428,127.1195036,FALSE +4651000,6540000,전북특별자치도,전주시 완산구,35.79209428,127.1195036,FALSE +4650000,6540000,전라북도,전주시 완산구,35.79209428,127.1195036,FALSE +4661000,6540000,전북특별자치도,전주시 덕진구,35.85870118,127.1129157,FALSE +4660000,6540000,전라북도,전주시 덕진구,35.85870118,127.1129157,FALSE 4671000,6540000,전북특별자치도,군산시,35.95043894,126.7260152,FALSE +4670000,6540000,전라북도,군산시,35.95043894,126.7260152,FALSE 4681000,6540000,전북특별자치도,익산시,36.02310555,126.9895102,FALSE +4680000,6540000,전라북도,익산시,36.02310555,126.9895102,FALSE 4691000,6540000,전북특별자치도,정읍시,35.60262466,126.9058575,FALSE +4690000,6540000,전라북도,정읍시,35.60262466,126.9058575,FALSE 4701000,6540000,전북특별자치도,남원시,35.4225448,127.4418897,FALSE +4700000,6540000,전라북도,남원시,35.4225448,127.4418897,FALSE 4711000,6540000,전북특별자치도,김제시,35.80671644,126.8948857,FALSE +4710000,6540000,전라북도,김제시,35.80671644,126.8948857,FALSE 4721000,6540000,전북특별자치도,완주군,35.91861444,127.2151146,FALSE +4720000,6540000,전라북도,완주군,35.91861444,127.2151146,FALSE 4731000,6540000,전북특별자치도,진안군,35.82880745,127.4300354,FALSE +4730000,6540000,전라북도,진안군,35.82880745,127.4300354,FALSE 4741000,6540000,전북특별자치도,무주군,35.93936736,127.7129531,FALSE +4740000,6540000,전라북도,무주군,35.93936736,127.7129531,FALSE 4751000,6540000,전북특별자치도,장수군,35.65746098,127.5442641,FALSE +4750000,6540000,전라북도,장수군,35.65746098,127.5442641,FALSE 4761000,6540000,전북특별자치도,임실군,35.59820204,127.2366472,FALSE +4760000,6540000,전라북도,임실군,35.59820204,127.2366472,FALSE 4771000,6540000,전북특별자치도,순창군,35.4336343,127.090087,FALSE +4770000,6540000,전라북도,순창군,35.4336343,127.090087,FALSE 4781000,6540000,전북특별자치도,고창군,35.44816757,126.6160462,FALSE +4780000,6540000,전라북도,고창군,35.44816757,126.6160462,FALSE 4791000,6540000,전북특별자치도,부안군,35.6779229,126.6443774,FALSE +4790000,6540000,전라북도,부안군,35.6779229,126.6443774,FALSE 4800000,6460000,전라남도,목포시,34.80376416,126.3918353,FALSE 4810000,6460000,전라남도,여수시,34.69617175,127.6532031,FALSE 4820000,6460000,전라남도,순천시,34.99474506,127.3891627,FALSE @@ -324,8 +243,9 @@ 4990000,6460000,전라남도,완도군,34.29557933,126.7768069,FALSE 5000000,6460000,전라남도,진도군,34.43939638,126.2150578,FALSE 5010000,6460000,전라남도,신안군,34.81240654,126.048907,FALSE -5030000,5020000,경상북도,포항시 남구,35.95813526,129.4376545,FALSE -5040000,5020000,경상북도,포항시 북구,36.16507327,129.234009,FALSE +5020000,6470000,경상북도,포항시,35.95813526,129.4376545,FALSE +5030000,6470000,경상북도,포항시 남구,35.95813526,129.4376545,FALSE +5040000,6470000,경상북도,포항시 북구,36.16507327,129.234009,FALSE 5050000,6470000,경상북도,경주시,35.8266428,129.2359296,FALSE 5060000,6470000,경상북도,김천시,36.06042386,128.0777075,FALSE 5070000,6470000,경상북도,안동시,36.58024221,128.7800427,FALSE @@ -349,11 +269,12 @@ 5240000,6470000,경상북도,봉화군,36.93414016,128.9129004,FALSE 5250000,6470000,경상북도,울진군,36.90391313,129.3123186,FALSE 5260000,6470000,경상북도,울릉군,37.50194192,130.864243,FALSE -5670123,5670000,경상남도,창원시 의창구,35.30894896,128.6495884,FALSE -5670140,5670000,경상남도,창원시 성산구,35.19618568,128.6721044,FALSE -5670156,5670000,경상남도,창원시 마산합포구,35.13545806,128.4852558,FALSE -5670184,5670000,경상남도,창원시 마산회원구,35.23222659,128.5364332,FALSE -5670206,5670000,경상남도,창원시 진해구,35.12994945,128.7363008,FALSE +5670000,6480000,경상남도,창원시,35.30894896,128.6495884,FALSE +5670123,6480000,경상남도,창원시 의창구,35.30894896,128.6495884,FALSE +5670140,6480000,경상남도,창원시 성산구,35.19618568,128.6721044,FALSE +5670156,6480000,경상남도,창원시 마산합포구,35.13545806,128.4852558,FALSE +5670184,6480000,경상남도,창원시 마산회원구,35.23222659,128.5364332,FALSE +5670206,6480000,경상남도,창원시 진해구,35.12994945,128.7363008,FALSE 5310000,6480000,경상남도,진주시,35.20515765,128.1298011,FALSE 5330000,6480000,경상남도,통영시,34.82932843,128.3740775,FALSE 5340000,6480000,경상남도,사천시,35.04970341,128.0376963,FALSE @@ -370,10 +291,11 @@ 5460000,6480000,경상남도,함양군,35.55160171,127.7220411,FALSE 5470000,6480000,경상남도,거창군,35.73255219,127.9041696,FALSE 5480000,6480000,경상남도,합천군,35.57657745,128.1415437,FALSE -5490000,6490000,제주도,제주시,33.44220188,126.5292476,FALSE +5490000,6500000,제주도,제주시,33.44220188,126.5292476,FALSE 6510000,6500000,제주특별자치도,제주시,33.44220188,126.5292476,FALSE -5500000,6490000,제주도,서귀포시,33.32504027,126.5810857,FALSE +5500000,6500000,제주도,서귀포시,33.32504027,126.5810857,FALSE 6520000,6500000,제주특별자치도,서귀포시,33.32504027,126.5810857,FALSE +5690000,5690000,세종특별자치시,세종특별자치시,36.56072897,127.258722,FALSE 6530000,6530000,강원특별자치도,강원특별자치도,37.71904264,128.3008969,TRUE 6410000,6410000,경기도,경기도,37.53434923,127.1810501,TRUE 6480000,6480000,경상남도,경상남도,35.32449891,128.2611748,TRUE @@ -388,54 +310,6 @@ 6280000,6280000,인천광역시,인천광역시,37.58457102,126.3755151,TRUE 6460000,6460000,전라남도,전라남도,34.87817002,126.9052332,TRUE 6540000,6540000,전북특별자치도,전북특별자치도,35.71581062,127.1427384,TRUE -6490000,6490000,제주도,제주도,33.38699923,126.5538395,TRUE 6500000,6500000,제주특별자치도,제주특별자치도,33.38699923,126.5538395,TRUE 6440000,6440000,충청남도,충청남도,36.52940199,126.8497393,TRUE -6430000,6430000,충청북도,충청북도,36.73877678,127.8313457,TRUE -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -,,,,,, -5710000,6430000,충청북도,청주시,,, -6430140,6430000,충청북도,증평출장소,,, -4410000,6430000,충청북도,청원군,,, +6430000,6430000,충청북도,충청북도,36.73877678,127.8313457,TRUE \ No newline at end of file diff --git a/src/test/java/com/gamsa/activity/entity/ActivityJpaEntityTest.java b/src/test/java/com/gamsa/activity/entity/ActivityJpaEntityTest.java index 3dfe74a..5baabaf 100644 --- a/src/test/java/com/gamsa/activity/entity/ActivityJpaEntityTest.java +++ b/src/test/java/com/gamsa/activity/entity/ActivityJpaEntityTest.java @@ -1,14 +1,15 @@ package com.gamsa.activity.entity; -import static org.assertj.core.api.Assertions.assertThat; - import com.gamsa.activity.constant.Category; import com.gamsa.activity.domain.Activity; import com.gamsa.activity.domain.District; import com.gamsa.activity.domain.Institute; +import org.junit.jupiter.api.Test; + import java.math.BigDecimal; import java.time.LocalDateTime; -import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; class ActivityJpaEntityTest { @@ -16,46 +17,46 @@ class ActivityJpaEntityTest { void 도메인모델에서_JPA엔티티로_변환() { // given District district = District.builder() - .sidoCode(1234) - .sidoGunguCode(8888) - .sidoName("서울특별시") - .gunguName("강남구") - .sido(false) - .build(); + .sidoCode(1234) + .sidoGunguCode(8888) + .sidoName("서울특별시") + .gunguName("강남구") + .sido(false) + .build(); Institute institute = Institute.builder() - .instituteId(1L) - .name("도서관") - .location("서울시") - .latitude(new BigDecimal("123456789.12341234")) - .longitude(new BigDecimal("987654321.43214321")) - .sidoGungu(district) - .phone("010xxxxxxxx") - .build(); + .instituteId(1L) + .name("도서관") + .location("서울시") + .latitude(new BigDecimal("37.56100278")) + .longitude(new BigDecimal("126.9996417")) + .sidoGungu(district) + .phone("010xxxxxxxx") + .build(); Activity activity = Activity.builder() - .actId(1L) - .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") - .actLocation("아이사랑꿈터 서구 5호점") - .description("봉사 내용") - .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .noticeEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .actEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartTime(13) - .actEndTime(18) - .recruitTotalNum(1) - .adultPossible(true) - .teenPossible(false) - .groupPossible(false) - .actWeek(0111110) - .actManager("윤순영") - .actPhone("032-577-3026") - .url("https://...") - .category(Category.OTHER_ACTIVITIES) - .institute(institute) - .sidoGungu(district) - .build(); + .actId(1L) + .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") + .actLocation("아이사랑꿈터 서구 5호점") + .description("봉사 내용") + .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .noticeEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) + .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .actEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) + .actStartTime(13) + .actEndTime(18) + .recruitTotalNum(1) + .adultPossible(true) + .teenPossible(false) + .groupPossible(false) + .actWeek(0111110) + .actManager("윤순영") + .actPhone("032-577-3026") + .url("https://...") + .category(Category.OTHER_ACTIVITIES) + .institute(institute) + .sidoGungu(district) + .build(); // when ActivityJpaEntity jpaEntity = ActivityJpaEntity.from(activity); @@ -68,46 +69,46 @@ class ActivityJpaEntityTest { void JPA엔티에서_도메인모델로_변환() { // given DistrictJpaEntity districtJpaEntity = DistrictJpaEntity.builder() - .sidoCode(1234) - .sidoGunguCode(8888) - .sidoName("서울특별시") - .gunguName("강남구") - .sido(false) - .build(); + .sidoCode(1234) + .sidoGunguCode(8888) + .sidoName("서울특별시") + .gunguName("강남구") + .sido(false) + .build(); InstituteJpaEntity institute = InstituteJpaEntity.builder() - .instituteId(1L) - .name("도서관") - .location("서울시") - .latitude(new BigDecimal("123456789.12341234")) - .longitude(new BigDecimal("987654321.43214321")) - .sidoGungu(districtJpaEntity) - .phone("010xxxxxxxx") - .build(); + .instituteId(1L) + .name("도서관") + .location("서울시") + .latitude(new BigDecimal("37.56100278")) + .longitude(new BigDecimal("126.9996417")) + .sidoGungu(districtJpaEntity) + .phone("010xxxxxxxx") + .build(); ActivityJpaEntity jpaEntity = ActivityJpaEntity.builder() - .actId(1L) - .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") - .actLocation("아이사랑꿈터 서구 5호점") - .description("봉사 내용") - .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .noticeEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .actEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartTime(13) - .actEndTime(18) - .recruitTotalNum(1) - .adultPossible(true) - .teenPossible(false) - .groupPossible(false) - .actWeek(0111110) - .actManager("윤순영") - .actPhone("032-577-3026") - .url("https://...") - .category(Category.OTHER_ACTIVITIES) - .institute(institute) - .sidoGungu(districtJpaEntity) - .build(); + .actId(1L) + .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") + .actLocation("아이사랑꿈터 서구 5호점") + .description("봉사 내용") + .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .noticeEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) + .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .actEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) + .actStartTime(13) + .actEndTime(18) + .recruitTotalNum(1) + .adultPossible(true) + .teenPossible(false) + .groupPossible(false) + .actWeek(0111110) + .actManager("윤순영") + .actPhone("032-577-3026") + .url("https://...") + .category(Category.OTHER_ACTIVITIES) + .institute(institute) + .sidoGungu(districtJpaEntity) + .build(); // when Activity activity = jpaEntity.toModel(); diff --git a/src/test/java/com/gamsa/activity/entity/InstituteJpaEntityTest.java b/src/test/java/com/gamsa/activity/entity/InstituteJpaEntityTest.java index 8e10d69..16fb2a6 100644 --- a/src/test/java/com/gamsa/activity/entity/InstituteJpaEntityTest.java +++ b/src/test/java/com/gamsa/activity/entity/InstituteJpaEntityTest.java @@ -1,13 +1,14 @@ package com.gamsa.activity.entity; -import static org.assertj.core.api.Assertions.assertThat; - import com.gamsa.activity.domain.District; import com.gamsa.activity.domain.Institute; -import java.math.BigDecimal; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.math.BigDecimal; + +import static org.assertj.core.api.Assertions.assertThat; + class InstituteJpaEntityTest { @@ -16,22 +17,22 @@ class InstituteJpaEntityTest { void changeToJpaEntity() { // given District district = District.builder() - .sidoCode(1234) - .sidoGunguCode(8888) - .sidoName("서울특별시") - .gunguName("강남구") - .sido(false) - .build(); + .sidoCode(1234) + .sidoGunguCode(8888) + .sidoName("서울특별시") + .gunguName("강남구") + .sido(false) + .build(); Institute model = Institute.builder() - .instituteId(1L) - .name("도서관") - .location("서울시") - .latitude(new BigDecimal("123456789.12341234")) - .longitude(new BigDecimal("987654321.43214321")) - .sidoGungu(district) - .phone("010xxxxxxxx") - .build(); + .instituteId(1L) + .name("도서관") + .location("서울시") + .latitude(new BigDecimal("37.56100278")) + .longitude(new BigDecimal("126.9996417")) + .sidoGungu(district) + .phone("010xxxxxxxx") + .build(); // when InstituteJpaEntity jpaEntity = InstituteJpaEntity.from(model); // then @@ -43,22 +44,22 @@ void changeToJpaEntity() { void changeToDomainModel() { // given DistrictJpaEntity districtJpaEntity = DistrictJpaEntity.builder() - .sidoCode(1234) - .sidoGunguCode(8888) - .sidoName("서울특별시") - .gunguName("강남구") - .sido(false) - .build(); + .sidoCode(1234) + .sidoGunguCode(8888) + .sidoName("서울특별시") + .gunguName("강남구") + .sido(false) + .build(); InstituteJpaEntity jpaEntity = InstituteJpaEntity.builder() - .instituteId(1L) - .name("도서관") - .location("서울시") - .latitude(new BigDecimal("123456789.12341234")) - .longitude(new BigDecimal("987654321.43214321")) - .sidoGungu(districtJpaEntity) - .phone("010xxxxxxxx") - .build(); + .instituteId(1L) + .name("도서관") + .location("서울시") + .latitude(new BigDecimal("37.56100278")) + .longitude(new BigDecimal("126.9996417")) + .sidoGungu(districtJpaEntity) + .phone("010xxxxxxxx") + .build(); // when Institute model = jpaEntity.toModel(); // then diff --git a/src/test/java/com/gamsa/activity/repository/ActivityJpaRepositoryTest.java b/src/test/java/com/gamsa/activity/repository/ActivityJpaRepositoryTest.java index c9ad167..a41c035 100644 --- a/src/test/java/com/gamsa/activity/repository/ActivityJpaRepositoryTest.java +++ b/src/test/java/com/gamsa/activity/repository/ActivityJpaRepositoryTest.java @@ -1,14 +1,10 @@ package com.gamsa.activity.repository; -import static org.assertj.core.api.Assertions.assertThat; - import com.gamsa.activity.constant.Category; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.entity.ActivityJpaEntity; import com.gamsa.common.config.TestConfig; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; @@ -17,6 +13,13 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort.Direction; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + @DataJpaTest @Import(TestConfig.class) class ActivityJpaRepositoryTest { @@ -24,103 +27,113 @@ class ActivityJpaRepositoryTest { @Autowired private ActivityJpaRepository activityJpaRepository; - private final ActivityJpaEntity jpaEntity = ActivityJpaEntity.builder() - .actId(1L) - .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") - .actLocation("아이사랑꿈터 서구 5호점") - .description("봉사 내용") - .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .noticeEndDate(LocalDateTime.of(2024, 9, 20, 0, 0)) - .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .actEndDate(LocalDateTime.of(2024, 9, 20, 0, 0)) - .actStartTime(13) - .actEndTime(18) - .recruitTotalNum(1) - .adultPossible(true) - .teenPossible(false) - .groupPossible(false) - .actWeek(0111110) - .actManager("윤순영") - .actPhone("032-577-3026") - .url("https://...") - .category(Category.OTHER_ACTIVITIES) - .build(); + private final ActivityJpaEntity jpaEntity1 = ActivityJpaEntity.builder() + .actId(1L) + .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") + .actLocation("아이사랑꿈터 서구 5호점") + .description("봉사 내용") + .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .noticeEndDate(LocalDateTime.of(2024, 9, 20, 0, 0)) + .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) + .actEndDate(LocalDateTime.of(2024, 9, 20, 0, 0)) + .actStartTime(13) + .actEndTime(18) + .recruitTotalNum(1) + .adultPossible(true) + .teenPossible(false) + .groupPossible(false) + .longitude(new BigDecimal("126.11111111")) + .latitude(new BigDecimal("37.11111111")) + .actWeek(0111110) + .actManager("윤순영") + .actPhone("032-577-3026") + .url("https://...") + .category(Category.OTHER_ACTIVITIES) + .build(); private final ActivityJpaEntity jpaEntity2 = ActivityJpaEntity.builder() - .actId(2L) - .actTitle("어린이놀이안전관리 청소") - .actLocation("아이사랑꿈터 서구 7호점") - .description("봉사 내용2") - .noticeStartDate(LocalDateTime.of(2024, 11, 1, 0, 0)) - .noticeEndDate(LocalDateTime.of(2024, 12, 8, 0, 0)) - .actStartDate(LocalDateTime.of(2024, 11, 1, 0, 0)) - .actEndDate(LocalDateTime.of(2024, 12, 8, 0, 0)) - .actStartTime(10) - .actEndTime(20) - .recruitTotalNum(2) - .adultPossible(true) - .teenPossible(true) - .groupPossible(false) - .actWeek(0111110) - .actManager("홀란드") - .actPhone("032-111-2222") - .url("https://...") - .category(Category.EDUCATION_AND_MENTORING) - .build(); + .actId(2L) + .actTitle("어린이놀이안전관리 청소") + .actLocation("아이사랑꿈터 서구 7호점") + .description("봉사 내용2") + .noticeStartDate(LocalDateTime.of(2024, 11, 1, 0, 0)) + .noticeEndDate(LocalDateTime.of(2024, 12, 8, 0, 0)) + .actStartDate(LocalDateTime.of(2024, 11, 1, 0, 0)) + .actEndDate(LocalDateTime.of(2024, 12, 8, 0, 0)) + .actStartTime(10) + .actEndTime(20) + .recruitTotalNum(2) + .adultPossible(true) + .teenPossible(true) + .groupPossible(false) + .longitude(new BigDecimal("127.66666666")) + .latitude(new BigDecimal("38.66666666")) + .actWeek(0111110) + .actManager("홀란드") + .actPhone("032-111-2222") + .url("https://...") + .category(Category.EDUCATION_AND_MENTORING) + .build(); private final ActivityJpaEntity jpaEntity3 = ActivityJpaEntity.builder() - .actId(3L) - .actTitle("학교") - .actLocation("도서관") - .description("책 정리") - .noticeStartDate(LocalDateTime.of(2025, 1, 1, 0, 0)) - .noticeEndDate(LocalDateTime.of(2025, 1, 8, 0, 0)) - .actStartDate(LocalDateTime.of(2025, 1, 1, 0, 0)) - .actEndDate(LocalDateTime.of(2025, 1, 8, 0, 0)) - .actStartTime(10) - .actEndTime(20) - .recruitTotalNum(5) - .adultPossible(true) - .teenPossible(true) - .groupPossible(false) - .actWeek(0111110) - .actManager("사서쌤") - .actPhone("032-111-2222") - .url("https://...") - .category(Category.ADMINISTRATIVE_AND_OFFICE_SUPPORT) - .build(); + .actId(3L) + .actTitle("학교") + .actLocation("도서관") + .description("책 정리") + .noticeStartDate(LocalDateTime.of(2025, 1, 1, 0, 0)) + .noticeEndDate(LocalDateTime.of(2025, 1, 8, 0, 0)) + .actStartDate(LocalDateTime.of(2025, 1, 1, 0, 0)) + .actEndDate(LocalDateTime.of(2025, 1, 8, 0, 0)) + .actStartTime(10) + .actEndTime(20) + .recruitTotalNum(5) + .adultPossible(true) + .teenPossible(true) + .groupPossible(false) + .longitude(new BigDecimal("128.99999999")) + .latitude(new BigDecimal("39.99999999")) + .actWeek(0111110) + .actManager("사서쌤") + .actPhone("032-111-2222") + .url("https://...") + .category(Category.ADMINISTRATIVE_AND_OFFICE_SUPPORT) + .build(); // 필터링 private final ActivityFilterRequest noFilterReq = new ActivityFilterRequest( - null, null, null, false, false); + null, null, null, false, false, null); private final ActivityFilterRequest otherCategoryFilterReq = new ActivityFilterRequest( - Category.OTHER_ACTIVITIES, null, null, false, false); + Category.OTHER_ACTIVITIES, null, null, false, false, null); private final ActivityFilterRequest teenPossibleFilterReq = new ActivityFilterRequest( - null, null, null, true, false); + null, null, null, true, false, null); private final ActivityFilterRequest beforeDeadlineFilterReq = new ActivityFilterRequest( - null, null, null, false, true); + null, null, null, false, true, null); + + // distance sorting + private final ActivityFindDistanceOrderRequest distanceOrderReq = new ActivityFindDistanceOrderRequest( + new BigDecimal("37.11111111"), new BigDecimal("126.11111111"), 9999999); @Test void 새_활동_저장() { // when - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); // then assertThat(activityJpaRepository.findById(1L).get().getActTitle()) - .isEqualTo(jpaEntity.getActTitle()); + .isEqualTo(jpaEntity1.getActTitle()); } @Test void 모든_활동_리스트_반환() { // given - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); // when List content = activityJpaRepository - .findSlice(noFilterReq, PageRequest.of(0, 10)) - .getContent(); + .findSlice(noFilterReq, PageRequest.of(0, 10)) + .getContent(); // then assertThat(content.size()).isEqualTo(1); } @@ -128,23 +141,23 @@ class ActivityJpaRepositoryTest { @Test void 활동_상세정보_조회() { // given - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); // when Optional result = activityJpaRepository.findById(1L); // then - assertThat(result.get().getActTitle()).isEqualTo(jpaEntity.getActTitle()); + assertThat(result.get().getActTitle()).isEqualTo(jpaEntity1.getActTitle()); } @Test void id로_정렬된_조회() { // given - activityJpaRepository.save(jpaEntity); // id = 1L + activityJpaRepository.save(jpaEntity1); // id = 1L activityJpaRepository.save(jpaEntity2); // id = 2L Pageable pageable = PageRequest.of(0, 2, Direction.DESC, "actId"); // when List content = activityJpaRepository.findSlice(noFilterReq, pageable) - .getContent(); + .getContent(); // then assertThat(content.size()).isEqualTo(2); @@ -155,58 +168,58 @@ class ActivityJpaRepositoryTest { @Test void 마감_날짜_오름차순_정렬_조회() { // given - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); activityJpaRepository.save(jpaEntity2); activityJpaRepository.save(jpaEntity3); Pageable pageable = PageRequest - .of(0, 3, Direction.ASC, "noticeEndDate"); + .of(0, 3, Direction.ASC, "noticeEndDate"); // when List content = activityJpaRepository.findSlice(noFilterReq, pageable) - .getContent(); + .getContent(); // then assertThat(content.size()).isEqualTo(3); assertThat(content.get(0).getNoticeEndDate().isBefore(content.get(1).getNoticeEndDate())) - .isTrue(); + .isTrue(); assertThat(content.get(1).getNoticeEndDate().isBefore(content.get(2).getNoticeEndDate())) - .isTrue(); + .isTrue(); } @Test void 마감된_공고중_마감_날짜_가까운순_정렬_조회() { // given LocalDateTime date = LocalDateTime.of(2024, 10, 1, 0, 0); - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); activityJpaRepository.save(jpaEntity2); activityJpaRepository.save(jpaEntity3); Pageable pageable = PageRequest - .of(0, 3, Direction.ASC, "noticeEndDate"); + .of(0, 3, Direction.ASC, "noticeEndDate"); // when List content1 = activityJpaRepository - .findSlice(noFilterReq, pageable).getContent(); + .findSlice(noFilterReq, pageable).getContent(); List content2 = activityJpaRepository - .findSlice(beforeDeadlineFilterReq, pageable).getContent(); + .findSlice(beforeDeadlineFilterReq, pageable).getContent(); // then assertThat(content1.size()).isEqualTo(3); // 필터링 X assertThat(content2.size()).isEqualTo(2); // 필터링 O assertThat(content2.getFirst().getNoticeEndDate() - .isBefore(content2.getLast().getNoticeEndDate())) - .isTrue(); + .isBefore(content2.getLast().getNoticeEndDate())) + .isTrue(); } @Test void 카테고리로_필터링_조회() { // given - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); activityJpaRepository.save(jpaEntity2); Pageable pageable = PageRequest.of(0, 2, Direction.ASC, "actId"); // when List content = activityJpaRepository.findSlice(otherCategoryFilterReq, - pageable).getContent(); + pageable).getContent(); // then assertThat(content.size()).isEqualTo(1); @@ -216,13 +229,13 @@ class ActivityJpaRepositoryTest { @Test void 청소년_가능여부_필터링_조회() { // given - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); activityJpaRepository.save(jpaEntity2); Pageable pageable = PageRequest.of(0, 2, Direction.ASC, "actId"); // when List content = activityJpaRepository.findSlice(teenPossibleFilterReq, - pageable).getContent(); + pageable).getContent(); // then assertThat(content.size()).isEqualTo(1); @@ -233,16 +246,35 @@ class ActivityJpaRepositoryTest { void 마감되지_않은_활동만_필터링_조회() { // given LocalDateTime date = LocalDateTime.of(2024, 10, 1, 0, 0); - activityJpaRepository.save(jpaEntity); + activityJpaRepository.save(jpaEntity1); activityJpaRepository.save(jpaEntity2); Pageable pageable = PageRequest.of(0, 2, Direction.ASC, "actId"); // when List content = activityJpaRepository.findSlice(beforeDeadlineFilterReq, - pageable).getContent(); + pageable).getContent(); // then assertThat(content.size()).isEqualTo(1); assertThat(content.getFirst().getNoticeEndDate().isAfter(date)).isTrue(); } -} \ No newline at end of file + + @Test + void 가까운_거리순_정렬_조회() { + // given + activityJpaRepository.save(jpaEntity1); + activityJpaRepository.save(jpaEntity2); + activityJpaRepository.save(jpaEntity3); + Pageable pageable = PageRequest.of(0, 3, Direction.ASC, "distance"); + + // when + List content = activityJpaRepository.findSliceDistanceOrder( + noFilterReq, distanceOrderReq, pageable) + .getContent(); + + // then + assertThat(content.size()).isEqualTo(3); + assertThat(content.getFirst().getActId()).isEqualTo(jpaEntity1.getActId()); + assertThat(content.getLast().getActId()).isEqualTo(jpaEntity3.getActId()); + } +} diff --git a/src/test/java/com/gamsa/activity/repository/InstituteJpaRepositoryTest.java b/src/test/java/com/gamsa/activity/repository/InstituteJpaRepositoryTest.java index 45f82c2..0a4c7dd 100644 --- a/src/test/java/com/gamsa/activity/repository/InstituteJpaRepositoryTest.java +++ b/src/test/java/com/gamsa/activity/repository/InstituteJpaRepositoryTest.java @@ -1,16 +1,17 @@ package com.gamsa.activity.repository; -import static org.assertj.core.api.Assertions.assertThat; - import com.gamsa.activity.entity.InstituteJpaEntity; import com.gamsa.common.config.TestConfig; -import java.math.BigDecimal; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; +import java.math.BigDecimal; + +import static org.assertj.core.api.Assertions.assertThat; + @DataJpaTest @Import(TestConfig.class) class InstituteJpaRepositoryTest { @@ -19,13 +20,13 @@ class InstituteJpaRepositoryTest { private InstituteJpaRepository instituteJpaRepository; private final InstituteJpaEntity jpaEntity = InstituteJpaEntity.builder() - .instituteId(1L) - .name("도서관") - .location("서울시") - .latitude(new BigDecimal("123456789.12341234")) - .longitude(new BigDecimal("987654321.43214321")) - .phone("010xxxxxxxx") - .build(); + .instituteId(1L) + .name("도서관") + .location("서울시") + .latitude(new BigDecimal("37.56100278")) + .longitude(new BigDecimal("126.9996417")) + .phone("010xxxxxxxx") + .build(); @Test @DisplayName("새 봉사기관 저장") @@ -34,6 +35,6 @@ void save() { instituteJpaRepository.save(jpaEntity); // then assertThat(instituteJpaRepository.findById(1L).get().getName()) - .isEqualTo(jpaEntity.getName()); + .isEqualTo(jpaEntity.getName()); } } \ No newline at end of file diff --git a/src/test/java/com/gamsa/activity/service/ActivityServiceTest.java b/src/test/java/com/gamsa/activity/service/ActivityServiceTest.java index 9a1e164..24e3639 100644 --- a/src/test/java/com/gamsa/activity/service/ActivityServiceTest.java +++ b/src/test/java/com/gamsa/activity/service/ActivityServiceTest.java @@ -1,95 +1,48 @@ package com.gamsa.activity.service; -import static org.assertj.core.api.Assertions.assertThat; - import com.gamsa.activity.constant.ActivityErrorCode; -import com.gamsa.activity.constant.Category; import com.gamsa.activity.dto.ActivityDetailResponse; import com.gamsa.activity.dto.ActivityFindSliceResponse; -import com.gamsa.activity.dto.ActivitySaveRequest; import com.gamsa.activity.exception.ActivityException; import com.gamsa.activity.stub.StubEmptyActivityRepository; import com.gamsa.activity.stub.StubExistsActivityRepository; -import com.gamsa.activity.stub.StubExistsDistrictRepository; -import com.gamsa.activity.stub.StubExistsInstituteRepository; -import java.time.LocalDateTime; +import com.gamsa.history.stub.StubHistoryRepository; +import com.gamsa.review.service.QuestionService; +import com.gamsa.review.service.ReviewService; +import com.gamsa.review.stub.StubAnswerRepository; +import com.gamsa.review.stub.StubQuestionRepository; +import com.gamsa.review.stub.StubReviewRepository; +import com.gamsa.user.stub.StubExistsUserRepository; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; -class ActivityServiceTest { - - ActivitySaveRequest saveRequest = ActivitySaveRequest.builder() - .actId(1L) - .actTitle("어린이놀이안전관리 및 놀잇감 청결유지 및 정리") - .actLocation("아이사랑꿈터 서구 5호점") - .description("봉사 내용") - .noticeStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .noticeEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartDate(LocalDateTime.of(2024, 9, 10, 0, 0)) - .actEndDate(LocalDateTime.of(2024, 12, 7, 0, 0)) - .actStartTime(13) - .actEndTime(18) - .recruitTotalNum(1) - .adultPossible(true) - .teenPossible(false) - .groupPossible(false) - .actWeek(0111110) - .actManager("윤순영") - .actPhone("032-577-3026") - .url("https://...") - .category(Category.OTHER_ACTIVITIES) - .instituteId(1L) - .sidoGunguCode(1) - .build(); - - @Test - void 활동객체를_저장하고_성공한다() { - // given - ActivityService activityService = new ActivityService( - new StubEmptyActivityRepository(), - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() - ); - - // then - Assertions.assertDoesNotThrow(() -> { - // when - activityService.save(saveRequest); - }); - - } +import static org.assertj.core.api.Assertions.assertThat; - @Test - void 이미_존재하는_ID의_활동객체를_생성하고_실패한다() { - // given - ActivityService activityService = new ActivityService( - new StubExistsActivityRepository(), - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() - ); +class ActivityServiceTest { - // then - Assertions.assertThrows(ActivityException.class, () -> { - // when - activityService.save(saveRequest); - }, ActivityErrorCode.ACTIVITY_ALREADY_EXISTS.getMsg()); - } @Test void 활동객체_리스트를_반환한다() { // given ActivityService activityService = new ActivityService( - new StubEmptyActivityRepository(), - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() + new StubEmptyActivityRepository(), + new QuestionService( + new StubQuestionRepository() + ), + new ReviewService( + new StubExistsUserRepository(), + new StubQuestionRepository(), + new StubReviewRepository(), + new StubAnswerRepository(), + new StubHistoryRepository() + ) ); // when - Slice result = activityService.findSlice(null, - PageRequest.of(0, 10)); + Slice result = activityService.findSlice(null, null, + PageRequest.of(0, 10)); // then assertThat(result.getContent().size()).isZero(); @@ -99,9 +52,17 @@ class ActivityServiceTest { void ID로_활동조회에_성공한다() { // given ActivityService activityService = new ActivityService( - new StubExistsActivityRepository(), - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() + new StubExistsActivityRepository(), + new QuestionService( + new StubQuestionRepository() + ), + new ReviewService( + new StubExistsUserRepository(), + new StubQuestionRepository(), + new StubReviewRepository(), + new StubAnswerRepository(), + new StubHistoryRepository() + ) ); // when @@ -115,9 +76,17 @@ class ActivityServiceTest { void ID로_활동조회에_실패한다() { // given ActivityService activityService = new ActivityService( - new StubEmptyActivityRepository(), - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() + new StubEmptyActivityRepository(), + new QuestionService( + new StubQuestionRepository() + ), + new ReviewService( + new StubExistsUserRepository(), + new StubQuestionRepository(), + new StubReviewRepository(), + new StubAnswerRepository(), + new StubHistoryRepository() + ) ); // then @@ -126,10 +95,4 @@ class ActivityServiceTest { activityService.findById(1L); }, ActivityErrorCode.ACTIVITY_NOT_EXISTS.getMsg()); } - - @Test - @DisplayName("활동 ID로 봉사 기관 정보를 조회한다.") - void findInstituteByActivityId() { - - } } \ No newline at end of file diff --git a/src/test/java/com/gamsa/activity/service/InstituteServiceTest.java b/src/test/java/com/gamsa/activity/service/InstituteServiceTest.java index 16814aa..ac1bf67 100644 --- a/src/test/java/com/gamsa/activity/service/InstituteServiceTest.java +++ b/src/test/java/com/gamsa/activity/service/InstituteServiceTest.java @@ -1,14 +1,10 @@ package com.gamsa.activity.service; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import com.gamsa.activity.constant.ActivityErrorCode; import com.gamsa.activity.dto.InstituteSaveRequest; -import com.gamsa.activity.exception.ActivityException; import com.gamsa.activity.stub.StubEmptyInstituteRepository; import com.gamsa.activity.stub.StubExistsDistrictRepository; -import com.gamsa.activity.stub.StubExistsInstituteRepository; import java.math.BigDecimal; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -38,19 +34,4 @@ void save() { service.save(saveRequest); }); } - - @Test - @DisplayName("봉시기관 동일 이름 충돌로 실패한다.") - void saveFail() { - // given - InstituteService service = new InstituteService( - new StubExistsInstituteRepository(), - new StubExistsDistrictRepository() - ); - // then - assertThrows(ActivityException.class, () -> { - // when - service.save(saveRequest); - }, ActivityErrorCode.INSTITUTE_ALREADY_EXISTS.getMsg()); - } } \ No newline at end of file diff --git a/src/test/java/com/gamsa/activity/stub/StubEmptyActivityRepository.java b/src/test/java/com/gamsa/activity/stub/StubEmptyActivityRepository.java index 4b58491..8f634f3 100644 --- a/src/test/java/com/gamsa/activity/stub/StubEmptyActivityRepository.java +++ b/src/test/java/com/gamsa/activity/stub/StubEmptyActivityRepository.java @@ -2,6 +2,7 @@ import com.gamsa.activity.domain.Activity; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.repository.ActivityRepository; import java.util.List; import java.util.Optional; @@ -21,6 +22,12 @@ public Slice findSlice(ActivityFilterRequest request, Pageable pageabl return new SliceImpl<>(List.of()); } + @Override + public Slice findSliceDistanceOrder(ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, Pageable pageable) { + return new SliceImpl<>(List.of()); + } + @Override public Optional findById(Long activityId) { return Optional.empty(); diff --git a/src/test/java/com/gamsa/activity/stub/StubExistsActivityRepository.java b/src/test/java/com/gamsa/activity/stub/StubExistsActivityRepository.java index d4161d2..d0a11cc 100644 --- a/src/test/java/com/gamsa/activity/stub/StubExistsActivityRepository.java +++ b/src/test/java/com/gamsa/activity/stub/StubExistsActivityRepository.java @@ -4,6 +4,7 @@ import com.gamsa.activity.domain.District; import com.gamsa.activity.domain.Institute; import com.gamsa.activity.dto.ActivityFilterRequest; +import com.gamsa.activity.dto.ActivityFindDistanceOrderRequest; import com.gamsa.activity.repository.ActivityRepository; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -65,6 +66,12 @@ public Slice findSlice(ActivityFilterRequest request, Pageable pageabl return new SliceImpl<>(List.of(activity)); } + @Override + public Slice findSliceDistanceOrder(ActivityFilterRequest filterRequest, + ActivityFindDistanceOrderRequest distanceOrderRequest, Pageable pageable) { + return new SliceImpl<>(List.of(activity)); + } + @Override public Optional findById(Long activityId) { return Optional.of(activity); diff --git a/src/test/java/com/gamsa/dataupdate/ActivityDataUtilsTest.java b/src/test/java/com/gamsa/dataupdate/ActivityDataUtilsTest.java deleted file mode 100644 index fcf92b7..0000000 --- a/src/test/java/com/gamsa/dataupdate/ActivityDataUtilsTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.gamsa.dataupdate; - -import com.gamsa.activity.constant.Category; -import com.gamsa.dataupdate.utils.ActivityDataUtils; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import java.time.LocalDate; - -import static org.assertj.core.api.Assertions.assertThat; - -@SpringBootTest -public class ActivityDataUtilsTest { - - @Autowired - private ActivityDataUtils activityDataUtils; - - @Test - void 기간별_활동_리스트_조회() { - //given - LocalDate today = LocalDate.now(); - LocalDate endDate = today.plusDays(7); - - //when - var list = activityDataUtils.getVolunteerParticipationList(today, endDate); - - //then - assertThat(list.size()).isNotZero(); - } - - @Test - void 기관_상세_조회() { - //given - String programNo = "3168803"; - - //when - var result = activityDataUtils.getInstituteApiResponse(programNo); - - //then - assertThat(result.getName()).isEqualTo("음성효심주간보호센터"); - } - - @Test - void 활동_상세_조회() { - //given - String programNo = "3168803"; - - //when - var result = activityDataUtils.getVolunteerDetail(programNo); - - //then - assertThat(result.getCategory()).isEqualTo(Category.CULTURE_ENVIRONMENT_AND_INTERNATIONAL_COOPERATION); - } -} diff --git a/src/test/java/com/gamsa/dataupdate/DataUpdateSchedulerTest.java b/src/test/java/com/gamsa/dataupdate/DataUpdateSchedulerTest.java deleted file mode 100644 index b7d25b4..0000000 --- a/src/test/java/com/gamsa/dataupdate/DataUpdateSchedulerTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gamsa.dataupdate; - -import com.gamsa.dataupdate.service.ActivityDataUpdateService; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -import java.time.LocalDate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; - -@SpringBootTest -public class DataUpdateSchedulerTest { - - @Autowired - private DataUpdateScheduler dataUpdateScheduler; - - @MockBean - private ActivityDataUpdateService activityDataUpdateService; - - @Test - public void 업데이트_메서드_동작() { - //given - int days = 7; - - //when - dataUpdateScheduler.runActivityDataUpdate(); - - //then - ArgumentCaptor captor = ArgumentCaptor.forClass(LocalDate.class); - verify(activityDataUpdateService).update(captor.capture(), captor.capture()); - - LocalDate today = LocalDate.now(); - LocalDate expectedEndDate = today.plusDays(days); - - assertThat(captor.getAllValues()) - .hasSize(2) - .containsExactly(today, expectedEndDate); - } -} \ No newline at end of file diff --git a/src/test/java/com/gamsa/dataupdate/KakaoLocalUtilsTest.java b/src/test/java/com/gamsa/dataupdate/KakaoLocalUtilsTest.java deleted file mode 100644 index 46ced13..0000000 --- a/src/test/java/com/gamsa/dataupdate/KakaoLocalUtilsTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.gamsa.dataupdate; - -import com.gamsa.dataupdate.utils.KakaoLocalUtils; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.assertj.core.api.Assertions.assertThat; - -@SpringBootTest -public class KakaoLocalUtilsTest { - - @Autowired - private KakaoLocalUtils kakaoLocalUtils; - - @Test - void 주소_검색_테스트() { - //given - String address = "경기 광주시 중앙로175번길 14 송정문화센터 2층"; - - //when - var result = kakaoLocalUtils.getCoordinateByAddress(address).orElseThrow(); - - //then - System.out.println(result); - assertThat(result).isNotNull(); - } -} diff --git a/src/test/java/com/gamsa/dataupdate/utils/ActivityDataUtilsTest.java b/src/test/java/com/gamsa/dataupdate/utils/ActivityDataUtilsTest.java new file mode 100644 index 0000000..420929a --- /dev/null +++ b/src/test/java/com/gamsa/dataupdate/utils/ActivityDataUtilsTest.java @@ -0,0 +1,233 @@ +package com.gamsa.dataupdate.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gamsa.activity.dto.ActivitySaveRequest; +import com.gamsa.activity.dto.InstituteApiResponse; +import com.gamsa.dataupdate.DataUpdateErrorCode; +import com.gamsa.dataupdate.DataUpdateException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +public class ActivityDataUtilsTest { + + @Mock + private RestTemplate restTemplate; + + @InjectMocks + private ActivityDataUtils activityDataUtils; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void 목록_조회_성공() throws Exception { + String firstResponse = """ + { + "response": { + "body": { + "items": { + "item": [ + { "progrmRegistNo": "12345" }, + { "progrmRegistNo": "67890" } + ] + } + } + } + } + """; + String secondResponse = """ + { + "response": { + "body": { + "items": { + "item": [ + ] + } + } + } + } + """; + + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(firstResponse, HttpStatus.OK)) + .thenReturn(new ResponseEntity<>(secondResponse, HttpStatus.OK)) + ; + + List result = activityDataUtils.getVolunteerParticipationList( + LocalDate.of(2024, 1, 1), LocalDate.of(2024, 12, 31)); + + assertEquals(2, result.size()); + assertTrue(result.contains("12345")); + assertTrue(result.contains("67890")); + } + + @Test + public void 목록_조회_실패() { + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + + assertThrows(DataUpdateException.class, () -> + activityDataUtils.getVolunteerParticipationList(LocalDate.of(2024, 1, 1), LocalDate.of(2024, 12, 31)), + DataUpdateErrorCode.OPENAPI_NOT_RESPOND.name() + ); + } + + @Test + public void 기관_조회_성공() throws Exception { + //given + String mockResponse = """ + {"response": { + "body": { + "items": { + "item": { + "actBeginTm": 10, + "actEndTm": 11, + "actPlace": "음성효심주간보호 프로그램실", + "actWkdy": 1111111, + "adultPosblAt": "Y", + "appTotal": 0, + "areaAddress1": "충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", + "areaAddress2": "", + "areaAddress3": "", + "areaLalo1": "36.9397922285334,127.686299185056", + "areaLalo2": "", + "areaLalo3": "", + "email": "shon1966@naver.com", + "familyPosblAt": "N", + "fxnum": "0438732338", + "grpPosblAt": "N", + "gugunCd": 4470000, + "mnnstNm": "음성효심주간보호센터", + "nanmmbyNm": "충청북도 음성군", + "nanmmbyNmAdmn": "손덕기", + "noticeBgnde": 20240803, + "noticeEndde": 20241102, + "pbsvntPosblAt": "N", + "postAdres": "충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", + "progrmBgnde": 20240803, + "progrmCn": "-어르신 민요교실 준비\\n-어르신 민요교실 프로그램 진행\\n-어르신 민요교실 마무리", + "progrmEndde": 20241102, + "progrmRegistNo": 3168803, + "progrmSj": "어르신 민요 공연 봉사", + "progrmSttusSe": 2, + "rcritNmpr": 2, + "sidoCd": 6430000, + "srvcClCode": "문화행사 > 공연활동", + "telno": "043-873-2337", + "yngbgsPosblAt": "N" + } + } + } + } + } + """; + + //when + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK)); + + InstituteApiResponse result = activityDataUtils.getInstituteApiResponse("3168803"); + + //then + assertEquals("충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", result.getLocation()); + } + + @Test + public void 기관_조회_실패() { + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + + assertThrows(DataUpdateException.class, () -> + activityDataUtils.getInstituteApiResponse("12345"), + DataUpdateErrorCode.OPENAPI_NOT_RESPOND.name() + ); + } + + @Test + public void 활동_조회_성공() throws Exception { + String mockResponse = """ + { + "response": { + "body": { + "items": { + "item": { + "actBeginTm": 10, + "actEndTm": 11, + "actPlace": "음성효심주간보호 프로그램실", + "actWkdy": 1111111, + "adultPosblAt": "Y", + "appTotal": 0, + "areaAddress1": "충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", + "areaAddress2": "", + "areaAddress3": "", + "areaLalo1": "36.9397922285334,127.686299185056", + "areaLalo2": "", + "areaLalo3": "", + "email": "shon1966@naver.com", + "familyPosblAt": "N", + "fxnum": "0438732338", + "grpPosblAt": "N", + "gugunCd": 4470000, + "mnnstNm": "음성효심주간보호센터", + "nanmmbyNm": "충청북도 음성군", + "nanmmbyNmAdmn": "손덕기", + "noticeBgnde": 20240803, + "noticeEndde": 20241102, + "pbsvntPosblAt": "N", + "postAdres": "충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", + "progrmBgnde": 20240803, + "progrmCn": "-어르신 민요교실 준비\\n-어르신 민요교실 프로그램 진행\\n-어르신 민요교실 마무리", + "progrmEndde": 20241102, + "progrmRegistNo": 3168803, + "progrmSj": "어르신 민요 공연 봉사", + "progrmSttusSe": 2, + "rcritNmpr": 2, + "sidoCd": 6430000, + "srvcClCode": "문화행사 > 공연활동", + "telno": "043-873-2337", + "yngbgsPosblAt": "N" + } + } + } + } + } + """; + + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK)); + + ActivitySaveRequest result = activityDataUtils.getVolunteerDetail("12345"); + + assertEquals("어르신 민요 공연 봉사", result.getActTitle()); + assertEquals("충청북도 음성군 음성읍 음성천서길 217-1 음성효심주간보호센터", result.getActLocation()); + } + + @Test + public void 활동_조회_실패() { + when(restTemplate.getForEntity(any(String.class), eq(String.class))) + .thenReturn(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); + + assertThrows(DataUpdateException.class, () -> + activityDataUtils.getVolunteerDetail("12345"), + DataUpdateErrorCode.OPENAPI_NOT_RESPOND.name() + ); + } +} diff --git a/src/test/java/com/gamsa/dataupdate/utils/KakaoLocalUtilsTest.java b/src/test/java/com/gamsa/dataupdate/utils/KakaoLocalUtilsTest.java new file mode 100644 index 0000000..5c81e20 --- /dev/null +++ b/src/test/java/com/gamsa/dataupdate/utils/KakaoLocalUtilsTest.java @@ -0,0 +1,90 @@ +package com.gamsa.dataupdate.utils; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +public class KakaoLocalUtilsTest { + + @Mock + private RestTemplate restTemplate; + + @InjectMocks + private KakaoLocalUtils kakaoLocalUtils; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void 좌표_반환_성공() { + //given + String address = "Seoul"; + Map document = new HashMap<>(); + document.put("x", "126.9784"); + document.put("y", "37.5665"); + + Map responseBody = new HashMap<>(); + responseBody.put("documents", List.of(document)); + + ResponseEntity responseEntity = new ResponseEntity<>(responseBody, HttpStatus.OK); + + //when + when(restTemplate.exchange( + any(String.class), + eq(HttpMethod.GET), + any(HttpEntity.class), + eq(Map.class) + )).thenReturn(responseEntity); + + Optional> result = kakaoLocalUtils.getCoordinateByAddress(address); + + //then + assertTrue(result.isPresent()); + + Map coordinates = result.get(); + assertEquals(new BigDecimal("126.9784"), coordinates.get("longitude")); + assertEquals(new BigDecimal("37.5665"), coordinates.get("latitude")); + } + + @Test + public void 좌표_반환_실패() { + //given + String address = "Seoul"; + ResponseEntity responseEntity = new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + + //when + when(restTemplate.exchange( + any(String.class), + eq(HttpMethod.GET), + any(HttpEntity.class), + eq(Map.class) + )).thenReturn(responseEntity); + + Optional> result = kakaoLocalUtils.getCoordinateByAddress(address); + + //then + assertEquals(Optional.empty(), result); + } + +} diff --git a/src/test/java/com/gamsa/history/service/HitstoryServiceTest.java b/src/test/java/com/gamsa/history/service/HistoryServiceTest.java similarity index 62% rename from src/test/java/com/gamsa/history/service/HitstoryServiceTest.java rename to src/test/java/com/gamsa/history/service/HistoryServiceTest.java index 30d5b44..423451b 100644 --- a/src/test/java/com/gamsa/history/service/HitstoryServiceTest.java +++ b/src/test/java/com/gamsa/history/service/HistoryServiceTest.java @@ -7,36 +7,23 @@ import com.gamsa.avatar.stub.StubExistsAvatarRepository; import com.gamsa.history.dto.HistorySaveRequest; import com.gamsa.history.stub.StubHistoryRepository; -import com.gamsa.review.service.QuestionService; -import com.gamsa.review.service.ReviewService; -import com.gamsa.review.stub.StubAnswerRepository; -import com.gamsa.review.stub.StubQuestionRepository; -import com.gamsa.review.stub.StubReviewRepository; -import com.gamsa.user.stub.StubExistsUserRepository; import org.junit.jupiter.api.Test; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -public class HitstoryServiceTest { +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class HistoryServiceTest { HistorySaveRequest historySaveRequest = HistorySaveRequest.builder() .actId(1L) .build(); - ReviewService reviewService = new ReviewService( - new StubExistsUserRepository(), - new StubQuestionRepository(), - new StubReviewRepository(), - new StubAnswerRepository(), - new StubHistoryRepository() - ); - - QuestionService questionService = new QuestionService( - new StubQuestionRepository() - ); HistoryService historyService = new HistoryService(new StubHistoryRepository(), - new StubExistsAvatarRepository(), new StubExistsActivityRepository(), questionService, reviewService); + new StubExistsAvatarRepository(), + new StubExistsActivityRepository()); @Test void 새로운_기록_저장() { diff --git a/src/test/java/com/gamsa/review/stub/StubReviewRepository.java b/src/test/java/com/gamsa/review/stub/StubReviewRepository.java index 464a340..301ea37 100644 --- a/src/test/java/com/gamsa/review/stub/StubReviewRepository.java +++ b/src/test/java/com/gamsa/review/stub/StubReviewRepository.java @@ -16,6 +16,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; public class StubReviewRepository implements ReviewRepository { @@ -101,8 +102,12 @@ public void save(Review review) { } @Override - public List findReviews(Long instituteID, Long questionId) { + public List findReviews(Long instituteID, int questionId) { return List.of(review1); + } + @Override + public Optional findHistoryReview(Long historyId) { + return Optional.of(review1); } }