Skip to content

Commit 5474908

Browse files
authored
Merge pull request #13 from swyp-app-team-4/feat#10-official-place-api
[Feat] 뷰포트 내에 위치한 공식 장소들의 좌표를 리스트로 반환하는 기능 구현
2 parents 1cea869 + 30e45d5 commit 5474908

16 files changed

Lines changed: 578 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,8 @@ out/
3636
### VS Code ###
3737
.vscode/
3838

39+
### .sql ###
40+
src/main/resources/*.sql
41+
3942
### application-dev ###
4043
src/main/resources/application-dev.yml
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package boombimapi.domain.congestion.domain.entity;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.GeneratedValue;
6+
import jakarta.persistence.GenerationType;
7+
import jakarta.persistence.Id;
8+
import jakarta.persistence.Table;
9+
import lombok.AccessLevel;
10+
import lombok.Builder;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
14+
@Entity
15+
@Getter
16+
@Table(name = "congestion_levels")
17+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
18+
public class CongestionLevel {
19+
20+
@Id
21+
@GeneratedValue(strategy = GenerationType.IDENTITY)
22+
private Integer id;
23+
24+
@Column(length = 20, nullable = false, unique = true)
25+
private String name;
26+
27+
@Column(length = 100, nullable = false)
28+
private String message;
29+
30+
@Builder
31+
private CongestionLevel(
32+
String name,
33+
String message
34+
) {
35+
this.name = name;
36+
this.message = message;
37+
}
38+
39+
private static CongestionLevel of(
40+
String name,
41+
String message
42+
) {
43+
return CongestionLevel.builder()
44+
.name(name)
45+
.message(message)
46+
.build();
47+
}
48+
49+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package boombimapi.domain.congestion.domain.entity;
2+
3+
import boombimapi.domain.place.domain.entity.OfficialPlace;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.FetchType;
7+
import jakarta.persistence.GeneratedValue;
8+
import jakarta.persistence.GenerationType;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.JoinColumn;
11+
import jakarta.persistence.ManyToOne;
12+
import jakarta.persistence.Table;
13+
import java.time.LocalDateTime;
14+
import lombok.AccessLevel;
15+
import lombok.Builder;
16+
import lombok.Getter;
17+
import lombok.NoArgsConstructor;
18+
19+
@Entity
20+
@Getter
21+
@Table(name = "official_congestions")
22+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
23+
public class OfficialCongestion {
24+
25+
@Id
26+
@GeneratedValue(strategy = GenerationType.IDENTITY)
27+
private Long id;
28+
29+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
30+
@JoinColumn(name = "official_place_id", nullable = false)
31+
private OfficialPlace officialPlace;
32+
33+
@ManyToOne(fetch = FetchType.LAZY, optional = false)
34+
@JoinColumn(name = "congestion_level_id", nullable = false)
35+
private CongestionLevel congestionLevel;
36+
37+
@Column(name = "population_min")
38+
private Long populationMin;
39+
40+
@Column(name = "population_max")
41+
private Long populationMax;
42+
43+
@Column(name = "observed_at", nullable = false)
44+
private LocalDateTime observedAt;
45+
46+
@Builder
47+
private OfficialCongestion(
48+
OfficialPlace officialPlace,
49+
CongestionLevel congestionLevel,
50+
Long populationMin,
51+
Long populationMax,
52+
LocalDateTime observedAt
53+
) {
54+
this.officialPlace = officialPlace;
55+
this.congestionLevel = congestionLevel;
56+
this.populationMin = populationMin;
57+
this.populationMax = populationMax;
58+
this.observedAt = observedAt;
59+
}
60+
61+
public static OfficialCongestion of(
62+
OfficialPlace officialPlace,
63+
CongestionLevel congestionLevel,
64+
Long populationMin,
65+
Long populationMax,
66+
LocalDateTime observedAt
67+
) {
68+
return OfficialCongestion.builder()
69+
.officialPlace(officialPlace)
70+
.congestionLevel(congestionLevel)
71+
.populationMin(populationMin)
72+
.populationMax(populationMax)
73+
.observedAt(observedAt)
74+
.build();
75+
}
76+
77+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package boombimapi.domain.congestion.domain.entity;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.FetchType;
6+
import jakarta.persistence.GeneratedValue;
7+
import jakarta.persistence.GenerationType;
8+
import jakarta.persistence.Id;
9+
import jakarta.persistence.JoinColumn;
10+
import jakarta.persistence.ManyToOne;
11+
import jakarta.persistence.Table;
12+
import lombok.AccessLevel;
13+
import lombok.Builder;
14+
import lombok.Getter;
15+
import lombok.NoArgsConstructor;
16+
17+
@Entity
18+
@Getter
19+
@Table(name = "official_congestion_demographics")
20+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
21+
public class OfficialCongestionDemographics {
22+
23+
@Id
24+
@GeneratedValue(strategy = GenerationType.IDENTITY)
25+
private Long id;
26+
27+
@ManyToOne(fetch = FetchType.LAZY)
28+
@JoinColumn(name = "official_congestion_id", nullable = false)
29+
private OfficialCongestion officialCongestion;
30+
31+
@Column(name = "category", length = 30, nullable = false)
32+
private String category;
33+
34+
@Column(name = "sub_category", length = 30, nullable = false)
35+
private String subCategory;
36+
37+
@Column(name = "rate", nullable = false)
38+
private Double rate;
39+
40+
@Builder
41+
public OfficialCongestionDemographics(
42+
OfficialCongestion officialCongestion,
43+
String category,
44+
String subCategory,
45+
Double rate
46+
) {
47+
this.officialCongestion = officialCongestion;
48+
this.category = category;
49+
this.subCategory = subCategory;
50+
this.rate = rate;
51+
}
52+
53+
public static OfficialCongestionDemographics of(
54+
OfficialCongestion officialCongestion,
55+
String category,
56+
String subCategory,
57+
Double rate
58+
) {
59+
return OfficialCongestionDemographics.builder()
60+
.officialCongestion(officialCongestion)
61+
.category(category)
62+
.subCategory(subCategory)
63+
.rate(rate)
64+
.build();
65+
}
66+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package boombimapi.domain.congestion.domain.entity;
2+
3+
import boombimapi.domain.place.domain.entity.OfficialPlace;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.FetchType;
7+
import jakarta.persistence.GeneratedValue;
8+
import jakarta.persistence.GenerationType;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.JoinColumn;
11+
import jakarta.persistence.ManyToOne;
12+
import jakarta.persistence.Table;
13+
import java.time.LocalDateTime;
14+
import lombok.AccessLevel;
15+
import lombok.Builder;
16+
import lombok.Getter;
17+
import lombok.NoArgsConstructor;
18+
19+
@Entity
20+
@Getter
21+
@Table(name = "official_congestion_forecasts")
22+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
23+
public class OfficialCongestionForecast {
24+
25+
@Id
26+
@GeneratedValue(strategy = GenerationType.IDENTITY)
27+
private Long id;
28+
29+
@ManyToOne(fetch = FetchType.LAZY)
30+
@JoinColumn(name = "official_place_id", nullable = false)
31+
private OfficialPlace officialPlace;
32+
33+
@Column(name = "observed_at", nullable = false)
34+
private LocalDateTime observedAt;
35+
36+
@Column(name = "forecast_time", nullable = false)
37+
private LocalDateTime forecastTime;
38+
39+
@ManyToOne(fetch = FetchType.LAZY)
40+
@JoinColumn(name = "forecast_congestion_level_id", nullable = false)
41+
private CongestionLevel forecastCongestionLevel;
42+
43+
@Column(name = "forecast_population_min")
44+
private Long forecastPopulationMin;
45+
46+
@Column(name = "forecast_population_max")
47+
private Long forecastPopulationMax;
48+
49+
@Builder
50+
private OfficialCongestionForecast(
51+
OfficialPlace officialPlace,
52+
LocalDateTime observedAt,
53+
LocalDateTime forecastTime,
54+
CongestionLevel forecastCongestionLevel,
55+
Long forecastPopulationMin,
56+
Long forecastPopulationMax
57+
) {
58+
this.officialPlace = officialPlace;
59+
this.observedAt = observedAt;
60+
this.forecastTime = forecastTime;
61+
this.forecastCongestionLevel = forecastCongestionLevel;
62+
this.forecastPopulationMin = forecastPopulationMin;
63+
this.forecastPopulationMax = forecastPopulationMax;
64+
}
65+
66+
public static OfficialCongestionForecast of(
67+
OfficialPlace officialPlace,
68+
LocalDateTime observedAt,
69+
LocalDateTime forecastTime,
70+
CongestionLevel forecastCongestionLevel,
71+
Long forecastPopulationMin,
72+
Long forecastPopulationMax
73+
) {
74+
return OfficialCongestionForecast.builder()
75+
.officialPlace(officialPlace)
76+
.observedAt(observedAt)
77+
.forecastTime(forecastTime)
78+
.forecastCongestionLevel(forecastCongestionLevel)
79+
.forecastPopulationMin(forecastPopulationMin)
80+
.forecastPopulationMax(forecastPopulationMax)
81+
.build();
82+
}
83+
84+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package boombimapi.domain.place.application.service;
2+
3+
import boombimapi.domain.place.presentation.dto.request.Viewport;
4+
import boombimapi.domain.place.presentation.dto.response.MapMarker;
5+
import java.util.List;
6+
7+
public interface PlaceService {
8+
9+
List<MapMarker> getMarkersInViewport(
10+
Viewport viewport
11+
);
12+
13+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package boombimapi.domain.place.application.service.impl;
2+
3+
import boombimapi.domain.place.application.service.PlaceService;
4+
import boombimapi.domain.place.domain.entity.OfficialPlace;
5+
import boombimapi.domain.place.domain.repository.OfficialPlaceRepository;
6+
import boombimapi.domain.place.presentation.dto.request.Viewport;
7+
import boombimapi.domain.place.presentation.dto.response.MapMarker;
8+
import java.util.List;
9+
import lombok.RequiredArgsConstructor;
10+
import org.springframework.stereotype.Service;
11+
import org.springframework.transaction.annotation.Transactional;
12+
13+
@Service
14+
@RequiredArgsConstructor
15+
@Transactional(readOnly = true)
16+
public class OfficialPlaceServiceImpl implements PlaceService {
17+
18+
private final OfficialPlaceRepository officialPlaceRepository;
19+
20+
@Override
21+
public List<MapMarker> getMarkersInViewport(
22+
Viewport viewport
23+
) {
24+
25+
double latitude1 = viewport.topLeft().latitude();
26+
double longitude1 = viewport.topLeft().longitude();
27+
double latitude2 = viewport.bottomRight().latitude();
28+
double longitude2 = viewport.bottomRight().longitude();
29+
30+
double minLatitude = Math.min(latitude1, latitude2);
31+
double maxLatitude = Math.max(latitude1, latitude2);
32+
double minLongitude = Math.min(longitude1, longitude2);
33+
double maxLongitude = Math.max(longitude1, longitude2);
34+
35+
List<OfficialPlace> officialPlaces = officialPlaceRepository.findInViewport(
36+
minLatitude,
37+
maxLatitude,
38+
minLongitude,
39+
maxLongitude
40+
);
41+
42+
return officialPlaces.stream()
43+
.map(MapMarker::fromEntity)
44+
.toList();
45+
46+
}
47+
}

0 commit comments

Comments
 (0)