docs: sam_stat Swagger API 문서 추가 (Phase 6)
- StatApi.php: Stats 태그, 4개 엔드포인트 Swagger 정의 - GET /stats/summary - 대시보드 통계 요약 - GET /stats/daily - 도메인별 일간 통계 - GET /stats/monthly - 도메인별 월간 통계 - GET /stats/alerts - 통계 알림 목록 - 스키마: StatSalesDaily, StatFinanceDaily, StatDashboardSummary, StatAlert Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
273
app/Swagger/v1/StatApi.php
Normal file
273
app/Swagger/v1/StatApi.php
Normal file
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
namespace App\Swagger\v1;
|
||||
|
||||
/**
|
||||
* @OA\Tag(name="Stats", description="통계 (sam_stat DB 기반)")
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="StatSalesDaily",
|
||||
* type="object",
|
||||
* description="일간 매출 통계",
|
||||
*
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=287),
|
||||
* @OA\Property(property="stat_date", type="string", format="date", example="2026-01-28"),
|
||||
* @OA\Property(property="order_count", type="integer", example=5, description="수주 건수"),
|
||||
* @OA\Property(property="order_amount", type="number", format="float", example=15000000, description="수주 금액"),
|
||||
* @OA\Property(property="sales_count", type="integer", example=3, description="매출 건수"),
|
||||
* @OA\Property(property="sales_amount", type="number", format="float", example=12000000, description="매출 금액"),
|
||||
* @OA\Property(property="sales_tax_amount", type="number", format="float", example=1200000, description="매출 세액"),
|
||||
* @OA\Property(property="new_client_count", type="integer", example=1, description="신규 고객 수"),
|
||||
* @OA\Property(property="active_client_count", type="integer", example=4, description="활성 고객 수"),
|
||||
* @OA\Property(property="shipment_count", type="integer", example=2, description="출하 건수"),
|
||||
* @OA\Property(property="shipment_amount", type="number", format="float", example=500000, description="출하 금액")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="StatFinanceDaily",
|
||||
* type="object",
|
||||
* description="일간 재무 통계",
|
||||
*
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=287),
|
||||
* @OA\Property(property="stat_date", type="string", format="date", example="2026-01-28"),
|
||||
* @OA\Property(property="deposit_count", type="integer", example=3, description="입금 건수"),
|
||||
* @OA\Property(property="deposit_amount", type="number", format="float", example=5000000, description="입금 금액"),
|
||||
* @OA\Property(property="withdrawal_count", type="integer", example=5, description="출금 건수"),
|
||||
* @OA\Property(property="withdrawal_amount", type="number", format="float", example=3000000, description="출금 금액"),
|
||||
* @OA\Property(property="net_cashflow", type="number", format="float", example=2000000, description="순 현금 흐름"),
|
||||
* @OA\Property(property="purchase_count", type="integer", example=2, description="매입 건수"),
|
||||
* @OA\Property(property="purchase_amount", type="number", format="float", example=8000000, description="매입 금액"),
|
||||
* @OA\Property(property="bank_balance_total", type="number", format="float", example=150000000, description="은행 잔액 합계")
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="StatDashboardSummary",
|
||||
* type="object",
|
||||
* description="대시보드 통계 요약 (sam_stat 기반)",
|
||||
*
|
||||
* @OA\Property(property="sales_today", ref="#/components/schemas/StatSalesDaily", nullable=true, description="오늘 매출 통계"),
|
||||
* @OA\Property(property="finance_today", ref="#/components/schemas/StatFinanceDaily", nullable=true, description="오늘 재무 통계"),
|
||||
* @OA\Property(property="production_today", type="object", nullable=true, description="오늘 생산 통계"),
|
||||
* @OA\Property(property="sales_monthly", type="object", nullable=true, description="이번 달 매출 요약"),
|
||||
* @OA\Property(property="alerts", type="array", description="미읽은/미해결 알림 (최대 10건)",
|
||||
*
|
||||
* @OA\Items(ref="#/components/schemas/StatAlert")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="StatAlert",
|
||||
* type="object",
|
||||
* description="통계 알림",
|
||||
*
|
||||
* @OA\Property(property="id", type="integer", example=1),
|
||||
* @OA\Property(property="tenant_id", type="integer", example=287),
|
||||
* @OA\Property(property="domain", type="string", example="sales", description="도메인"),
|
||||
* @OA\Property(property="alert_type", type="string", example="aggregation_failure", description="알림 유형"),
|
||||
* @OA\Property(property="severity", type="string", enum={"info","warning","critical"}, example="critical", description="심각도"),
|
||||
* @OA\Property(property="title", type="string", example="[sales_daily] 집계 실패", description="제목"),
|
||||
* @OA\Property(property="message", type="string", example="오류 상세 메시지", description="상세 메시지"),
|
||||
* @OA\Property(property="current_value", type="number", format="float", nullable=true, example=0, description="현재 값"),
|
||||
* @OA\Property(property="threshold_value", type="number", format="float", nullable=true, example=1, description="기준 값"),
|
||||
* @OA\Property(property="is_read", type="boolean", example=false, description="읽음 여부"),
|
||||
* @OA\Property(property="is_resolved", type="boolean", example=false, description="해결 여부"),
|
||||
* @OA\Property(property="resolved_at", type="string", format="date-time", nullable=true, description="해결 일시"),
|
||||
* @OA\Property(property="created_at", type="string", format="date-time", example="2026-01-28T10:00:00Z", description="생성 일시")
|
||||
* )
|
||||
*/
|
||||
class StatApi
|
||||
{
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/stats/summary",
|
||||
* tags={"Stats"},
|
||||
* summary="대시보드 통계 요약",
|
||||
* description="sam_stat DB 기반 대시보드 요약 통계를 반환합니다. 오늘의 매출/재무/생산 통계, 이번 달 매출 요약, 미해결 알림을 포함합니다. Redis 캐싱 적용 (TTL 5분).",
|
||||
* operationId="getStatSummary",
|
||||
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", ref="#/components/schemas/StatDashboardSummary")
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패")
|
||||
* )
|
||||
*/
|
||||
public function summary() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/stats/daily",
|
||||
* tags={"Stats"},
|
||||
* summary="도메인별 일간 통계 조회",
|
||||
* description="지정한 도메인의 일간 통계를 기간별로 조회합니다. 7개 도메인 지원: sales, finance, production, inventory, quote, hr, system. Redis 캐싱 적용 (TTL 5분).",
|
||||
* operationId="getStatDaily",
|
||||
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="domain",
|
||||
* in="query",
|
||||
* required=true,
|
||||
* description="통계 도메인",
|
||||
*
|
||||
* @OA\Schema(type="string", enum={"sales","finance","production","inventory","quote","hr","system"})
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="start_date",
|
||||
* in="query",
|
||||
* required=true,
|
||||
* description="시작 날짜",
|
||||
*
|
||||
* @OA\Schema(type="string", format="date", example="2026-01-01")
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="end_date",
|
||||
* in="query",
|
||||
* required=true,
|
||||
* description="종료 날짜 (start_date 이후)",
|
||||
*
|
||||
* @OA\Schema(type="string", format="date", example="2026-01-31")
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", type="array",
|
||||
*
|
||||
* @OA\Items(type="object", description="도메인별 일간 통계 레코드 (스키마는 도메인에 따라 다름)")
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패"),
|
||||
* @OA\Response(response=422, description="유효성 검증 실패")
|
||||
* )
|
||||
*/
|
||||
public function daily() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/stats/monthly",
|
||||
* tags={"Stats"},
|
||||
* summary="도메인별 월간 통계 조회",
|
||||
* description="지정한 도메인의 월간 통계를 조회합니다. 4개 도메인 지원: sales, finance, production, project. Redis 캐싱 적용 (TTL 5분).",
|
||||
* operationId="getStatMonthly",
|
||||
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="domain",
|
||||
* in="query",
|
||||
* required=true,
|
||||
* description="통계 도메인",
|
||||
*
|
||||
* @OA\Schema(type="string", enum={"sales","finance","production","project"})
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="year",
|
||||
* in="query",
|
||||
* required=true,
|
||||
* description="조회 연도",
|
||||
*
|
||||
* @OA\Schema(type="integer", minimum=2020, maximum=2099, example=2026)
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="month",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* description="조회 월 (미지정 시 연간 전체)",
|
||||
*
|
||||
* @OA\Schema(type="integer", minimum=1, maximum=12, example=1)
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", type="array",
|
||||
*
|
||||
* @OA\Items(type="object", description="도메인별 월간 통계 레코드 (스키마는 도메인에 따라 다름)")
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패"),
|
||||
* @OA\Response(response=422, description="유효성 검증 실패")
|
||||
* )
|
||||
*/
|
||||
public function monthly() {}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/stats/alerts",
|
||||
* tags={"Stats"},
|
||||
* summary="통계 알림 목록 조회",
|
||||
* description="통계 시스템에서 발생한 알림을 조회합니다. 집계 실패, 데이터 누락, 정합성 불일치 등의 알림이 포함됩니다.",
|
||||
* operationId="getStatAlerts",
|
||||
* security={{"ApiKeyAuth":{}}, {"BearerAuth":{}}},
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="limit",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* description="조회 건수 (기본 20)",
|
||||
*
|
||||
* @OA\Schema(type="integer", minimum=1, maximum=100, example=20)
|
||||
* ),
|
||||
*
|
||||
* @OA\Parameter(
|
||||
* name="unread_only",
|
||||
* in="query",
|
||||
* required=false,
|
||||
* description="미읽은 알림만 조회",
|
||||
*
|
||||
* @OA\Schema(type="boolean", example=true)
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="성공",
|
||||
*
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
*
|
||||
* @OA\Property(property="success", type="boolean", example=true),
|
||||
* @OA\Property(property="message", type="string", example="데이터를 조회했습니다."),
|
||||
* @OA\Property(property="data", type="array",
|
||||
*
|
||||
* @OA\Items(ref="#/components/schemas/StatAlert")
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
*
|
||||
* @OA\Response(response=401, description="인증 실패"),
|
||||
* @OA\Response(response=422, description="유효성 검증 실패")
|
||||
* )
|
||||
*/
|
||||
public function alerts() {}
|
||||
}
|
||||
Reference in New Issue
Block a user