44import devkor .ontime_back .response .ApiResponseForm ;
55import devkor .ontime_back .service .AlarmService ;
66import 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 ;
712import jakarta .servlet .http .HttpServletRequest ;
813import lombok .RequiredArgsConstructor ;
914import 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 );
0 commit comments