Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 0.4.1 #196

Merged
merged 25 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8d67d1f
feat: 리뷰 등록시 회원 매너 온도 반영 기능 추가 및 리뷰 등록 리팩토링 (#158)
choidongkuen Jan 28, 2024
d940870
Merge branch 'main' into develop
devxb Jan 28, 2024
2a13014
test: MeetingRepository 테스트에서 시간과 id비교 비활서화
devxb Jan 28, 2024
d2ff7bf
refactor: 회원 탈퇴 URI 변경 (#162)
choidongkuen Jan 29, 2024
cbd09bf
feat: fcm token 업데이트 api 추가 (#166)
devxb Jan 30, 2024
eeb01f5
fix: 모임 수정 시 이미지가 추가되는 버그 수정 (#169)
ddingmin Jan 30, 2024
539d24e
Merge remote-tracking branch 'origin/main' into develop
devxb Jan 30, 2024
d621bd6
perf: upgrade GPT-3.5 to GPT-4 (#174)
devxb Feb 1, 2024
98a2037
refactor: 위치 기반 데이터 값 유효기간 변경
choidongkuen Feb 3, 2024
cf08ef1
Merge branch 'develop' of https://github.com/depromeet/teum-teum-serv…
choidongkuen Feb 3, 2024
c0fbe70
Merge remote-tracking branch 'origin/main' into develop
choidongkuen Feb 3, 2024
83e2327
refactor: 위치 기반 데이터 값 유효기간 변경
choidongkuen Feb 3, 2024
b4cb5b2
Merge remote-tracking branch 'origin/main' into develop
choidongkuen Feb 3, 2024
ef04cd4
refactor: 위치 기반 데이터 값 유효기간 변경
choidongkuen Feb 3, 2024
0357d19
feat: 모임 종료, 사용자 추천 알림을 추가 (#182)
devxb Feb 9, 2024
be58b5b
feat: 유저가 한달 동안 받은 알람을 조회하는 기능 개발 (#185)
devxb Feb 10, 2024
a2a901c
feat: 북마크 추가, 취소 기능 구현 (#184)
ddingmin Feb 10, 2024
e88622d
Merge remote-tracking branch 'origin/main' into develop
devxb Feb 10, 2024
ec5e29c
fix: flyway_schema alert userId를 user_id로 변경한다
devxb Feb 10, 2024
afa2e3b
fix: flyway 13 의 alert table문을 변경한다
devxb Feb 10, 2024
197467f
Merge remote-tracking branch 'origin/main' into develop
devxb Feb 11, 2024
bc220a5
refactor: 알람 조회에 읽은알람인지, 언제 발행되었는지를 추가 (#189)
devxb Feb 11, 2024
53d28ce
feat: 회원탈퇴, 로그아웃 시, 회원 위치 데이터 삭제 로직 추가 및 위치 데이터 유효기간 변경 (#179)
choidongkuen Feb 11, 2024
016c3c5
feat: 모임 참여자 정보 조회 기능을 구현 (#192)
choidongkuen Feb 11, 2024
f3699f1
refactor: 리뷰 피드백 및 테스트 코드 추가 구현 (#194)
choidongkuen Feb 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/main/java/net/teumteum/alert/app/AlertHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void handleBeforeMeetingAlerts(BeforeMeetingAlerted alerted) {
.stream()
.map(userAlert -> Pair.of(userAlert.getToken(),
new Alert(null, userAlert.getUserId(), "5분 뒤에 모임이 시작돼요!",
"모임 장소로 가서 틈틈 모임을 준비해주세요.", AlertType.BEFORE_MEETING)))
"모임 장소로 가서 틈틈 모임을 준비해주세요.", AlertType.BEFORE_MEETING, true)))
.map(tokenAndAlert -> Pair.of(tokenAndAlert.getFirst(), alertService.save(tokenAndAlert.getSecond())))
.forEach(
tokenAndAlert -> alertPublisher.publish(tokenAndAlert.getFirst(), tokenAndAlert.getSecond(), Map.of())
Expand All @@ -50,7 +50,7 @@ public void handleStartMeetingAlerts(EndMeetingAlerted alerted) {
.stream()
.map(userAlert -> Pair.of(userAlert.getToken(),
new Alert(null, userAlert.getUserId(), alerted.meetingTitle(),
"모임이 종료되었어요", AlertType.END_MEETING)))
"모임이 종료되었어요", AlertType.END_MEETING, true)))
.map(tokenAndAlert -> Pair.of(tokenAndAlert.getFirst(), alertService.save(tokenAndAlert.getSecond())))
.forEach(tokenAndAlert ->
alertPublisher.publish(tokenAndAlert.getFirst(), tokenAndAlert.getSecond(),
Expand All @@ -75,7 +75,7 @@ public void handleUserRecommended(UserRecommended alerted) {
.stream()
.map(userAlert -> Pair.of(userAlert.getToken(),
new Alert(null, userAlert.getUserId(), "틈 채우기",
alerted.recommenderName() + "님이 당신을 추천했어요!", AlertType.RECOMMEND_USER)))
alerted.recommenderName() + "님이 당신을 추천했어요!", AlertType.RECOMMEND_USER, true)))
.map(tokenAndAlert -> Pair.of(tokenAndAlert.getFirst(), alertService.save(tokenAndAlert.getSecond())))
.forEach(tokenAndAlert ->
alertPublisher.publish(tokenAndAlert.getFirst(), tokenAndAlert.getSecond(), Map.of())
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/net/teumteum/alert/domain/Alert.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class Alert extends TimeBaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "userId", nullable = false)
@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "title", nullable = false, length = 20)
Expand All @@ -37,4 +37,11 @@ public class Alert extends TimeBaseEntity {
@Column(name = "type")
@Enumerated(EnumType.STRING)
private AlertType type;

@Column(name = "is_read", nullable = false)
private Boolean isRead;

public void read() {
isRead = true;
}
}
6 changes: 5 additions & 1 deletion src/main/java/net/teumteum/alert/domain/AlertService.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ public Alert save(Alert alert) {
return alertRepository.save(alert);
}

@Transactional
public AlertsResponse findAllByUserId(Long userId) {
return AlertsResponse.of(alertRepository.findAllByUserId(userId));
var alerts = alertRepository.findAllByUserId(userId);
var alertsResponse = AlertsResponse.of(alerts);
alerts.forEach(Alert::read);
return alertsResponse;
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.teumteum.alert.domain.response;

import java.time.Instant;
import java.util.List;
import net.teumteum.alert.domain.Alert;

Expand All @@ -10,15 +11,23 @@ public record AlertsResponse(
public static AlertsResponse of(List<Alert> alerts) {
return new AlertsResponse(
alerts.stream()
.map(alert -> new AlertResponse(alert.getTitle(), alert.getBody(), alert.getType().name()))
.map(alert -> new AlertResponse(
alert.getTitle(),
alert.getBody(),
alert.getType().name(),
alert.getCreatedAt(),
alert.getIsRead()
))
.toList()
);
}

public record AlertResponse(
String title,
String body,
String type
String type,
Instant createdAt,
boolean isRead
) {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void setUserLocation(UserLocation userLocation, Long duration) {
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
setDataWithExpiration(key,value,duration);
setDataWithExpiration(key, value, duration);
}

public Set<UserLocation> getAllUserLocations() {
Expand All @@ -69,4 +69,8 @@ public Set<UserLocation> getAllUserLocations() {
}
}).collect(Collectors.toSet());
}

public void deleteUserLocation(Long id) {
deleteData(HASH_KEY + id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.request.CreateMeetingRequest;
import net.teumteum.meeting.domain.request.UpdateMeetingRequest;
import net.teumteum.meeting.domain.response.MeetingParticipantsForReviewResponse;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
import net.teumteum.meeting.model.PageDto;
Expand Down Expand Up @@ -39,8 +40,7 @@ public class MeetingController {

@PostMapping()
@ResponseStatus(HttpStatus.CREATED)
public MeetingResponse createMeeting(
@RequestPart @Valid CreateMeetingRequest meetingRequest,
public MeetingResponse createMeeting(@RequestPart @Valid CreateMeetingRequest meetingRequest,
@RequestPart List<MultipartFile> images) {
Long userId = securityService.getCurrentUserId();
return meetingService.createMeeting(images, meetingRequest, userId);
Expand All @@ -55,10 +55,8 @@ public MeetingResponse getMeetingById(@PathVariable("meetingId") Long meetingId)

@GetMapping
@ResponseStatus(HttpStatus.OK)
public PageDto<MeetingsResponse> getMeetingsByCondition(
Pageable pageable,
@RequestParam(value = "isOpen") boolean isOpen,
@RequestParam(value = "topic", required = false) Topic topic,
public PageDto<MeetingsResponse> getMeetingsByCondition(Pageable pageable,
@RequestParam(value = "isOpen") boolean isOpen, @RequestParam(value = "topic", required = false) Topic topic,
@RequestParam(value = "meetingAreaStreet", required = false) String meetingAreaStreet,
@RequestParam(value = "participantUserId", required = false) Long participantUserId,
@RequestParam(value = "searchWord", required = false) String searchWord) {
Expand All @@ -69,8 +67,7 @@ public PageDto<MeetingsResponse> getMeetingsByCondition(

@PutMapping("/{meetingId}")
@ResponseStatus(HttpStatus.OK)
public MeetingResponse updateMeeting(@PathVariable Long meetingId,
@RequestPart @Valid UpdateMeetingRequest request,
public MeetingResponse updateMeeting(@PathVariable Long meetingId, @RequestPart @Valid UpdateMeetingRequest request,
@RequestPart List<MultipartFile> images) {
Long userId = securityService.getCurrentUserId();
return meetingService.updateMeeting(meetingId, images, request, userId);
Expand All @@ -97,6 +94,12 @@ public void deleteParticipant(@PathVariable("meetingId") Long meetingId) {
meetingService.cancelParticipant(meetingId, userId);
}

@GetMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.OK)
public MeetingParticipantsForReviewResponse getParticipants(@PathVariable("meetingId") Long meetingId) {
return meetingService.getParticipants(meetingId);
}

@PostMapping("/{meetingId}/reports")
@ResponseStatus(HttpStatus.CREATED)
public void reportMeeting(@PathVariable("meetingId") Long meetingId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.teumteum.meeting.domain.response;

import java.util.List;
import net.teumteum.user.domain.User;

public record MeetingParticipantsForReviewResponse(
List<MeetingParticipantForReviewResponse> participants
) {

public static MeetingParticipantsForReviewResponse of(List<User> users) {
return new MeetingParticipantsForReviewResponse(
users.stream()
.map(user -> new MeetingParticipantForReviewResponse(
user.getId(),
user.getCharacterId(),
user.getName(),
user.getJob().getDetailJobClass()))
.toList()
);
}

public record MeetingParticipantForReviewResponse(
Long id,
Long characterId,
String name,
String job
) {

}
}
17 changes: 17 additions & 0 deletions src/main/java/net/teumteum/meeting/service/MeetingService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.teumteum.meeting.service;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import net.teumteum.meeting.domain.ImageUpload;
Expand All @@ -11,9 +12,12 @@
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.request.CreateMeetingRequest;
import net.teumteum.meeting.domain.request.UpdateMeetingRequest;
import net.teumteum.meeting.domain.response.MeetingParticipantsForReviewResponse;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
import net.teumteum.meeting.model.PageDto;
import net.teumteum.user.domain.User;
import net.teumteum.user.domain.UserConnector;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
Expand All @@ -27,6 +31,7 @@ public class MeetingService {

private final MeetingRepository meetingRepository;
private final ImageUpload imageUpload;
private final UserConnector userConnector;

@Transactional
public MeetingResponse createMeeting(List<MultipartFile> images, CreateMeetingRequest meetingRequest, Long userId) {
Expand Down Expand Up @@ -148,6 +153,18 @@ public void cancelParticipant(Long meetingId, Long userId) {
existMeeting.cancelParticipant(userId);
}

@Transactional(readOnly = true)
public MeetingParticipantsForReviewResponse getParticipants(Long meetingId) {
var existMeeting = getMeeting(meetingId);

List<User> participantUsers = existMeeting.getParticipantUserIds().stream()
.map(userConnector::findUserById)
.flatMap(Optional::stream)
.toList();

return MeetingParticipantsForReviewResponse.of(participantUsers);
}

@Transactional
public void addBookmark(Long meetingId, Long userId) {
var existMeeting = getMeeting(meetingId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package net.teumteum.teum_teum.domain.response;

import java.util.List;
import java.util.Set;
import net.teumteum.teum_teum.domain.UserLocation;

public record UserAroundLocationsResponse(
List<UserAroundLocationResponse> aroundUserLocations
) {

public static UserAroundLocationsResponse of(List<UserLocation> userData) {
public static UserAroundLocationsResponse of(Set<UserLocation> userData) {
return new UserAroundLocationsResponse(
userData.stream()
.map(UserAroundLocationResponse::of)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,43 @@
import static java.lang.Math.toRadians;
import static java.util.Comparator.comparingDouble;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.teumteum.core.security.service.RedisService;
import net.teumteum.teum_teum.domain.UserLocation;
import net.teumteum.teum_teum.domain.request.UserLocationRequest;
import net.teumteum.teum_teum.domain.response.UserAroundLocationsResponse;
import org.springframework.stereotype.Service;

@Slf4j

@Service
@RequiredArgsConstructor
public class TeumTeumService {

private static final int SEARCH_LIMIT = 6;
private static final long USER_LOCATION_DATA_DURATION = 10L;
private static final int AROUND_USER_LOCATION_DISTANCE = 100;

private final RedisService redisService;

public UserAroundLocationsResponse saveAndGetUserAroundLocations(UserLocationRequest request) {
redisService.setUserLocation(request.toUserLocation(), 60L);
redisService.setUserLocation(request.toUserLocation(), USER_LOCATION_DATA_DURATION);
return getUserAroundLocations(request);
}

private UserAroundLocationsResponse getUserAroundLocations(UserLocationRequest request) {
Set<UserLocation> allUserLocations = redisService.getAllUserLocations();

List<UserLocation> aroundUserLocations = allUserLocations.stream()
Set<UserLocation> aroundUserLocations = allUserLocations.stream()
.filter(userLocation -> !userLocation.id().equals(request.id()))
.filter(userLocation -> calculateDistance(request.latitude(), request.longitude(),
userLocation.latitude(), userLocation.longitude()) <= 100)
userLocation.latitude(), userLocation.longitude()) <= AROUND_USER_LOCATION_DISTANCE)
.sorted(comparingDouble(userLocation
-> calculateDistance(request.latitude(), request.longitude(),
userLocation.latitude(), userLocation.longitude()))
).limit(SEARCH_LIMIT)
.toList();
.collect(Collectors.toSet());

return UserAroundLocationsResponse.of(aroundUserLocations);
}
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/net/teumteum/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ public void addFriends(Long myId, Long friendId) {
public void withdraw(UserWithdrawRequest request, Long userId) {
var existUser = getUser(userId);

userRepository.delete(existUser);
redisService.deleteData(String.valueOf(userId));

userRepository.delete(existUser);

withdrawReasonRepository.saveAll(request.toEntity());
}

Expand All @@ -95,9 +96,9 @@ public UserRegisterResponse register(UserRegisterRequest request) {
return UserRegisterResponse.of(savedUser.getId(), jwtService.createServiceToken(savedUser));
}

@Transactional
public void logout(Long userId) {
redisService.deleteData(String.valueOf(userId));

SecurityService.clearSecurityContext();
}

Expand Down Expand Up @@ -143,10 +144,11 @@ public InterestQuestionResponse getInterestQuestionByUserIds(List<Long> userIds,
}

private void checkUserExistence(Authenticated authenticated, String oauthId) {
userRepository.findByAuthenticatedAndOAuthId(authenticated, oauthId)
.ifPresent(user -> {
boolean userExists = userRepository.findByAuthenticatedAndOAuthId(authenticated, oauthId).isPresent();
Assert.isTrue(!userExists, () -> {
throw new IllegalArgumentException("일치하는 user 가 이미 존재합니다.");
});
}
);
}

private void checkMeetingExistence(Long meetingId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table alert
add column is_read boolean not null;
8 changes: 8 additions & 0 deletions src/test/java/net/teumteum/integration/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,12 @@ ResponseSpec registerUserReview(String accessToken, Long meetingId, ReviewRegist
.bodyValue(request)
.exchange();
}

ResponseSpec getMeetingParticipants(String accessToken, Long meetingId) {
return webTestClient
.get()
.uri("/meetings/" + meetingId + "/participants")
.header(HttpHeaders.AUTHORIZATION, accessToken)
.exchange();
}
}
Loading
Loading