Skip to content

Commit ef9f446

Browse files
authored
[FEAT] 모임 위도와 경도 추가
[FEAT] 모임 위도와 경도 추가
2 parents f8bd722 + 5811cc8 commit ef9f446

13 files changed

Lines changed: 105 additions & 38 deletions

File tree

src/main/java/team/wego/wegobackend/group/application/service/v1/GroupService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ private boolean upsertAttend(Group group, User member, GroupUser groupUser) {
234234

235235
@Transactional
236236
public GetGroupResponse attendGroup(CustomUserDetails userDetails, Long groupId) {
237+
// 1. 현재 참석자 수(count)를 조회한다
238+
// 2. count < maxParticipants면 참석 처리한다
239+
// 3. 저장한다
240+
237241
Long userId = userDetails.getId();
238242

239243
Group group = findActiveGroup(groupId);

src/main/java/team/wego/wegobackend/group/domain/exception/GroupErrorCode.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,17 @@ public enum GroupErrorCode implements ErrorCode {
202202
ALREADY_REQUESTED_TO_JOIN(HttpStatus.BAD_REQUEST, "모임: 이미 가입 요청한 상태입니다. 모임 ID: %s 회원 ID: %s"),
203203
DUPLICATED_IMAGE_KEY_IN_REQUEST(HttpStatus.BAD_REQUEST, "모임: 이미지 키가 중복되었습니다."),
204204

205-
GROUP_CHAT_ROOM_NOT_FOUND_BY_ID(HttpStatus.NOT_FOUND, "모임: 모임 채팅방을 찾을 수 없습니다. 모임 ID: %s");
205+
GROUP_CHAT_ROOM_NOT_FOUND_BY_ID(HttpStatus.NOT_FOUND, "모임: 모임 채팅방을 찾을 수 없습니다. 모임 ID: %s"),
206+
207+
// 위치(좌표) 검증
208+
LOCATION_COORDINATES_INVALID(HttpStatus.BAD_REQUEST,
209+
"모임: 위도(latitude)와 경도(longitude)는 함께 전달되어야 합니다."),
210+
211+
LOCATION_LATITUDE_OUT_OF_RANGE(HttpStatus.BAD_REQUEST,
212+
"모임: 위도(latitude) 범위가 올바르지 않습니다. (허용: -90~90)"),
213+
214+
LOCATION_LONGITUDE_OUT_OF_RANGE(HttpStatus.BAD_REQUEST,
215+
"모임: 경도(longitude) 범위가 올바르지 않습니다. (허용: -180~180)");
206216

207217
private final HttpStatus status;
208218
private final String message;

src/main/java/team/wego/wegobackend/group/v2/application/dto/common/Address.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@
22

33
import team.wego.wegobackend.group.v2.domain.entity.GroupV2Address;
44

5-
public record Address(String location, String locationDetail) {
6-
5+
public record Address(
6+
String location,
7+
String locationDetail,
8+
Double latitude,
9+
Double longitude
10+
) {
711
public static Address from(GroupV2Address address) {
8-
return new Address(address.getLocation(), address.getLocationDetail());
12+
return new Address(
13+
address.getLocation(),
14+
address.getLocationDetail(),
15+
address.getLatitude(),
16+
address.getLongitude()
17+
);
918
}
10-
}
19+
}

src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ public record CreateGroupV2Request(
2020

2121
String locationDetail,
2222

23+
Double latitude,
24+
25+
Double longitude,
26+
2327
@NotNull(message = "모임: 시작 시간은 필수 입니다.")
2428
@FutureOrPresent(message = "모임: 시작 시간은 현재 이후여야 합니다.")
2529
LocalDateTime startTime,

src/main/java/team/wego/wegobackend/group/v2/application/dto/request/UpdateGroupV2Request.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public record UpdateGroupV2Request(
2525
String location,
2626
String locationDetail,
2727

28+
Double latitude,
29+
Double longitude,
30+
2831
@FutureOrPresent(message = "모임: 시작 시간은 현재 이후여야 합니다.")
2932
LocalDateTime startTime,
3033

src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ public AttendanceGroupV2Response attend(Long userId, Long groupId, String messag
5757

5858
// 모임 체크: for update로 가져오기
5959
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
60-
.orElseThrow(
61-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
60+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
6261

6362
// HOST는 참석 불가능(모임 생성 시 이미 참가된 상태)
6463
if (group.getHost().getId().equals(userId)) {
@@ -171,14 +170,10 @@ public AttendanceGroupV2Response attend(Long userId, Long groupId, String messag
171170

172171
@Transactional
173172
public AttendanceGroupV2Response left(Long userId, Long groupId) {
174-
if (userId == null) {
175-
throw new GroupException(GroupErrorCode.USER_ID_NULL);
176-
}
173+
if (userId == null) throw new GroupException(GroupErrorCode.USER_ID_NULL);
177174

178175
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
179-
.orElseThrow(
180-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID,
181-
groupId));
176+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
182177

183178
// HOST는 나가기/신청취소 불가
184179
if (group.getHost().getId().equals(userId)) {
@@ -237,8 +232,7 @@ public GroupUserV2StatusResponse approve(Long approverUserId, Long groupId,
237232
}
238233

239234
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
240-
.orElseThrow(
241-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
235+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
242236

243237
// 승인제 모임만 가능
244238
if (group.getJoinPolicy() != GroupV2JoinPolicy.APPROVAL_REQUIRED) {
@@ -324,8 +318,7 @@ public GroupUserV2StatusResponse reject(Long approverUserId, Long groupId,
324318
}
325319

326320
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
327-
.orElseThrow(
328-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
321+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
329322

330323
if (group.getJoinPolicy() != GroupV2JoinPolicy.APPROVAL_REQUIRED) {
331324
throw new GroupException(GroupErrorCode.GROUP_JOIN_POLICY_NOT_APPROVAL_REQUIRED,
@@ -387,8 +380,7 @@ public GroupUserV2StatusResponse kick(Long kickerUserId, Long groupId, Long targ
387380
}
388381

389382
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
390-
.orElseThrow(
391-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
383+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
392384

393385
// HOST only
394386
if (!group.getHost().getId().equals(kickerUserId)) {
@@ -442,8 +434,7 @@ public GroupUserV2StatusResponse ban(Long bannerUserId, Long groupId, Long targe
442434
}
443435

444436
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
445-
.orElseThrow(
446-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
437+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
447438

448439
// HOST only
449440
if (!group.getHost().getId().equals(bannerUserId)) {
@@ -553,8 +544,7 @@ public GroupUserV2StatusResponse unban(Long requesterUserId, Long groupId, Long
553544
}
554545

555546
GroupV2 group = groupV2Repository.findByIdForUpdate(groupId)
556-
.orElseThrow(
557-
() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
547+
.orElseThrow(() -> new GroupException(GroupErrorCode.GROUP_NOT_FOUND_BY_ID, groupId));
558548

559549
// HOST만 가능
560550
if (!group.getHost().getId().equals(requesterUserId)) {

src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,12 @@ public CreateGroupV2Response create(Long userId, CreateGroupV2Request request) {
211211
host.increaseGroupJoinedCount();
212212

213213
// 모임 주소 생성
214-
GroupV2Address address = GroupV2Address.of(request.location(), request.locationDetail());
214+
GroupV2Address address = GroupV2Address.of(
215+
request.location(),
216+
request.locationDetail(),
217+
request.latitude(),
218+
request.longitude()
219+
);
215220

216221
// 모임 생성
217222
GroupV2 group = GroupV2.create(

src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2UpdateService.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,30 @@ private void applyScalarUpdates(GroupV2 group, Long groupId, UpdateGroupV2Reques
132132
group.changeDescription(request.description());
133133
}
134134

135-
if (request.location() != null || request.locationDetail() != null) { // 주소
136-
String newLocation = request.location() != null
135+
if (request.location() != null
136+
|| request.locationDetail() != null
137+
|| request.latitude() != null
138+
|| request.longitude() != null) {
139+
140+
GroupV2Address cur = group.getAddress();
141+
142+
String newLocation = (request.location() != null)
137143
? request.location()
138-
: group.getAddress().getLocation();
144+
: cur.getLocation();
139145

140-
String newDetail = request.locationDetail() != null
146+
String newDetail = (request.locationDetail() != null)
141147
? request.locationDetail()
142-
: group.getAddress().getLocationDetail();
148+
: cur.getLocationDetail();
149+
150+
Double newLat = (request.latitude() != null || request.longitude() != null)
151+
? request.latitude()
152+
: cur.getLatitude();
153+
154+
Double newLng = (request.latitude() != null || request.longitude() != null)
155+
? request.longitude()
156+
: cur.getLongitude();
143157

144-
group.changeAddress(GroupV2Address.of(newLocation, newDetail));
158+
group.changeAddress(GroupV2Address.of(newLocation, newDetail, newLat, newLng));
145159
}
146160

147161
// 시간: 둘 중 하나만 와도 엔티티가 최종 검증하도록 설계했으면 각각 호출

src/main/java/team/wego/wegobackend/group/v2/application/service/PreUploadedGroupImageOrphanGcWorker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class PreUploadedGroupImageOrphanGcWorker {
2626
// 한 번에 너무 많이 지우지 않도록 제한
2727
private static final int BATCH_LIMIT = 200;
2828

29-
// 10분마다 정도면 충분히 안정적
29+
// 10분마다 정도면 충분히 안정적으로 판단
3030
@Scheduled(fixedDelay = 10 * 60 * 1000L)
3131
public void gc() {
3232
long thresholdEpochSec = Instant.now().minus(ORPHAN_GRACE).getEpochSecond();

src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2Address.java

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,42 @@ public class GroupV2Address {
1919
@Column(name = "location_detail", length = 255)
2020
private String locationDetail;
2121

22-
private GroupV2Address(String location, String locationDetail) {
22+
@Column(name = "latitude", length = 255)
23+
private Double latitude;
24+
25+
@Column(name = "longitude", length = 255)
26+
private Double longitude;
27+
28+
private GroupV2Address(String location, String locationDetail, Double latitude,
29+
Double longitude) {
2330
if (location == null || location.isBlank()) {
2431
throw new GroupException(GroupErrorCode.LOCATION_REQUIRED);
2532
}
26-
this.location = location;
33+
34+
// 위/경도는 둘 다 있거나 둘 다 없어야 함
35+
if ((latitude == null) != (longitude == null)) {
36+
throw new GroupException(GroupErrorCode.LOCATION_COORDINATES_INVALID);
37+
}
38+
39+
// 범위 검증(둘 다 있을 때만)
40+
if (latitude != null) {
41+
if (latitude < -90 || latitude > 90) {
42+
throw new GroupException(GroupErrorCode.LOCATION_LATITUDE_OUT_OF_RANGE);
43+
}
44+
if (longitude < -180 || longitude > 180) {
45+
throw new GroupException(GroupErrorCode.LOCATION_LONGITUDE_OUT_OF_RANGE);
46+
}
47+
}
48+
49+
this.location = location.trim();
2750
this.locationDetail = locationDetail;
51+
this.latitude = latitude;
52+
this.longitude = longitude;
2853
}
2954

30-
public static GroupV2Address of(String location, String locationDetail) {
31-
return new GroupV2Address(location, locationDetail);
55+
public static GroupV2Address of(String location, String locationDetail, Double latitude,
56+
Double longitude) {
57+
return new GroupV2Address(location, locationDetail, latitude, longitude);
3258
}
3359
}
3460

0 commit comments

Comments
 (0)