feat: 대시보드 API 및 FCM 푸시 알림 API 구현
Dashboard API: - DashboardController, DashboardService 추가 - /dashboard/summary, /charts, /approvals 엔드포인트 Push Notification API: - FCM 토큰 관리 (등록/해제/목록) - 알림 설정 관리 (유형별 on/off, 알림음 설정) - 알림 유형: deposit, withdrawal, order, approval, attendance, notice, system - 알림음: default, deposit, withdrawal, order, approval, urgent - PushDeviceToken, PushNotificationSetting 모델 - Swagger 문서 추가
This commit is contained in:
184
app/Swagger/v1/DashboardApi.php
Normal file
184
app/Swagger/v1/DashboardApi.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace App\Swagger\v1;
|
||||
|
||||
/**
|
||||
* @OA\Tag(name="Dashboard", description="대시보드")
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="DashboardSummary",
|
||||
* type="object",
|
||||
* description="대시보드 요약 데이터",
|
||||
*
|
||||
* @OA\Property(property="today", type="object", description="오늘 요약",
|
||||
* @OA\Property(property="date", type="string", format="date", example="2025-01-15", description="오늘 날짜"),
|
||||
* @OA\Property(property="attendances_count", type="integer", example=25, description="오늘 출근자 수"),
|
||||
* @OA\Property(property="leaves_count", type="integer", example=3, description="오늘 휴가자 수"),
|
||||
* @OA\Property(property="approvals_pending", type="integer", example=5, description="결재 대기 문서 수")
|
||||
* ),
|
||||
* @OA\Property(property="finance", type="object", description="재무 요약",
|
||||
* @OA\Property(property="monthly_deposit", type="number", format="float", example=50000000, description="월간 입금액"),
|
||||
* @OA\Property(property="monthly_withdrawal", type="number", format="float", example=30000000, description="월간 출금액"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example=150000000, description="현재 잔액")
|
||||
* ),
|
||||
* @OA\Property(property="sales", type="object", description="매출/매입 요약",
|
||||
* @OA\Property(property="monthly_sales", type="number", format="float", example=80000000, description="월간 매출"),
|
||||
* @OA\Property(property="monthly_purchases", type="number", format="float", example=45000000, description="월간 매입")
|
||||
* ),
|
||||
* @OA\Property(property="tasks", type="object", description="할 일 요약",
|
||||
* @OA\Property(property="pending_approvals", type="integer", example=3, description="내가 결재할 문서 수"),
|
||||
* @OA\Property(property="pending_leaves", type="integer", example=2, description="승인 대기 휴가 신청 수")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="DashboardCharts",
|
||||
* type="object",
|
||||
* description="대시보드 차트 데이터",
|
||||
*
|
||||
* @OA\Property(property="period", type="string", enum={"week","month","quarter"}, example="month", description="조회 기간"),
|
||||
* @OA\Property(property="start_date", type="string", format="date", example="2024-12-17", description="시작일"),
|
||||
* @OA\Property(property="end_date", type="string", format="date", example="2025-01-15", description="종료일"),
|
||||
* @OA\Property(property="deposit_trend", type="array", description="입금 추이",
|
||||
* @OA\Items(type="object",
|
||||
* @OA\Property(property="date", type="string", format="date", example="2025-01-15"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example=5000000)
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="withdrawal_trend", type="array", description="출금 추이",
|
||||
* @OA\Items(type="object",
|
||||
* @OA\Property(property="date", type="string", format="date", example="2025-01-15"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example=3000000)
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="sales_by_client", type="array", description="거래처별 매출 (상위 10개)",
|
||||
* @OA\Items(type="object",
|
||||
* @OA\Property(property="client_id", type="integer", example=1),
|
||||
* @OA\Property(property="client_name", type="string", example="(주)테스트"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example=15000000)
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="DashboardApprovals",
|
||||
* type="object",
|
||||
* description="대시보드 결재 현황",
|
||||
*
|
||||
* @OA\Property(property="pending_approvals", type="array", description="결재 대기 문서 (내가 결재할 문서)",
|
||||
* @OA\Items(type="object",
|
||||
* @OA\Property(property="id", type="integer", example=1, description="결재문서 ID"),
|
||||
* @OA\Property(property="title", type="string", example="출장 신청서", description="제목"),
|
||||
* @OA\Property(property="drafter_name", type="string", example="홍길동", description="기안자명"),
|
||||
* @OA\Property(property="status", type="string", example="pending", description="상태"),
|
||||
* @OA\Property(property="created_at", type="string", format="date-time", example="2025-01-15 10:30:00", description="생성일시")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Property(property="my_drafts", type="array", description="내가 기안한 진행중인 문서",
|
||||
* @OA\Items(type="object",
|
||||
* @OA\Property(property="id", type="integer", example=2, description="결재문서 ID"),
|
||||
* @OA\Property(property="title", type="string", example="휴가 신청서", description="제목"),
|
||||
* @OA\Property(property="status", type="string", example="pending", description="상태"),
|
||||
* @OA\Property(property="current_step", type="integer", example=2, description="현재 결재 단계"),
|
||||
* @OA\Property(property="created_at", type="string", format="date-time", example="2025-01-14 09:00:00", description="생성일시")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class DashboardApi
|
||||
{
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/dashboard/summary",
|
||||
* tags={"Dashboard"},
|
||||
* summary="대시보드 요약 데이터 조회",
|
||||
* description="오늘 현황, 재무 요약, 매출/매입 요약, 할 일 요약을 반환합니다.",
|
||||
* operationId="getDashboardSummary",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", ref="#/components/schemas/DashboardSummary")
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패")
|
||||
* )
|
||||
*/
|
||||
public function summary() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/dashboard/charts",
|
||||
* tags={"Dashboard"},
|
||||
* summary="대시보드 차트 데이터 조회",
|
||||
* description="입금/출금 추이, 거래처별 매출 차트 데이터를 반환합니다.",
|
||||
* operationId="getDashboardCharts",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="period",
|
||||
* in="query",
|
||||
* description="조회 기간 (week: 7일, month: 30일, quarter: 3개월)",
|
||||
* required=false,
|
||||
*
|
||||
* @OA\Schema(type="string", enum={"week","month","quarter"}, default="month")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", ref="#/components/schemas/DashboardCharts")
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패"),
|
||||
* @OA\Response(response=422, description="유효성 검사 실패")
|
||||
* )
|
||||
*/
|
||||
public function charts() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/dashboard/approvals",
|
||||
* tags={"Dashboard"},
|
||||
* summary="결재 현황 조회",
|
||||
* description="결재 대기 문서(결재함)와 내가 기안한 진행중인 문서 목록을 반환합니다.",
|
||||
* operationId="getDashboardApprovals",
|
||||
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="limit",
|
||||
* in="query",
|
||||
* description="각 목록의 최대 항목 수 (1~50)",
|
||||
* required=false,
|
||||
*
|
||||
* @OA\Schema(type="integer", minimum=1, maximum=50, default=10)
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", ref="#/components/schemas/DashboardApprovals")
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패"),
|
||||
* @OA\Response(response=422, description="유효성 검사 실패")
|
||||
* )
|
||||
*/
|
||||
public function approvals() {}
|
||||
}
|
||||
303
app/Swagger/v1/PushApi.php
Normal file
303
app/Swagger/v1/PushApi.php
Normal file
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
namespace App\Swagger\v1;
|
||||
|
||||
/**
|
||||
* @OA\Tag(name="Push", description="푸시 알림 관리")
|
||||
*/
|
||||
|
||||
/**
|
||||
* Push 관련 스키마 정의
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="PushDeviceToken",
|
||||
* type="object",
|
||||
* description="푸시 디바이스 토큰",
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=1),
|
||||
* @OA\Property(property="user_id", type="integer", example=5),
|
||||
* @OA\Property(property="token", type="string", example="dGhpcyBpcyBhIHNhbXBsZSBGQ00gdG9rZW4..."),
|
||||
* @OA\Property(property="platform", type="string", enum={"ios", "android", "web"}, example="android"),
|
||||
* @OA\Property(property="device_name", type="string", nullable=true, example="Samsung Galaxy S24"),
|
||||
* @OA\Property(property="app_version", type="string", nullable=true, example="1.0.0"),
|
||||
* @OA\Property(property="is_active", type="boolean", example=true),
|
||||
* @OA\Property(property="last_used_at", type="string", format="date-time", example="2025-12-18 10:30:00"),
|
||||
* @OA\Property(property="created_at", type="string", format="date-time", example="2025-12-18 10:00:00"),
|
||||
* @OA\Property(property="updated_at", type="string", format="date-time", example="2025-12-18 10:30:00")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="PushNotificationSetting",
|
||||
* type="object",
|
||||
* description="푸시 알림 설정",
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=1),
|
||||
* @OA\Property(property="user_id", type="integer", example=5),
|
||||
* @OA\Property(property="notification_type", type="string", enum={"deposit", "withdrawal", "order", "approval", "attendance", "notice", "system"}, example="deposit"),
|
||||
* @OA\Property(property="is_enabled", type="boolean", example=true),
|
||||
* @OA\Property(property="sound", type="string", enum={"default.wav", "deposit.wav", "withdrawal.wav", "order.wav", "approval.wav", "urgent.wav"}, example="deposit.wav"),
|
||||
* @OA\Property(property="vibrate", type="boolean", example=true),
|
||||
* @OA\Property(property="show_preview", type="boolean", example=true),
|
||||
* @OA\Property(property="created_at", type="string", format="date-time", example="2025-12-18 10:00:00"),
|
||||
* @OA\Property(property="updated_at", type="string", format="date-time", example="2025-12-18 10:30:00")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="RegisterTokenRequest",
|
||||
* type="object",
|
||||
* required={"token", "platform"},
|
||||
* @OA\Property(property="token", type="string", minLength=10, example="dGhpcyBpcyBhIHNhbXBsZSBGQ00gdG9rZW4...", description="FCM 토큰"),
|
||||
* @OA\Property(property="platform", type="string", enum={"ios", "android", "web"}, example="android", description="디바이스 플랫폼"),
|
||||
* @OA\Property(property="device_name", type="string", nullable=true, maxLength=255, example="Samsung Galaxy S24", description="디바이스명"),
|
||||
* @OA\Property(property="app_version", type="string", nullable=true, maxLength=50, example="1.0.0", description="앱 버전")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="UnregisterTokenRequest",
|
||||
* type="object",
|
||||
* required={"token"},
|
||||
* @OA\Property(property="token", type="string", example="dGhpcyBpcyBhIHNhbXBsZSBGQ00gdG9rZW4...", description="해제할 FCM 토큰")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="UpdatePushSettingsRequest",
|
||||
* type="object",
|
||||
* required={"settings"},
|
||||
* @OA\Property(
|
||||
* property="settings",
|
||||
* type="array",
|
||||
* description="알림 설정 배열",
|
||||
* @OA\Items(
|
||||
* type="object",
|
||||
* required={"notification_type", "is_enabled"},
|
||||
* @OA\Property(property="notification_type", type="string", enum={"deposit", "withdrawal", "order", "approval", "attendance", "notice", "system"}, example="deposit"),
|
||||
* @OA\Property(property="is_enabled", type="boolean", example=true),
|
||||
* @OA\Property(property="sound", type="string", nullable=true, enum={"default.wav", "deposit.wav", "withdrawal.wav", "order.wav", "approval.wav", "urgent.wav"}, example="deposit.wav"),
|
||||
* @OA\Property(property="vibrate", type="boolean", nullable=true, example=true),
|
||||
* @OA\Property(property="show_preview", type="boolean", nullable=true, example=true)
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="NotificationTypesResponse",
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="types",
|
||||
* type="array",
|
||||
* description="지원하는 알림 유형 목록",
|
||||
* @OA\Items(type="string", example="deposit")
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="sounds",
|
||||
* type="array",
|
||||
* description="지원하는 알림음 목록",
|
||||
* @OA\Items(type="string", example="deposit.wav")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class PushApi
|
||||
{
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/push/register-token",
|
||||
* tags={"Push"},
|
||||
* summary="FCM 토큰 등록",
|
||||
* description="디바이스의 FCM 토큰을 등록합니다. 동일한 토큰이 이미 존재하면 업데이트됩니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/RegisterTokenRequest")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="토큰 등록 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(property="message", type="string", example="푸시 토큰이 등록되었습니다."),
|
||||
* @OA\Property(property="data", ref="#/components/schemas/PushDeviceToken")
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
|
||||
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function registerToken() {}
|
||||
|
||||
/**
|
||||
* @OA\Post(
|
||||
* path="/api/push/unregister-token",
|
||||
* tags={"Push"},
|
||||
* summary="FCM 토큰 해제",
|
||||
* description="디바이스의 FCM 토큰을 비활성화합니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/UnregisterTokenRequest")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="토큰 해제 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(property="message", type="string", example="푸시 토큰이 해제되었습니다."),
|
||||
* @OA\Property(
|
||||
* property="data",
|
||||
* type="object",
|
||||
* @OA\Property(property="unregistered", type="boolean", example=true)
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=400, description="토큰 누락", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function unregisterToken() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/push/tokens",
|
||||
* tags={"Push"},
|
||||
* summary="사용자 토큰 목록 조회",
|
||||
* description="현재 사용자의 활성화된 디바이스 토큰 목록을 조회합니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="조회 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="data",
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/PushDeviceToken")
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function getTokens() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/push/settings",
|
||||
* tags={"Push"},
|
||||
* summary="알림 설정 조회",
|
||||
* description="현재 사용자의 알림 유형별 설정을 조회합니다. 설정이 없는 유형은 기본값으로 반환됩니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="조회 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="data",
|
||||
* type="object",
|
||||
* description="알림 유형별 설정 (키: notification_type)",
|
||||
* @OA\Property(property="deposit", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="withdrawal", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="order", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="approval", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="attendance", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="notice", ref="#/components/schemas/PushNotificationSetting"),
|
||||
* @OA\Property(property="system", ref="#/components/schemas/PushNotificationSetting")
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function getSettings() {}
|
||||
|
||||
/**
|
||||
* @OA\Put(
|
||||
* path="/api/push/settings",
|
||||
* tags={"Push"},
|
||||
* summary="알림 설정 업데이트",
|
||||
* description="사용자의 알림 설정을 업데이트합니다. 여러 알림 유형을 한 번에 설정할 수 있습니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(ref="#/components/schemas/UpdatePushSettingsRequest")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="설정 업데이트 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(property="message", type="string", example="알림 설정이 업데이트되었습니다."),
|
||||
* @OA\Property(
|
||||
* property="data",
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/PushNotificationSetting")
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse")),
|
||||
* @OA\Response(response=422, description="검증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function updateSettings() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/push/notification-types",
|
||||
* tags={"Push"},
|
||||
* summary="알림 유형 목록 조회",
|
||||
* description="지원하는 알림 유형과 알림음 목록을 조회합니다.",
|
||||
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="조회 성공",
|
||||
* @OA\JsonContent(
|
||||
* allOf={
|
||||
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
|
||||
* @OA\Schema(
|
||||
* @OA\Property(property="data", ref="#/components/schemas/NotificationTypesResponse")
|
||||
* )
|
||||
* }
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
|
||||
* )
|
||||
*/
|
||||
public function getNotificationTypes() {}
|
||||
}
|
||||
Reference in New Issue
Block a user