Skip to content

[Merge] #46 트래킹 사진 푸시 머지#79

Merged
JangInho merged 6 commits into
developfrom
feat/#46-tracking-photo-push
May 22, 2026
Merged

[Merge] #46 트래킹 사진 푸시 머지#79
JangInho merged 6 commits into
developfrom
feat/#46-tracking-photo-push

Conversation

@JangInho

@JangInho JangInho commented May 22, 2026

Copy link
Copy Markdown
Contributor

🧾 요약

  • 트래킹 사진 푸시 머지 피알

🔗 이슈

✨ 변경 내용

  • 트래킹 사진 푸시 머지

✅ 확인

  • 빌드 OK
  • 테스트 OK

Summary by CodeRabbit

Release Notes

  • New Features
    • Users can now upload verification photos during active tracking sessions at distance milestones
    • Photo uploads include validation and duplicate prevention
    • Automatic milestone notifications prompt users to capture photos
    • Complete photo retrieval and viewing functionality for tracking sessions
    • Error handling for inactive sessions and duplicate submissions

Review Change Stack

JangInho added 6 commits May 19, 2026 22:16
…photo-push

# Conflicts:
#	src/main/java/com/semosan/api/common/status/ErrorStatus.java
#	src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java
#	src/main/java/com/semosan/api/domain/tracking/service/TrackingStreamConsumer.java
- 003_tracking_photos.sql → V10__create_tracking_photos.sql Flyway 컨벤션 통일
- BIGSERIAL → bigint identity, FK 제약 이름 명시(fk_tracking_photos_session)
- timestamp(6), DEFAULT now() 제거 (BaseEntity 가 채움)
- notifications.type CHECK 갱신 동봉 (TRACKING_PHOTO_MILESTONE 추가)
@JangInho JangInho self-assigned this May 22, 2026
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 69963134-90ae-47c9-9c11-6c2e17d1787c

📥 Commits

Reviewing files that changed from the base of the PR and between f6b3ae4 and b586ec5.

📒 Files selected for processing (16)
  • src/main/java/com/semosan/api/common/status/ErrorStatus.java
  • src/main/java/com/semosan/api/common/status/SuccessStatus.java
  • src/main/java/com/semosan/api/domain/notification/enums/NotificationType.java
  • src/main/java/com/semosan/api/domain/tracking/controller/TrackingPhotoController.java
  • src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingPhotoControllerDocs.java
  • src/main/java/com/semosan/api/domain/tracking/dto/request/TrackingPhotoUploadRequest.java
  • src/main/java/com/semosan/api/domain/tracking/dto/response/TrackingPhotoResponse.java
  • src/main/java/com/semosan/api/domain/tracking/entity/TrackingPhoto.java
  • src/main/java/com/semosan/api/domain/tracking/repository/TrackingPhotoRepository.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingMilestoneCalculator.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingPhotoService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingPhotoTriggerService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionStatsService.java
  • src/main/java/com/semosan/api/domain/tracking/service/TrackingStreamConsumer.java
  • src/main/resources/db/migration/V10__create_tracking_photos.sql

📝 Walkthrough

Walkthrough

This PR implements a complete photo milestone tracking feature. It adds photo upload/list endpoints secured by user ownership, calculates distance-based milestones from GPS sessions, stores photos in a new entity, and triggers WebSocket and FCM notifications when users enter distance windows during active tracking.

Changes

Tracking Photo Feature

Layer / File(s) Summary
Status codes and notification types
src/main/java/com/semosan/api/common/status/ErrorStatus.java, src/main/java/com/semosan/api/common/status/SuccessStatus.java, src/main/java/com/semosan/api/domain/notification/enums/NotificationType.java
Two error codes (TRK_409_3 duplicate photo, TRK_409_4 inactive session) and two success codes (TRK_201_2 upload, TRK_200_8 list) introduced; TRACKING_PHOTO_MILESTONE notification type added with {distance}m template parameter.
Photo entity and data access
src/main/java/com/semosan/api/domain/tracking/entity/TrackingPhoto.java, src/main/java/com/semosan/api/domain/tracking/repository/TrackingPhotoRepository.java
TrackingPhoto JPA entity stores milestone photos indexed by session and (session, milestone index); repository provides queries to fetch ordered photos and check duplicate milestones.
Photo upload/list service
src/main/java/com/semosan/api/domain/tracking/dto/request/TrackingPhotoUploadRequest.java, src/main/java/com/semosan/api/domain/tracking/dto/response/TrackingPhotoResponse.java, src/main/java/com/semosan/api/domain/tracking/service/TrackingPhotoService.java
Request DTO validates photo metadata; response DTO maps entity fields; service enforces active session state, rejects duplicate milestones per session, validates user ownership, and persists/retrieves photos with proper error handling.
Milestone distance calculation
src/main/java/com/semosan/api/domain/tracking/service/TrackingMilestoneCalculator.java
Generates 500m intervals (6 max) for free-recording sessions or course distance divided into 4 equal segments for course-based sessions; milestones initialize Redis state and guide distance window evaluation.
Milestone trigger service
src/main/java/com/semosan/api/domain/tracking/service/TrackingPhotoTriggerService.java
Stores milestones in Redis with 24h TTL and tracks OPEN/CLOSED state per milestone using Redis sets (idempotent). On distance updates, evaluates cumulative distance against tolerance windows: sends WebSocket OPEN + FCM notification on entry (FCM failures suppressed), sends WebSocket CLOSED on exit.
REST controller and API docs
src/main/java/com/semosan/api/domain/tracking/controller/docs/TrackingPhotoControllerDocs.java, src/main/java/com/semosan/api/domain/tracking/controller/TrackingPhotoController.java
Swagger interface documents photo upload (POST 201/409) and list (GET 200) endpoints with request/response types and error cases; controller wires authenticated userId and sessionId, validates request, delegates to service, returns API response.
GPS stream integration
src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionStatsService.java, src/main/java/com/semosan/api/domain/tracking/service/TrackingSessionService.java, src/main/java/com/semosan/api/domain/tracking/service/TrackingStreamConsumer.java
recordPoint(...) now returns accumulated distanceTotal; TrackingSessionService injects and initializes photoTriggerService on session creation; stream consumer parses userId, captures returned distance, and calls trigger evaluate to emit milestone events.
Database schema
src/main/resources/db/migration/V10__create_tracking_photos.sql
Creates tracking_photos table with session FK, milestone index/distance, image URL, capture timestamp, and geolocation fields; composite index on (session, milestone index); updates notifications.type CHECK constraint to allow TRACKING_PHOTO_MILESTONE.

Sequence Diagram(s)

sequenceDiagram
  participant GPSStream
  participant StreamConsumer
  participant StatsService
  participant ActivityService
  participant TriggerService
  participant Redis
  participant WebSocket
  participant FCM
  GPSStream->>StreamConsumer: GPS point {lat, lng, userId}
  StreamConsumer->>StatsService: recordPoint(sessionId, lat, lng, altitude, time)
  StatsService->>Redis: update distance in session hash
  StatsService-->>StreamConsumer: return distanceTotal
  StreamConsumer->>ActivityService: markActive(sessionId)
  StreamConsumer->>TriggerService: evaluate(sessionId, userId, distanceTotal)
  TriggerService->>Redis: load milestones and state sets
  alt distanceTotal enters milestone window
    TriggerService->>Redis: mark milestone as OPEN
    TriggerService->>WebSocket: send OPEN event {index, distance, status, timestamp}
    TriggerService->>FCM: sendNotification(distance, userId)
    FCM-->>TriggerService: ok or exception (caught, logged)
  end
  alt OPEN milestone exceeds exit threshold
    TriggerService->>Redis: mark milestone as CLOSED
    TriggerService->>WebSocket: send CLOSED event {index, distance, status, timestamp}
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • SEMOSAN/SEMOSAN_BE#53: Both PRs modify TrackingStreamConsumer to parse userId from stream messages and propagate distance information downstream for milestone triggering.
  • SEMOSAN/SEMOSAN_BE#68: Both PRs extend TrackingSessionService with new dependencies and integrate tracking-photo feature initialization into session creation lifecycle.
  • SEMOSAN/SEMOSAN_BE#74: Both PRs modify TrackingSessionStatsService.recordPoint(...) at the same method signature level to return distance metrics for downstream milestone evaluation.

Suggested labels

enhancement

Suggested reviewers

  • howooyeon

Poem

🐰 A rabbit hops through distances bright,
Each milestone marked with photos of delight,
Redis sets track the opened and closed,
WebSocket whispers as notifications are posed,
From stream to trigger, the journey flows free!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#46-tracking-photo-push

Comment @coderabbitai help to get the list of available commands and usage tips.

@JangInho
JangInho merged commit 8899f0d into develop May 22, 2026
4 of 5 checks passed
@howooyeon
howooyeon deleted the feat/#46-tracking-photo-push branch May 28, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 트래킹 중 푸시

1 participant