Files
sam-api/app/Swagger/v1/CardTransactionApi.php
권혁성 857192e8ac feat(API): 카드 거래 대시보드 API 신규 추가
- GET /api/v1/card-transactions/dashboard 엔드포인트 추가
- 월별 추이, 사용자별 비율, 최근 거래 목록 포함
- CEO 대시보드 cm1 모달용 데이터 제공

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 22:28:41 +09:00

386 lines
15 KiB
PHP

<?php
namespace App\Swagger\v1;
/**
* @OA\Tag(
* name="CardTransaction",
* description="카드 거래 조회 API - 법인카드 사용 내역 조회 및 계정과목 관리"
* )
*/
/**
* @OA\Schema(
* schema="CardTransactionItem",
* description="카드 거래 항목",
*
* @OA\Property(property="id", type="integer", description="거래 ID", example=1),
* @OA\Property(property="card_id", type="integer", description="카드 ID", example=1, nullable=true),
* @OA\Property(property="withdrawal_date", type="string", format="date", description="출금일", example="2025-01-15"),
* @OA\Property(property="used_at", type="string", format="date-time", description="사용일시", example="2025-01-15T14:30:00Z", nullable=true),
* @OA\Property(property="merchant_name", type="string", description="가맹점명", example="스타벅스 강남역점", nullable=true),
* @OA\Property(property="amount", type="number", format="float", description="사용금액", example=15000),
* @OA\Property(property="account_code", type="string", description="계정과목", example="expenses", nullable=true),
* @OA\Property(property="description", type="string", description="적요", example="회의 다과", nullable=true),
* @OA\Property(
* property="card",
* type="object",
* nullable=true,
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="card_company", type="string", example="신한"),
* @OA\Property(property="card_number_last4", type="string", example="1234"),
* @OA\Property(property="card_name", type="string", example="법인카드1"),
* @OA\Property(
* property="assigned_user",
* type="object",
* nullable=true,
* @OA\Property(property="id", type="integer", example=1),
* @OA\Property(property="name", type="string", example="홍길동")
* )
* ),
* @OA\Property(property="created_at", type="string", format="date-time", description="생성일시"),
* @OA\Property(property="updated_at", type="string", format="date-time", description="수정일시")
* )
*
* @OA\Schema(
* schema="CardTransactionSummary",
* description="카드 거래 요약 통계",
*
* @OA\Property(property="previous_month_total", type="number", format="float", description="전월 사용액", example=1500000),
* @OA\Property(property="current_month_total", type="number", format="float", description="당월 사용액", example=850000),
* @OA\Property(property="total_count", type="integer", description="조회 기간 내 거래 건수", example=45),
* @OA\Property(property="total_amount", type="number", format="float", description="조회 기간 내 총 금액", example=2350000)
* )
*
* @OA\Schema(
* schema="CardTransactionPagination",
* description="카드 거래 목록 페이지네이션",
* type="object",
*
* @OA\Property(property="current_page", type="integer", example=1),
* @OA\Property(property="data", type="array", @OA\Items(ref="#/components/schemas/CardTransactionItem")),
* @OA\Property(property="first_page_url", type="string"),
* @OA\Property(property="from", type="integer"),
* @OA\Property(property="last_page", type="integer"),
* @OA\Property(property="last_page_url", type="string"),
* @OA\Property(property="next_page_url", type="string", nullable=true),
* @OA\Property(property="path", type="string"),
* @OA\Property(property="per_page", type="integer"),
* @OA\Property(property="prev_page_url", type="string", nullable=true),
* @OA\Property(property="to", type="integer"),
* @OA\Property(property="total", type="integer")
* )
*
* @OA\Schema(
* schema="CardTransactionBulkUpdateRequest",
* description="계정과목 일괄 수정 요청",
* required={"ids", "account_code"},
*
* @OA\Property(
* property="ids",
* type="array",
* description="거래 ID 배열",
*
* @OA\Items(type="integer"),
* example={1, 2, 3}
* ),
*
* @OA\Property(property="account_code", type="string", description="계정과목 코드", example="expenses")
* )
*
* @OA\Schema(
* schema="CardTransactionDashboard",
* description="카드 거래 대시보드 데이터 (CEO 대시보드 cm1 모달용)",
*
* @OA\Property(
* property="summary",
* type="object",
* description="요약 통계",
* @OA\Property(property="current_month_total", type="number", format="float", description="당월 카드 사용액", example=30123000),
* @OA\Property(property="previous_month_total", type="number", format="float", description="전월 카드 사용액", example=27250000),
* @OA\Property(property="change_rate", type="number", format="float", description="전월 대비 증감률 (%)", example=10.5),
* @OA\Property(property="unprocessed_count", type="integer", description="미정리 건수", example=5)
* ),
* @OA\Property(
* property="monthly_trend",
* type="array",
* description="최근 6개월 추이",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="month", type="string", description="년월", example="2026-01"),
* @OA\Property(property="amount", type="number", format="float", description="사용액", example=25000000)
* )
* ),
* @OA\Property(
* property="user_ratio",
* type="array",
* description="사용자별 비율",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="user_name", type="string", description="사용자명", example="홍길동"),
* @OA\Property(property="amount", type="number", format="float", description="사용액", example=15000000),
* @OA\Property(property="percentage", type="number", format="float", description="비율 (%)", example=49.8)
* )
* ),
* @OA\Property(
* property="recent_transactions",
* type="array",
* description="최근 거래 10건",
*
* @OA\Items(
* type="object",
*
* @OA\Property(property="id", type="integer", description="거래 ID", example=1),
* @OA\Property(property="card_name", type="string", description="카드명", example="법인카드1"),
* @OA\Property(property="user_name", type="string", description="사용자명", example="홍길동"),
* @OA\Property(property="used_at", type="string", description="사용일시", example="2026-01-15 14:30:00"),
* @OA\Property(property="merchant_name", type="string", description="가맹점명", example="스타벅스 강남역점"),
* @OA\Property(property="amount", type="number", format="float", description="사용금액", example=15000),
* @OA\Property(property="usage_type", type="string", description="계정과목", example="expenses", nullable=true)
* )
* )
* )
*/
class CardTransactionApi
{
/**
* @OA\Get(
* path="/api/v1/card-transactions",
* operationId="getCardTransactionList",
* tags={"CardTransaction"},
* summary="카드 거래 목록 조회",
* description="법인카드 사용 내역을 조회합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="start_date",
* in="query",
* description="조회 시작일",
*
* @OA\Schema(type="string", format="date", example="2025-01-01")
* ),
*
* @OA\Parameter(
* name="end_date",
* in="query",
* description="조회 종료일",
*
* @OA\Schema(type="string", format="date", example="2025-12-31")
* ),
*
* @OA\Parameter(
* name="card_id",
* in="query",
* description="카드 ID 필터",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @OA\Parameter(
* name="search",
* in="query",
* description="검색어 (카드명, 가맹점명)",
*
* @OA\Schema(type="string", example="스타벅스")
* ),
*
* @OA\Parameter(
* name="sort_by",
* in="query",
* description="정렬 기준",
*
* @OA\Schema(type="string", enum={"used_at", "amount", "merchant_name", "created_at"}, default="used_at")
* ),
*
* @OA\Parameter(
* name="sort_dir",
* in="query",
* description="정렬 방향",
*
* @OA\Schema(type="string", enum={"asc", "desc"}, default="desc")
* ),
*
* @OA\Parameter(
* name="per_page",
* in="query",
* description="페이지당 항목 수",
*
* @OA\Schema(type="integer", default=20)
* ),
*
* @OA\Parameter(
* name="page",
* in="query",
* description="페이지 번호",
*
* @OA\Schema(type="integer", default=1)
* ),
*
* @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/CardTransactionPagination")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음")
* )
*/
public function index() {}
/**
* @OA\Get(
* path="/api/v1/card-transactions/summary",
* operationId="getCardTransactionSummary",
* tags={"CardTransaction"},
* summary="카드 거래 요약 통계",
* description="전월/당월 카드 사용액 통계를 조회합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="start_date",
* in="query",
* description="조회 시작일",
*
* @OA\Schema(type="string", format="date", example="2025-01-01")
* ),
*
* @OA\Parameter(
* name="end_date",
* in="query",
* description="조회 종료일",
*
* @OA\Schema(type="string", format="date", example="2025-12-31")
* ),
*
* @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/CardTransactionSummary")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음")
* )
*/
public function summary() {}
/**
* @OA\Get(
* path="/api/v1/card-transactions/dashboard",
* operationId="getCardTransactionDashboard",
* tags={"CardTransaction"},
* summary="카드 거래 대시보드 데이터",
* description="CEO 대시보드 카드/가지급금 관리 섹션(cm1)의 모달 팝업용 상세 데이터를 조회합니다. 요약 통계, 월별 추이, 사용자별 비율, 최근 거래 목록을 포함합니다.",
* 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/CardTransactionDashboard")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음")
* )
*/
public function dashboard() {}
/**
* @OA\Put(
* path="/api/v1/card-transactions/bulk-update-account",
* operationId="bulkUpdateCardTransactionAccountCode",
* tags={"CardTransaction"},
* summary="계정과목 일괄 수정",
* description="선택한 카드 거래들의 계정과목을 일괄 수정합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\RequestBody(
* required=true,
*
* @OA\JsonContent(ref="#/components/schemas/CardTransactionBulkUpdateRequest")
* ),
*
* @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",
* type="object",
* @OA\Property(property="updated_count", type="integer", description="수정된 건수", example=5)
* )
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음"),
* @OA\Response(response=422, description="유효성 검사 실패")
* )
*/
public function bulkUpdateAccountCode() {}
/**
* @OA\Get(
* path="/api/v1/card-transactions/{id}",
* operationId="getCardTransaction",
* tags={"CardTransaction"},
* summary="카드 거래 상세 조회",
* description="특정 카드 거래의 상세 정보를 조회합니다.",
* security={{"ApiKeyAuth": {}}, {"BearerAuth": {}}},
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* description="거래 ID",
*
* @OA\Schema(type="integer", example=1)
* ),
*
* @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/CardTransactionItem")
* )
* ),
*
* @OA\Response(response=401, description="인증 실패"),
* @OA\Response(response=403, description="권한 없음"),
* @OA\Response(response=404, description="거래를 찾을 수 없음")
* )
*/
public function show() {}
}