Files
Gnuboard7/modules/_bundled/sirsoft-ecommerce/docs/api/coupons.md
T
HeuJung b5c0ec1178 fix(core,ecommerce,board,page,admin_basic,basic): 목록 응답의 하위 컬렉션 전량 직렬화 해소
관리자 상품목록을 한 페이지 여는 것만으로 그 페이지 모든 상품의 옵션이 응답에 실렸다.
같은 패턴을 저장소 전역에서 찾아 14개 목록 엔드포인트를 함께 정리했다.

근본 원인은 둘이다. Resource 가 whenLoaded 로 방어하는데 Repository 가 목록 쿼리에서
관계를 무조건 로드해 가드가 항상 참이 되는 가짜 가드, 그리고 toListArray 경량 표현을
정의해 두고도 컬렉션이 toArray 를 부르는 목록/상세 미분리다. 둘 다 응답만 보면
정상이라 오류도 경고도 없이 페이로드만 불어난다.

목록은 화면이 실제로 그리는 것만 싣는다. 개수·합계는 PHP 컬렉션 연산이 아니라 DB
집계로, 대표 1건이 필요한 곳은 관계 자체를 oldestOfMany 로 좁힌다. eager load 의
limit(1) 은 부모별이 아니라 배치 쿼리 전체에 걸려 첫 행만 값을 갖게 되므로 쓸 수 없다.

뺀 값에는 대체 경로를 먼저 만들었다. 상품 옵션은 행을 펼칠 때 배치로 불러오고(상품 수와
무관하게 쿼리 상수), 종전 동작이 필요한 호출자를 위해 ?with_options=1 등 opt-in 을 남겼다.
배송정책 국가설정과 리뷰 첨부 이미지는 소비처를 실측한 결과 화면이 실제로 그리고 있어
제거하지 않았다 — 그 소비 사실을 회귀 테스트로 고정했다.

재발 방지로 정적 검사 룰 4종과 규정 문서 항목을 함께 넣었다.
2026-08-05 21:20:05 +09:00

24 KiB
Raw Blame History

Coupons API 레퍼런스

소유: module sirsoft-ecommerce · 생성: php artisan api:docgen (실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.


TL;DR (5초 요약)

1. 이 문서는 실제 API 호출로 실측한 Coupons 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(curl) + 실측 응답 필드 표 + 응답 예시(envelope)
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
5. 설명(TODO) 칸은 사람이 채웁니다

GET /api/modules/sirsoft-ecommerce/user/coupons

  • 라우트명: api.modules.sirsoft-ecommerce.user.coupons.index
  • 컨트롤러: Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@index
  • 인증/권한: auth:sanctum

요청 파라미터

이름 위치 타입 필수 허용값 용도
status query string 아니오 available, used, expired 상태 필터 (해당 상태의 항목만 조회)
per_page query integer 아니오 min 1, max 50 페이지당 항목 수

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-ecommerce.coupon.user_list_validation_rules).

요청 예시

GET /api/modules/sirsoft-ecommerce/user/coupons?status=available&per_page=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
coupons object {"data":[{"id":2512,"coupon_id":107,"user_id":"a26219fc-9… 회원이 발급받은 쿠폰(발급 내역) 페이지네이션 객체 (data[] 발급 건 + pagination — CouponIssueCollection 직렬화, 쿠폰 정의가 아닌 회원별 발급 건)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "쿠폰 목록을 조회했습니다.",
    "data": {
        "coupons": {
            "data": [
                {
                    "id": 2512,
                    "coupon_id": 107,
                    "user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
                    "coupon_code": "DL-ORG8PPAH",
                    "status": "used",
                    "...": "(12개 키 생략, 총 17개)"
                },
                {
                    "id": 2513,
                    "coupon_id": 61,
                    "user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
                    "coupon_code": "DR-WC3RLEDB",
                    "status": "used",
                    "...": "(12개 키 생략, 총 17개)"
                },
                {
                    "id": 2514,
                    "coupon_id": 62,
                    "user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
                    "coupon_code": "DR-VHQFNYRR",
                    "status": "used",
                    "...": "(12개 키 생략, 총 17개)"
                },
                {
                    "id": 2515,
                    "coupon_id": 63,
                    "user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
                    "coupon_code": "DR-4QRXNXAI",
                    "status": "used",
                    "...": "(12개 키 생략, 총 17개)"
                },
                {
                    "id": 2516,
                    "coupon_id": 64,
                    "user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
                    "coupon_code": "DR-IT4CCTSM",
                    "status": "used",
                    "...": "(12개 키 생략, 총 17개)"
                },
                "... (총 25건 중 5건 표시)"
            ],
            "pagination": {
                "current_page": 1,
                "last_page": 2,
                "per_page": 25,
                "total": 41,
                "from": 1,
                "...": "(2개 키 생략, 총 7개)"
            }
        }
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 로그인한 회원이 마이페이지 쿠폰함에서 자신이 발급받은 쿠폰(발급 내역)을 페이지네이션으로 조회합니다. auth:sanctum 인증이 필요하며, status 필터(available·used·expired)로 사용 가능/사용 완료/만료 쿠폰을 구분합니다. UserCouponService::getUserCoupons()가 조회하고 CouponIssueCollection으로 직렬화되므로, 여기의 항목은 쿠폰 정의(마스터)가 아니라 회원별 발급 건입니다.

GET /api/modules/sirsoft-ecommerce/user/coupons/available

  • 라우트명: api.modules.sirsoft-ecommerce.user.coupons.available
  • 컨트롤러: Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@available
  • 인증/권한: auth:sanctum

요청 파라미터

이름 위치 타입 필수 허용값 용도
product_ids query array 아니오 — product 식별자 배열

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-ecommerce.coupon.user_available_validation_rules).

요청 예시

GET /api/modules/sirsoft-ecommerce/user/coupons/available?product_ids=%EC%98%88%EC%8B%9C%EA%B0%92 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

단건 응답: data 객체의 필드.

필드 타입 실측 예시값 용도/설명
coupons array [{"id":2534,"coupon_id":85,"user_id":1209,"coupon_code":"… 현재 장바구니 상품에 적용 가능한 보유 쿠폰(발급 건) 배열 (상품/카테고리 범위·최소 주문금액·유효기간을 만족해 주문에 곧바로 선택 가능한 후보만)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "사용 가능한 쿠폰 목록을 조회했습니다.",
    "data": {
        "coupons": [
            {
                "id": 2534,
                "coupon_id": 85,
                "user_id": 1209,
                "coupon_code": "DR-PDZ7HT4G",
                "status": "available",
                "...": "(8개 키 생략, 총 13개)"
            },
            {
                "id": 2542,
                "coupon_id": 94,
                "user_id": 1209,
                "coupon_code": "DR-ROQPOOED",
                "status": "available",
                "...": "(8개 키 생략, 총 13개)"
            },
            {
                "id": 2552,
                "coupon_id": 106,
                "user_id": 1209,
                "coupon_code": "DR-XBLQUABC",
                "status": "available",
                "...": "(8개 키 생략, 총 13개)"
            },
            {
                "id": 2529,
                "coupon_id": 79,
                "user_id": 1209,
                "coupon_code": "DR-90IO2SWI",
                "status": "available",
                "...": "(8개 키 생략, 총 13개)"
            },
            {
                "id": 2532,
                "coupon_id": 83,
                "user_id": 1209,
                "coupon_code": "DR-FEKYVAFT",
                "status": "available",
                "...": "(8개 키 생략, 총 13개)"
            },
            "... (총 27건 중 5건 표시)"
        ]
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 체크아웃 화면에서 회원이 현재 장바구니 상품에 실제로 적용할 수 있는 보유 쿠폰만 추려서 반환합니다. auth:sanctum 인증이 필요하고 product_ids 로 대상 상품을 전달하면, UserCouponService::getAvailableCoupons()가 보유 쿠폰 중 상품/카테고리 적용 범위·최소 주문금액·유효기간 등을 만족하는 것만 필터링해 내려줍니다. 쿠폰함 목록(index)과 달리 주문에 곧바로 선택 가능한 후보만 반환하는 점이 다릅니다.

GET /api/modules/sirsoft-ecommerce/user/coupons/downloadable

  • 라우트명: api.modules.sirsoft-ecommerce.user.coupons.downloadable
  • 컨트롤러: Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@downloadable
  • 인증/권한: auth:sanctum

요청 파라미터

이름 위치 타입 필수 허용값 용도
per_page query integer 아니오 min 1, max 50 페이지당 항목 수

이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (sirsoft-ecommerce.coupon.user_downloadable_validation_rules).

요청 예시

GET /api/modules/sirsoft-ecommerce/user/coupons/downloadable?per_page=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}

응답 필드 (data 내부)

목록 응답: data.data[] 배열 항목의 필드.

필드 타입 실측 예시값 용도/설명
id integer 107 기본 키 (내부 식별자)
name object {"ko":"카테고리 배송비 3,000원 할인","en":"Category Shipping 3,000 … 대상의 이름/명칭 (다국어 필드는 로케일별 값 객체)
description object {"ko":"특정 카테고리 배송비 할인","en":"Shipping discount on categor… 설명 (다국어 필드는 로케일별 값 객체)
target_type string shipping_fee 할인 적용 대상 (product_amount=상품금액, order_amount=주문금액, shipping_fee=배송비)
discount_type string fixed 혜택 유형 (fixed=정액 할인, rate=정률(%) 할인)
discount_value string 3000.00 혜택값 (정액이면 할인 금액, 정률이면 할인율 %)
discount_max_amount string 3000.00 정률 할인 시 최대 할인 금액 상한 (없으면 null)
min_order_amount string 20000.00 쿠폰 적용 최소 주문금액 (미만 주문에는 사용 불가)
issue_method string download 발급 방법 (direct=직접발급, download=다운로드, auto=자동발급)
issue_condition string manual 발급 조건 (manual=수동, signup=회원가입, first_purchase=첫구매, birthday=생일)
issue_status string issuing 발급 상태 (issuing=발급중, stopped=발급중단)
total_quantity integer 300 총 발급 수량 상한 (null=무제한)
issued_count integer 1 issued 개수 (집계)
per_user_limit integer 1 회원 1인당 발급 제한 수량
valid_type string period 유효기간 유형 (period=기간지정, days_from_issue=발급일로부터 N일)
valid_days integer 14 발급일로부터 유효한 일수 (valid_type=days_from_issue 인 경우)
valid_from string 2026-07-23T14:36:17.000000Z 유효기간 시작일 (쿠폰 사용 가능 시작 시각)
valid_to string 2026-09-21T14:36:17.000000Z 유효기간 종료일 (쿠폰 사용 가능 종료 시각)
issue_from string 2026-07-23T14:36:17.000000Z 발급기간 시작일 (다운로드 가능 시작 시각)
issue_to string 2026-08-29T14:36:17.000000Z 발급기간 종료일 (다운로드 가능 종료 시각)
is_combinable boolean true combinable 여부
target_scope string categories 적용 범위 (all=전체 상품, products=특정 상품, categories=특정 카테고리)
created_by null null 쿠폰 등록자(관리자) 식별자 (users 참조, 삭제 시 null)
created_at string 2026-07-30T14:36:17.000000Z 생성 일시
updated_at string 2026-07-31T12:51:54.000000Z 최종 수정 일시
deleted_at null null 소프트 삭제 일시 (미삭제 시 null)
is_downloaded boolean true downloaded 여부
user_issued_count integer 1 user issued 개수 (집계)
coupon_id integer 107 coupon 식별자 (연관 리소스 참조)
localized_name string 카테고리 배송비 3,000원 할인 name 의 현재 로케일 해석 값 (다국어 필드를 표시용 문자열로 해석)
target_type_short_label string 배송비 target_type_short 값의 사람이 읽는 라벨 (현지화/Enum 파생)
valid_period_formatted string 2026-07-23 ~ 2026-09-21 valid_period 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
min_order_amount_formatted string ¥20,000 min_order_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
remaining_quantity integer 299 잔여 발급 가능 수량 (total_quantity − issued_count, 무제한이면 null)
benefit_formatted string ¥3,000 할인 benefit 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷)
included_products array [] 적용 대상 포함 상품 목록 (target_scope=products 시 이 상품에만 적용)
excluded_products array [] 적용 제외 상품 목록 (해당 상품은 쿠폰 적용에서 제외)
included_categories array [{"id":32,"name":{"ko":"바지","en":"Pants"},"description":{… 적용 대상 포함 카테고리 목록 (target_scope=categories 시 이 카테고리에만 적용)
excluded_categories array [] 적용 제외 카테고리 목록 (해당 카테고리는 쿠폰 적용에서 제외)

응답 예시

HTTP/1.1 200
{
    "success": true,
    "message": "다운로드 가능한 쿠폰 목록을 불러왔습니다.",
    "data": {
        "current_page": 1,
        "data": [
            {
                "id": 107,
                "name": {
                    "ko": "카테고리 배송비 3,000원 할인",
                    "en": "Category Shipping 3,000 KRW Off"
                },
                "description": {
                    "ko": "특정 카테고리 배송비 할인",
                    "en": "Shipping discount on categories"
                },
                "target_type": "shipping_fee",
                "discount_type": "fixed",
                "discount_value": "3000.00",
                "discount_max_amount": null,
                "min_order_amount": "20000.00",
                "issue_method": "download",
                "issue_condition": "manual",
                "issue_status": "issuing",
                "total_quantity": 300,
                "issued_count": 1,
                "per_user_limit": 1,
                "valid_type": "period",
                "valid_days": null,
                "valid_from": "2026-07-23T14:36:17.000000Z",
                "valid_to": "2026-09-21T14:36:17.000000Z",
                "issue_from": "2026-07-23T14:36:17.000000Z",
                "issue_to": "2026-08-29T14:36:17.000000Z",
                "is_combinable": true,
                "target_scope": "categories",
                "created_by": null,
                "created_at": "2026-07-30T14:36:17.000000Z",
                "updated_at": "2026-07-31T12:51:54.000000Z",
                "deleted_at": null,
                "is_downloaded": true,
                "user_issued_count": 1,
                "coupon_id": 107,
                "localized_name": "카테고리 배송비 3,000원 할인",
                "target_type_short_label": "배송비",
                "valid_period_formatted": "2026-07-23 ~ 2026-09-21",
                "min_order_amount_formatted": "¥20,000",
                "remaining_quantity": 299,
                "benefit_formatted": "¥3,000 할인",
                "included_products": [],
                "excluded_products": [],
                "included_categories": [
                    {
                        "id": 32,
                        "name": {
                            "ko": "바지",
                            "en": "Pants"
                        },
                        "description": {
                            "ko": "다양한 스타일의 바지",
                            "en": "Various styles of pants"
                        },
                        "parent_id": 30,
                        "path": "29/30/32",
                        "depth": 2,
                        "sort_order": 1,
                        "is_active": true,
                        "slug": "men-pants",
                        "meta_title": null,
                        "meta_description": null,
                        "created_at": "2026-07-30T14:35:47.000000Z",
                        "updated_at": "2026-07-30T14:35:47.000000Z",
                        "pivot": {
                            "coupon_id": 107,
                            "category_id": 32
                        }
                    },
                    {
                        "id": 42,
                        "name": {
                            "ko": "노트북",
                            "en": "Laptops"
                        },
                        "description": {
                            "ko": "노트북 컴퓨터",
                            "en": "Laptop computers"
                        },
                        "parent_id": 38,
                        "path": "38/42",
                        "depth": 1,
                        "sort_order": 1,
                        "is_active": true,
                        "slug": "laptops",
                        "meta_title": null,
                        "meta_description": null,
                        "created_at": "2026-07-30T14:35:47.000000Z",
                        "updated_at": "2026-07-30T14:35:47.000000Z",
                        "pivot": {
                            "coupon_id": 107,
                            "category_id": 42
                        }
                    }
                ],
                "excluded_categories": []
            },
            {
                "id": 103,
                "name": {
                    "ko": "배송비 50% 할인",
                    "en": "Shipping 50% Off"
                },
                "description": {
                    "ko": "배송비 반값 할인",
                    "en": "50% off shipping fee"
                },
                "target_type": "shipping_fee",
                "discount_type": "rate",
                "discount_value": "50.00",
                "discount_max_amount": "3000.00",
                "min_order_amount": "20000.00",
                "issue_method": "download",
                "issue_condition": "manual",
                "issue_status": "issuing",
                "total_quantity": 1000,
                "issued_count": 62,
                "per_user_limit": 1,
                "valid_type": "days_from_issue",
                "valid_days": 14,
                "valid_from": null,
                "valid_to": null,
                "issue_from": "2026-07-25T14:36:17.000000Z",
                "issue_to": "2026-09-28T14:36:17.000000Z",
                "is_combinable": true,
                "target_scope": "all",
                "created_by": null,
                "created_at": "2026-07-30T14:36:17.000000Z",
                "updated_at": "2026-07-31T12:52:41.000000Z",
                "deleted_at": null,
                "is_downloaded": true,
                "user_issued_count": 1,
                "coupon_id": 103,
                "localized_name": "배송비 50% 할인",
                "target_type_short_label": "배송비",
                "valid_period_formatted": "발급일로부터 14일",
                "min_order_amount_formatted": "¥20,000",
                "remaining_quantity": 938,
                "benefit_formatted": "50.00% 할인 (최대 ¥3,000)",
                "included_products": [],
                "excluded_products": [],
                "included_categories": [],
                "excluded_categories": []
            },
            "... (총 11건 중 2건 표시)"
        ],
        "first_page_url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
        "from": 1,
        "last_page": 1,
        "last_page_url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
        "links": [
            {
                "url": null,
                "label": "pagination.previous",
                "page": null,
                "active": false
            },
            {
                "url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "pagination.next",
                "page": null,
                "active": false
            }
        ],
        "next_page_url": null,
        "path": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable",
        "per_page": 25,
        "prev_page_url": null,
        "to": 11,
        "total": 11
    }
}

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)

설명 로그인한 회원이 지금 다운로드해 발급받을 수 있는 쿠폰(다운로드형) 목록을 페이지네이션으로 조회합니다. auth:sanctum 인증이 필요하며, UserCouponService::getDownloadableCoupons()가 발급기간·수량·회원당 한도를 만족하는 다운로드형 쿠폰을 반환하고 각 항목에 is_downloaded·user_issued_count로 이미 받았는지 여부를 표시합니다. 여기 항목은 아직 발급 전이므로 쿠폰 정의(마스터) 기준이며, 실제 발급은 download 엔드포인트로 수행합니다.

POST /api/modules/sirsoft-ecommerce/user/coupons/{couponId}/download

  • 라우트명: api.modules.sirsoft-ecommerce.user.coupons.download
  • 컨트롤러: Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@download
  • 인증/권한: auth:sanctum

요청 파라미터

이름 위치 타입 필수 허용값 용도
couponId path string 예 — 대상 coupon의 식별자
coupon_id body integer 예 — coupon 식별자

요청 예시

POST /api/modules/sirsoft-ecommerce/user/coupons/{couponId}/download HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json

{
    "coupon_id": 1
}

응답 필드 (data 내부)

응답 예시

에러 응답

상태코드 의미 발생 조건
401 Unauthenticated 유효한 Bearer 토큰이 없거나 만료된 경우
422 Unprocessable Entity 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지)
404 Not Found path 파라미터에 해당하는 리소스가 없는 경우

설명 로그인한 회원이 다운로드형 쿠폰 1건을 실제로 발급받습니다. auth:sanctum 인증이 필요하고 대상 쿠폰은 couponId(경로)로 지정하며, UserCouponService::downloadCoupon()이 발급기간·수량·회원당 한도·중복 발급 여부를 검증한 뒤 발급 내역을 생성해 201로 반환합니다. 한도 초과·발급기간 종료 등 발급 불가 사유는 서비스 예외의 메시지와 코드가 그대로 오류 응답에 전달됩니다.