Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
bce7dbc
feat : 닉네임 중복 체크 (nickname unique), 인증코드 검사 예외처리 추가
yyytir777 Dec 8, 2025
3573613
fix : user_id IDENTITY strategy & dev redis host 이름변경 (localhost -> r…
yyytir777 Dec 8, 2025
08cfb63
test코드 생성 & swagger url 삭제 & 환경변수 중복 삭제
yyytir777 Dec 8, 2025
ac96fa0
fix : 엔드포인트 추가
yyytir777 Dec 9, 2025
43e75ed
Merge pull request #27 from tinybite-2025/feature/13-user
yyytir777 Dec 9, 2025
a70941b
Feature/26 notification (#29)
marshmallowing Dec 11, 2025
cbbf597
feat : google login 구현 완료
yyytir777 Dec 11, 2025
d03fd30
fix : main push 시에만 workflow trigger
yyytir777 Dec 11, 2025
00cc289
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
yyytir777 Dec 11, 2025
729ae0a
Feature/#28 google apple login
yyytir777 Dec 16, 2025
b5c29db
Merge branch 'main' into develop
yyytir777 Dec 16, 2025
2e5da55
Merge branch 'develop' of https://github.com/tinybite-2025/tinybite-s…
yyytir777 Dec 18, 2025
1fbd896
merge main into develop : main의 핫픽스 변경사항 develop에 반영
yyytir777 Dec 18, 2025
dd9771a
workflow 줄바꿈 에러 수정
yyytir777 Dec 18, 2025
38de611
hotifx : 에러 핸들링 수정 및 무중단 배포 삭제 (리소스 너무 많이 먹음)
yyytir777 Dec 19, 2025
91b8cba
main의 핫픽스 develop에 반영
yyytir777 Dec 22, 2025
fbc5e90
수정사항 반영 (API 인증 관련, db schema, 예외 처리 등..)
yyytir777 Dec 23, 2025
7b9fb7b
main브랜치 핫픽스 반영
yyytir777 Dec 24, 2025
bbb080f
Feature/35 term (#38)
yyytir777 Dec 24, 2025
4c352aa
fix : docker compose 명령어 수정
yyytir777 Dec 24, 2025
27dfcbb
Feature : 파티 기능 (#42)
milowon Dec 27, 2025
0de3a43
Merge branch 'main' into develop
milowon Dec 31, 2025
2f27dee
hotfix : url parser 경로 제거
milowon Dec 31, 2025
6eb0d8d
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 1, 2026
3f69bc1
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 2, 2026
45191a9
hotfix : 파티 거리 계산 로직 임시 주석 처리
milowon Jan 2, 2026
3a9a6e6
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 2, 2026
b2ca1f4
hotfix : 파티 수정, 삭제 controller 추가
milowon Jan 2, 2026
38ab16c
hotfix : 선택 값들이 존재할때만 넣도록 수정
milowon Jan 2, 2026
037d2e4
hotfix : 위도, 경도 로직 삭제
milowon Jan 2, 2026
9d305f8
Feat : 마이페이지 참여중인 파티 조회 (#50)
milowon Jan 2, 2026
1cee657
hotfix : user service에 transactional 어노테이션 추가
milowon Jan 2, 2026
5213214
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 2, 2026
ed3a399
hotfix : 참여중 파티 조회 반환 형식 통일
milowon Jan 2, 2026
374f720
hotfix : 파티 생성, 조회 시, 거리 계산 로직 반영
milowon Jan 2, 2026
4ddfa39
Hotfix: 유저 좌표 입력 requestParam 형식으로 변경
milowon Jan 2, 2026
42bc4d4
Merge branch 'main' into develop
milowon Jan 2, 2026
9ee078a
Merge branch 'main' into develop
milowon Jan 2, 2026
3be9d38
hotfix : 누락된 swagger 문서 수정사항 반영
milowon Jan 2, 2026
89bbef3
Merge branch 'main' into develop
milowon Jan 2, 2026
b281a29
feat : 회원 탈퇴 및 재가입 방지, 검증 (#65)
milowon Jan 2, 2026
35a62b7
fix : 파티 수정 버그 픽스 (#67)
milowon Jan 2, 2026
a4f3582
hotfix : 탈퇴 유저 마스킹 로직 변경
milowon Jan 3, 2026
9f05a6a
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 3, 2026
d802e15
feat : 마이페이지에서 참여중,호스트인 파티 구분해서 조회 (#71)
milowon Jan 4, 2026
8715584
Feature/73 search party (#74)
yyytir777 Jan 4, 2026
78349d6
fix : 스웨거 description 추가
yyytir777 Jan 4, 2026
ba3d9d8
Merge branch 'main' into develop
yyytir777 Jan 4, 2026
c15e45b
Feature/73 search party (#76)
yyytir777 Jan 4, 2026
92bef29
Merge branch 'main' into develop
yyytir777 Jan 4, 2026
bd136de
Fix : 호스트만 있을때는 파티 수정할 수 있도록 변경 (#78)
milowon Jan 4, 2026
5d3e13d
fix : 파티 삭제시 호스트는 현재인원에서 제외하도록 수정 (#80)
milowon Jan 4, 2026
1e5b600
hotfix : jpa 네이밍 및 쿼리 수정
yyytir777 Jan 4, 2026
ba4ed25
hotfix : jpa 네이밍 및 쿼리 수정
yyytir777 Jan 4, 2026
c2d9465
Merge branch 'main' into develop
yyytir777 Jan 4, 2026
0b783c7
feat : 파티 카테고리, 최신순, 거리순 정렬 (#83)
milowon Jan 4, 2026
4474664
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 4, 2026
3353068
Feature/44 chat (#82)
yyytir777 Jan 6, 2026
6e2450c
hotfix : 파티 삭제 되지 않는 문제 수정 (#86)
milowon Jan 6, 2026
b9630cf
hotfix : 파티 수정사항이 db에 반영 되지 않는 문제 수정
milowon Jan 6, 2026
866bb84
feat : 유저 프로필 이미지 수정, 삭제 (#89)
milowon Jan 6, 2026
e1fc441
Fix : 유저 프로필 수정, 삭제 (#91)
milowon Jan 6, 2026
64449d4
Merge branch 'main' into develop
milowon Jan 6, 2026
85f9a6e
hotfix: 유저 정보 조회시 프로필 이미지 반환하도록 수정
milowon Jan 9, 2026
17485c9
Fix/party search (#94)
yyytir777 Jan 9, 2026
e77c560
feat: 파티 참여, 거절, 종료 알림 연결 (#97)
marshmallowing Jan 10, 2026
2826cae
fix : 마이페이지에서 참여중, 호스트 파티 조회시 최신순으로 조회되도록 수정 (#98)
milowon Jan 10, 2026
cf0f51d
Merge branch 'main' into develop
milowon Jan 10, 2026
f02e7eb
feat : 파티 생성시 이미지 없을 경우 디폴트 이미지 반환하도록 수정 (#100)
milowon Jan 10, 2026
72accaf
feat: 채팅 알림 단체/개인 구분 (#102)
marshmallowing Jan 10, 2026
8fa6f24
fix : 채팅방 유형 별 알림 변경
yyytir777 Jan 10, 2026
0707f62
Feat : 파티 목록 디폴트 이미지 필드 추가 (#104)
milowon Jan 10, 2026
02c3e16
Fix : 파티 썸네일 이미지 주입되도록 value값 수정 (#106)
milowon Jan 10, 2026
5c230a6
Merge branch 'main' into develop
milowon Jan 10, 2026
7611fd9
Feature/44 chat (#107)
yyytir777 Jan 10, 2026
0a416c4
hotfix: 파티 세부 조회시 디폴트 이미지 필드 수정
milowon Jan 10, 2026
69c48b8
Feature/103 파티장 리마인드 알림 (#110)
marshmallowing Jan 10, 2026
0f4ea15
Merge branch 'main' into develop
yyytir777 Jan 10, 2026
361a3ee
Feat : 파티 추가 기능(파티 목록 페이지네이션, 파티탈퇴, 파티 모집 완료) (#113)
milowon Jan 10, 2026
d55a526
Merge branch 'main' into develop
milowon Jan 10, 2026
28af054
Feature/44 chat (#115)
yyytir777 Jan 10, 2026
01fb19b
Merge branch 'main' into develop
yyytir777 Jan 10, 2026
1a0e242
Feat : host 위치 추가
milowon Jan 12, 2026
891110c
Merge branch 'main' into develop
milowon Jan 12, 2026
50b4db5
Feature/chatroom detail (#118)
yyytir777 Jan 13, 2026
a6401d0
Feature/chatroom detail (#120)
yyytir777 Jan 13, 2026
45af129
Merge branch 'main' into develop
yyytir777 Jan 13, 2026
41d9b7d
feat : 파티 정렬 항상 거리순으로 수정 + 동네 기준으로 파티 조회 (#122)
milowon Jan 13, 2026
c3748dc
Merge branch 'main' of https://github.com/tinybite-2025/tinybite-serv…
milowon Jan 14, 2026
8da39b7
Refactor: 파티 조회 시 거리 정보 반환 및 API 개선 (#124)
milowon Jan 14, 2026
f96bab4
feat: 알림 테스트용 API (#127)
marshmallowing Jan 14, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import ita.tinybite.domain.notification.dto.request.FcmTokenRequest;
import ita.tinybite.domain.notification.service.FcmTokenService;
import ita.tinybite.domain.notification.service.facade.NotificationFacade;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

Expand All @@ -18,6 +20,7 @@
public class FcmTokenController {

private final FcmTokenService fcmTokenService;
private final NotificationFacade notificationFacade;

// token 이미 존재 시 업데이트 해줌
@PostMapping("/token")
Expand All @@ -26,4 +29,10 @@ public ResponseEntity<Void> registerToken(@RequestBody @Valid FcmTokenRequest re
fcmTokenService.saveOrUpdateToken(currentUserId, request.token());
return ResponseEntity.noContent().build();
}

@PostMapping("/Test")
public ResponseEntity<Void> test(@RequestParam Long userId) {
notificationFacade.notifyTest(userId);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public enum NotificationType {
// 파티 참여 리마인드
PENDING_APPROVAL_REMINDER,

// 테스트 알림
TEST_EVENT,

// 마케팅 알림
MARKETING_LOCAL_NEW_PARTY,
MARKETING_WEEKLY_POPULAR,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ita.tinybite.domain.notification.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.firebase.messaging.BatchResponse;

import ita.tinybite.domain.notification.dto.request.NotificationMulticastRequest;
import ita.tinybite.domain.notification.enums.NotificationType;
import ita.tinybite.domain.notification.infra.fcm.FcmNotificationSender;
import ita.tinybite.domain.notification.infra.helper.NotificationTransactionHelper;
import ita.tinybite.domain.notification.service.manager.TestMessageManager;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class TestNotificationService {
private final FcmNotificationSender fcmNotificationSender;
private final FcmTokenService fcmTokenService;
private final TestMessageManager testMessageManager;
private final NotificationLogService notificationLogService;
private final NotificationTransactionHelper notificationTransactionHelper;

@Transactional
public void sendTestNotification(Long targetUserId) {
String title = "알림 테스트 제목";
String detail = "알림 테스트 내용";

notificationLogService.saveLog(targetUserId, NotificationType.TEST_EVENT.name(), title, detail);

List<String> tokens = fcmTokenService.getTokensAndLogIfEmpty(targetUserId);
if (tokens.isEmpty())
return;

NotificationMulticastRequest request = testMessageManager.createTestRequest(tokens, title, detail);

BatchResponse response = fcmNotificationSender.send(request);
notificationTransactionHelper.handleBatchResponse(response, tokens);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import ita.tinybite.domain.notification.service.ChatNotificationService;
import ita.tinybite.domain.notification.service.PartyNotificationService;
import ita.tinybite.domain.notification.service.TestNotificationService;
import ita.tinybite.domain.party.entity.Party;
import ita.tinybite.domain.party.enums.ParticipantStatus;
import ita.tinybite.domain.party.repository.PartyParticipantRepository;
Expand All @@ -31,14 +32,21 @@ public class NotificationFacade {

private final PartyNotificationService partyNotificationService;
private final ChatNotificationService chatNotificationService;
private final TestNotificationService testNotificationService;

private final PartyRepository partyRepository;
private final UserRepository userRepository;
private final PartyParticipantRepository partyParticipantRepository;

private final RedisTemplate<String, String> redisTemplate;

@Transactional
public void notifyTest(Long targetUserId) {
userRepository.findById(targetUserId)
.orElseThrow(() -> new BusinessException(UserErrorCode.USER_NOT_EXISTS));

testNotificationService.sendTestNotification(targetUserId);
}

public void notifyNewPartyRequest(Long managerId, Long requesterId, Long partyId) {
Party party = partyRepository.findById(partyId)
.orElseThrow(() -> new BusinessException(PartyErrorCode.PARTY_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ita.tinybite.domain.notification.service.manager;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import ita.tinybite.domain.notification.converter.NotificationRequestConverter;
import ita.tinybite.domain.notification.dto.request.NotificationMulticastRequest;
import ita.tinybite.domain.notification.enums.NotificationType;
import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor
public class TestMessageManager {

private final NotificationRequestConverter requestConverter;

public NotificationMulticastRequest createTestRequest(List<String> tokens, String title, String detail) {
Map<String, String> data = new HashMap<>();
data.put("eventType", NotificationType.TEST_EVENT.name());

return requestConverter.toMulticastRequest(tokens, title, detail, data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public ResponseEntity<?> completeRecruitment(
content = @Content
)
})
@PostMapping("{partyId}/participants/{participantId}/approve")
@PostMapping("/{partyId}/participants/{participantId}/approve")
public ResponseEntity<Void> approveParticipant(
@PathVariable Long partyId,
@PathVariable Long participantId,
Expand Down Expand Up @@ -262,7 +262,7 @@ public ResponseEntity<Void> rejectParticipant(
content = @Content
)
})
@GetMapping("{partyId}/chat/group")
@GetMapping("/{partyId}/chat/group")
public ResponseEntity<ChatRoomResponse> getGroupChatRoom(
@PathVariable Long partyId,
@Parameter(hidden = true) @AuthenticationPrincipal Long userId) {
Expand All @@ -285,7 +285,7 @@ public ResponseEntity<ChatRoomResponse> getGroupChatRoom(
content = @Content
)
})
@GetMapping("{partyId}/can-settle")
@GetMapping("/{partyId}/can-settle")
public ResponseEntity<Boolean> canSettle(@PathVariable Long partyId) {
boolean canSettle = partyService.canSettle(partyId);
return ResponseEntity.ok(canSettle);
Expand Down Expand Up @@ -319,7 +319,7 @@ public ResponseEntity<Boolean> canSettle(@PathVariable Long partyId) {
content = @Content
)
})
@PostMapping("{partyId}/settle")
@PostMapping("/{partyId}/settle")
public ResponseEntity<Void> settleParty(
@PathVariable Long partyId,
@Parameter(hidden = true) @AuthenticationPrincipal Long userId) {
Expand Down Expand Up @@ -352,7 +352,7 @@ public ResponseEntity<Void> settleParty(
content = @Content
)
})
@GetMapping("{partyId}/participants/pending")
@GetMapping("/{partyId}/participants/pending")
public ResponseEntity<List<PartyParticipant>> getPendingParticipants(
@PathVariable Long partyId,
@Parameter(hidden = true) @AuthenticationPrincipal Long userId) {
Expand All @@ -365,6 +365,27 @@ public ResponseEntity<List<PartyParticipant>> getPendingParticipants(
/**
* 파티 목록 조회 (홈 화면)
*/
@Operation(
summary = "파티 목록 조회",
description = "홈 화면에서 파티 목록을 조회합니다. 카테고리별 필터링, 정렬, 위치 기반 조회를 지원합니다."
)
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content = @Content(schema = @Schema(implementation = PartyListResponse.class))
),
@ApiResponse(
responseCode = "400",
description = "잘못된 요청 (위치 정보 형식 오류)",
content = @Content
),
@ApiResponse(
responseCode = "401",
description = "인증 실패",
content = @Content
)
})
@GetMapping
public ResponseEntity<PartyListResponse> getPartyList(
@Parameter(hidden = true) @AuthenticationPrincipal Long userId,
Expand All @@ -380,9 +401,6 @@ public ResponseEntity<PartyListResponse> getPartyList(
) {
Double lat = null;
Double lon = null;
// if (userLat == null || userLon == null) {
// throw new IllegalArgumentException("거리순 정렬을 위해서는 현재 위치 정보가 필요합니다.");
// }

if (latitude != null && longitude != null) {
try {
Expand Down Expand Up @@ -577,6 +595,18 @@ public ResponseEntity<Void> deleteParty(
몇 번째 페이지 인지 (page), 한 페이지 당 몇 개의 파티를 조회할 지 (size) 파라미터로 입력해주시면 됩니다.
"""
)
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "검색 성공",
content = @Content(schema = @Schema(implementation = PartyQueryListResponse.class))
),
@ApiResponse(
responseCode = "400",
description = "잘못된 요청 (검색어 누락)",
content = @Content
)
})
@GetMapping("/search")
public APIResponse<PartyQueryListResponse> getParty(
@RequestParam String q,
Expand All @@ -602,6 +632,17 @@ public APIResponse<PartyQueryListResponse> getParty(
한 번에 20개가 조회됩니다.
"""
)
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "조회 성공"
),
@ApiResponse(
responseCode = "401",
description = "인증 실패",
content = @Content
)
})
@GetMapping("/search/log")
public APIResponse<List<String>> getRecentLog() {
return success(partySearchService.getLog());
Expand All @@ -614,6 +655,17 @@ public APIResponse<List<String>> getRecentLog() {
이때 검색어에 대한 Id값은 없고, 최근 검색어 자체를 keyword에 넣어주시면 됩니다.
"""
)
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "삭제 성공"
),
@ApiResponse(
responseCode = "401",
description = "인증 실패",
content = @Content
)
})
@DeleteMapping("/search/log/{keyword}")
public APIResponse<?> deleteRecentLog(@PathVariable String keyword) {
partySearchService.deleteLog(keyword);
Expand All @@ -626,6 +678,17 @@ public APIResponse<?> deleteRecentLog(@PathVariable String keyword) {
특정 유저에 대한 모든 최근 검색어를 삭제합니다.
"""
)
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "전체 삭제 성공"
),
@ApiResponse(
responseCode = "401",
description = "인증 실패",
content = @Content
)
})
@DeleteMapping("/search/log")
public APIResponse<?> deleteRecentLogAll() {
partySearchService.deleteAllLog();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,36 @@ public class PartyCardResponse {
private LocalDateTime createdAt;

public static PartyCardResponse from(Party party, int currentParticipants) {
return from(party, currentParticipants, null, null);
}

public static PartyCardResponse from(Party party, int currentParticipants, Double userLat, Double userLon) {
String distanceValue = null;
String distanceKmValue = null;

// 거리 계산
if (userLat != null && userLon != null
&& party.getPickupLocation() != null
&& party.getPickupLocation().getPickupLatitude() != null
&& party.getPickupLocation().getPickupLongitude() != null) {
double distance = DistanceCalculator.calculateDistance(
userLat,
userLon,
party.getPickupLocation().getPickupLatitude(),
party.getPickupLocation().getPickupLongitude()
);
distanceKmValue = DistanceCalculator.formatDistance(distance);
distanceValue = Double.toString(distance);
}

return PartyCardResponse.builder()
.partyId(party.getId())
.thumbnailImage(party.getThumbnailImage())
.title(party.getTitle())
.pricePerPerson(calculatePricePerPerson(party, currentParticipants))
.participantStatus(formatParticipantStatus(currentParticipants, party.getMaxParticipants()))
.distance(null) // 거리 계산은 별도 처리 필요
.distanceKm(null) // 거리 계산은 별도 처리 필요
.distance(distanceValue)
.distanceKm(distanceKmValue)
.timeAgo(calculateTimeAgo(party.getCreatedAt()))
.isClosed(checkIfClosed(party, currentParticipants))
.category(party.getCategory())
Expand Down
Loading