Skip to content

Commit 699c282

Browse files
authored
Merge pull request #262 from DevKor-github/codex/backend-alarm-swagger-docs
[codex] Add Swagger docs for alarm endpoints
2 parents f3d7f3a + 13dcebd commit 699c282

3 files changed

Lines changed: 119 additions & 1 deletion

File tree

ontime-back/src/main/java/devkor/ontime_back/controller/AlarmController.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
import devkor.ontime_back.response.ApiResponseForm;
55
import devkor.ontime_back.service.AlarmService;
66
import devkor.ontime_back.service.UserAuthService;
7+
import io.swagger.v3.oas.annotations.Operation;
8+
import io.swagger.v3.oas.annotations.media.Content;
9+
import io.swagger.v3.oas.annotations.media.Schema;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
11+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
712
import jakarta.servlet.http.HttpServletRequest;
813
import lombok.RequiredArgsConstructor;
914
import org.springframework.http.HttpStatus;
@@ -19,13 +24,39 @@ public class AlarmController {
1924
private final UserAuthService userAuthService;
2025
private final AlarmService alarmService;
2126

27+
@Operation(summary = "Get current user's native alarm settings")
28+
@ApiResponses(value = {
29+
@ApiResponse(responseCode = "200", description = "Alarm settings lookup succeeded", content = @Content(
30+
mediaType = "application/json",
31+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"alarmsEnabled\": true,\n \"defaultAlarmOffsetMinutes\": 10,\n \"updatedAt\": \"2026-05-05T00:00:00Z\"\n }\n}")
32+
)),
33+
@ApiResponse(responseCode = "4XX", description = "Alarm settings lookup failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
34+
})
2235
@GetMapping("/users/me/alarm-settings")
2336
public ResponseEntity<ApiResponseForm<AlarmSettingsResponseDto>> getAlarmSettings(HttpServletRequest request) {
2437
Long userId = userAuthService.getUserIdFromToken(request);
2538
return ResponseEntity.status(HttpStatus.OK)
2639
.body(ApiResponseForm.success(alarmService.getAlarmSettings(userId)));
2740
}
2841

42+
@Operation(
43+
summary = "Update current user's native alarm settings",
44+
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
45+
description = "Partial alarm settings update. Omit fields that should not change.",
46+
required = true,
47+
content = @Content(schema = @Schema(
48+
type = "object",
49+
example = "{\"alarmsEnabled\": true, \"defaultAlarmOffsetMinutes\": 10}"
50+
))
51+
)
52+
)
53+
@ApiResponses(value = {
54+
@ApiResponse(responseCode = "200", description = "Alarm settings update succeeded", content = @Content(
55+
mediaType = "application/json",
56+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"alarmsEnabled\": true,\n \"defaultAlarmOffsetMinutes\": 10,\n \"updatedAt\": \"2026-05-05T00:00:00Z\"\n }\n}")
57+
)),
58+
@ApiResponse(responseCode = "4XX", description = "Alarm settings update failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
59+
})
2960
@PatchMapping("/users/me/alarm-settings")
3061
public ResponseEntity<ApiResponseForm<AlarmSettingsResponseDto>> patchAlarmSettings(
3162
HttpServletRequest request,
@@ -35,6 +66,24 @@ public ResponseEntity<ApiResponseForm<AlarmSettingsResponseDto>> patchAlarmSetti
3566
.body(ApiResponseForm.success(alarmService.patchAlarmSettings(userId, requestBody)));
3667
}
3768

69+
@Operation(
70+
summary = "Register current device for native alarm ownership",
71+
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
72+
description = "Current device metadata used to bind the logged-in access token to native alarm status.",
73+
required = true,
74+
content = @Content(schema = @Schema(
75+
type = "object",
76+
example = "{\"deviceId\": \"ios-device-000001\", \"platform\": \"ios\", \"appVersion\": \"1.2.3\", \"osVersion\": \"iOS 18.0\", \"supportsNativeAlarm\": true, \"nativeAlarmProvider\": \"iosAlarmKit\", \"fallbackProvider\": \"localNotification\"}"
77+
))
78+
)
79+
)
80+
@ApiResponses(value = {
81+
@ApiResponse(responseCode = "200", description = "Current device registration succeeded", content = @Content(
82+
mediaType = "application/json",
83+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"deviceId\": \"ios-device-000001\",\n \"active\": true,\n \"lastSeenAt\": \"2026-05-05T00:00:00Z\"\n }\n}")
84+
)),
85+
@ApiResponse(responseCode = "4XX", description = "Current device registration failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
86+
})
3887
@PutMapping("/users/me/devices/current")
3988
public ResponseEntity<ApiResponseForm<AlarmDeviceCurrentResponseDto>> registerCurrentDevice(
4089
HttpServletRequest request,
@@ -48,6 +97,23 @@ public ResponseEntity<ApiResponseForm<AlarmDeviceCurrentResponseDto>> registerCu
4897
userAuthService.getRefreshTokenFromRequest(request))));
4998
}
5099

100+
@Operation(
101+
summary = "Unregister current device from native alarm ownership",
102+
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
103+
description = "Optional device ID. If omitted, the device bound to the access token is unregistered.",
104+
content = @Content(schema = @Schema(
105+
type = "object",
106+
example = "{\"deviceId\": \"ios-device-000001\"}"
107+
))
108+
)
109+
)
110+
@ApiResponses(value = {
111+
@ApiResponse(responseCode = "200", description = "Current device unregister succeeded", content = @Content(
112+
mediaType = "application/json",
113+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"active\": false\n }\n}")
114+
)),
115+
@ApiResponse(responseCode = "4XX", description = "Current device unregister failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
116+
})
51117
@DeleteMapping("/users/me/devices/current")
52118
public ResponseEntity<ApiResponseForm<AlarmDeviceUnregisterResponseDto>> unregisterCurrentDevice(
53119
HttpServletRequest request,
@@ -60,6 +126,24 @@ public ResponseEntity<ApiResponseForm<AlarmDeviceUnregisterResponseDto>> unregis
60126
userAuthService.getAccessTokenFromRequest(request))));
61127
}
62128

129+
@Operation(
130+
summary = "Report current native alarm reconciliation status",
131+
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
132+
description = "Native alarm reconciliation status for the current device and schedule window.",
133+
required = true,
134+
content = @Content(schema = @Schema(
135+
type = "object",
136+
example = "{\"deviceId\": \"ios-device-000001\", \"reconciledAt\": \"2026-05-05T09:00:00+09:00\", \"scheduleWindowStart\": \"2026-05-05T00:00:00\", \"scheduleWindowEnd\": \"2026-05-06T00:00:00\", \"alarmCoverageStart\": \"2026-05-05T00:00:00\", \"alarmCoverageEnd\": \"2026-05-06T00:00:00\", \"status\": \"armed\", \"permissionIssue\": null, \"nativeAlarmProvider\": \"iosAlarmKit\", \"fallbackProvider\": \"localNotification\", \"armedScheduleCount\": 1, \"armedScheduleIds\": [\"3fa85f64-5717-4562-b3fc-2c963f66afe5\"], \"skippedScheduleCount\": 0, \"failures\": []}"
137+
))
138+
)
139+
)
140+
@ApiResponses(value = {
141+
@ApiResponse(responseCode = "200", description = "Alarm status report succeeded", content = @Content(
142+
mediaType = "application/json",
143+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"received\": true\n }\n}")
144+
)),
145+
@ApiResponse(responseCode = "4XX", description = "Alarm status report failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
146+
})
63147
@PostMapping("/users/me/alarm-status")
64148
public ResponseEntity<ApiResponseForm<AlarmStatusReportResponseDto>> reportAlarmStatus(
65149
HttpServletRequest request,
@@ -72,6 +156,14 @@ public ResponseEntity<ApiResponseForm<AlarmStatusReportResponseDto>> reportAlarm
72156
userAuthService.getAccessTokenFromRequest(request))));
73157
}
74158

159+
@Operation(summary = "Get current native alarm reconciliation status")
160+
@ApiResponses(value = {
161+
@ApiResponse(responseCode = "200", description = "Current alarm status lookup succeeded", content = @Content(
162+
mediaType = "application/json",
163+
schema = @Schema(example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": {\n \"deviceId\": \"ios-device-000001\",\n \"active\": true,\n \"platform\": \"ios\",\n \"appVersion\": \"1.2.3\",\n \"osVersion\": \"iOS 18.0\",\n \"supportsNativeAlarm\": true,\n \"nativeAlarmProvider\": \"iosAlarmKit\",\n \"fallbackProvider\": \"localNotification\",\n \"lastSeenAt\": \"2026-05-05T00:00:00Z\",\n \"reconciledAt\": \"2026-05-05T00:00:00Z\",\n \"scheduleWindowStart\": \"2026-05-05T00:00:00\",\n \"scheduleWindowEnd\": \"2026-05-06T00:00:00\",\n \"alarmCoverageStart\": \"2026-05-05T00:00:00\",\n \"alarmCoverageEnd\": \"2026-05-06T00:00:00\",\n \"status\": \"armed\",\n \"permissionIssue\": null,\n \"armedScheduleCount\": 1,\n \"armedScheduleIds\": [\"3fa85f64-5717-4562-b3fc-2c963f66afe5\"],\n \"skippedScheduleCount\": 0,\n \"failures\": [],\n \"updatedAt\": \"2026-05-05T00:00:00Z\"\n }\n}")
164+
)),
165+
@ApiResponse(responseCode = "4XX", description = "Current alarm status lookup failed", content = @Content(mediaType = "application/json", schema = @Schema(example = "Failure message")))
166+
})
75167
@GetMapping("/users/me/alarm-status")
76168
public ResponseEntity<ApiResponseForm<AlarmStatusCurrentResponseDto>> getCurrentAlarmStatus(HttpServletRequest request) {
77169
Long userId = userAuthService.getUserIdFromToken(request);

ontime-back/src/main/java/devkor/ontime_back/controller/FirebaseTokenController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class FirebaseTokenController {
3232
content = @Content(
3333
schema = @Schema(
3434
type = "object",
35-
example = "{\"firebaseToken\": \"token1234abcd(실제로는 firebase에서 받은 토큰을 기입해야 함)\"}"
35+
example = "{\"firebaseToken\": \"token1234abcd(실제로는 firebase에서 받은 토큰을 기입해야 함)\", \"deviceId\": \"ios-device-000001\"}"
3636
)
3737
)
3838
)

ontime-back/src/main/java/devkor/ontime_back/controller/ScheduleController.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,36 @@ public ResponseEntity<ApiResponseForm<List<ScheduleDto>>> getPeriodSchedule(Http
7070
return ResponseEntity.status(HttpStatus.OK).body(ApiResponseForm.success(schedules));
7171
}
7272

73+
@Operation(summary = "Native alarm schedule window lookup",
74+
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
75+
description = "No JSON body is required. Send access token in the header and use startDate/endDate query parameters."
76+
)
77+
)
78+
@ApiResponses(value = {
79+
@ApiResponse(responseCode = "200", description = "Alarm schedule window lookup succeeded",
80+
content = @Content(
81+
mediaType = "application/json",
82+
schema = @Schema(
83+
example = "{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": \"OK\",\n \"data\": [\n {\n \"scheduleId\": \"3fa85f64-5717-4562-b3fc-2c963f66afe5\",\n \"scheduleName\": \"Morning meeting\",\n \"place\": {\n \"placeId\": \"3fa85f64-5717-4562-b3fc-2c963f66afe6\",\n \"placeName\": \"Office\"\n },\n \"scheduleTime\": \"2026-05-05T09:30:00\",\n \"moveTime\": 20,\n \"scheduleSpareTime\": 10,\n \"doneStatus\": \"NOT_ENDED\",\n \"preparationStartTime\": \"2026-05-05T08:40:00\",\n \"defaultAlarmTime\": \"2026-05-05T08:30:00\",\n \"preparations\": [],\n \"alarmSettings\": null\n }\n ]\n}"
84+
)
85+
)),
86+
@ApiResponse(responseCode = "4XX", description = "Alarm schedule window lookup failed",
87+
content = @Content(
88+
mediaType = "application/json",
89+
schema = @Schema(example = "Failure message")
90+
)
91+
)
92+
})
7393
@GetMapping("/alarm-window")
7494
public ResponseEntity<ApiResponseForm<List<AlarmWindowScheduleDto>>> getAlarmWindowSchedules(
7595
HttpServletRequest request,
96+
@Parameter(description = "Alarm window start date-time. Supports ISO local date-time or ISO offset date-time.",
97+
required = true,
98+
example = "2026-05-05T00:00:00")
7699
@RequestParam String startDate,
100+
@Parameter(description = "Alarm window end date-time. Supports ISO local date-time or ISO offset date-time.",
101+
required = true,
102+
example = "2026-05-06T00:00:00")
77103
@RequestParam String endDate) {
78104
Long userId = userAuthService.getUserIdFromToken(request);
79105
List<AlarmWindowScheduleDto> schedules = scheduleService.getAlarmWindowSchedules(

0 commit comments

Comments
 (0)