Skip to main content

개요

Core 서비스의 쿠폰 도메인은 할인 쿠폰의 발급, 적용, 만료 처리 및 사용 이력 관리 기능을 제공합니다. 숙소별 쿠폰과 전체 시스템 쿠폰을 모두 지원하며, 다양한 할인 유형과 사용 제한 조건을 설정할 수 있습니다.

Queries

getAccommodationCoupons

숙소의 쿠폰 목록을 조회합니다. (관리자 전용)

GraphQL Signature

query GetAccommodationCoupons(
  $accommodationId: ID!
  $first: Int
  $after: String
) {
  getAccommodationCoupons(
    accommodationId: $accommodationId
    first: $first
    after: $after
  ) {
    nodes {
      id
      code
      name
      couponType
      discountType
      discount
      maxDiscountAmount
      maxUsableCount
      usableCount
      minUsableAmount
      expireAt
      isExhausted
      createdAt
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

파라미터

accommodationId
ID!
required
조회할 숙소 ID (관리자 권한 필요)
first
Int
페이지당 항목 수 (기본값: 20)
after
String
페이지네이션 커서

응답

nodes
Coupon[]
쿠폰 목록
  • id: 쿠폰 고유 ID
  • code: 쿠폰 코드 (고객이 입력하는 코드)
  • name: 쿠폰명
  • couponType: 쿠폰 유형
  • discountType: 할인 유형 (정액/정률)
  • discount: 할인 금액/비율
  • maxDiscountAmount: 최대 할인 금액
  • maxUsableCount: 최대 사용 가능 횟수
  • usableCount: 남은 사용 가능 횟수
  • minUsableAmount: 최소 사용 금액
  • expireAt: 만료일
  • isExhausted: 소진 여부
  • createdAt: 생성일
pageInfo
PageInfo
페이지네이션 정보

예제

query {
  getAccommodationCoupons(
    accommodationId: "acc_123"
    first: 10
  ) {
    nodes {
      id
      code
      name
      discountType
      discount
      usableCount
      expireAt
    }
    pageInfo {
      hasNextPage
    }
  }
}

Mutations

issueCoupon

새로운 쿠폰을 발급합니다. (관리자 또는 시스템 관리자 전용)

GraphQL Signature

mutation IssueCoupon($input: IssueCouponInput!) {
  issueCoupon(input: $input) {
    id
    code
    name
    couponType
    discountType
    discount
    maxDiscountAmount
    maxUsableCount
    minUsableAmount
    expireAt
    createdAt
  }
}

파라미터

input
IssueCouponInput!
required
쿠폰 발급 정보:
  • accommodationId (ID): 숙소 ID (null이면 전체 시스템 쿠폰)
  • name (String!): 쿠폰명
  • couponType (String!): 쿠폰 유형
  • discountType (String!): 할인 유형 (“FIXED” 또는 “PERCENT”)
  • discount (Int!): 할인 금액 또는 비율
  • maxDiscountAmount (Int): 최대 할인 금액 (정률 할인 시 필수)
  • maxUsableCount (Int): 최대 사용 가능 횟수 (기본값: 1)
  • minUsableAmount (Int): 최소 사용 금액
  • quantity (Int!): 발급 수량
  • expireAt (DateTime): 만료일 (기본값: 9999-12-31)
  • mask (String): 사용 제한 마스크 (JSON 형식)

응답

coupons
Coupon[]
발급된 쿠폰 목록 (quantity만큼 생성됨)

예제

mutation {
  issueCoupon(input: {
    accommodationId: "acc_123"
    name: "신규 고객 환영 쿠폰"
    couponType: "WELCOME"
    discountType: "FIXED"
    discount: 10000
    maxUsableCount: 1
    minUsableAmount: 50000
    quantity: 100
    expireAt: "2024-12-31T23:59:59Z"
  }) {
    id
    code
    name
    discount
  }
}
  • 쿠폰 코드는 쿠폰 ID를 기반으로 자동 생성됩니다
  • quantity만큼 동일한 조건의 쿠폰이 생성됩니다
  • accommodationId를 null로 설정하면 전체 시스템에서 사용 가능한 쿠폰이 됩니다

applyCoupon

구매 시 쿠폰을 적용하여 할인 금액을 계산하고 사용 이력을 생성합니다.

GraphQL Signature

mutation ApplyCoupon(
  $code: String!
  $purchaseAmount: Int!
  $accommodationId: ID
  $roomTypeId: ID
  $usageHashMask: String
) {
  applyCoupon(
    code: $code
    purchaseAmount: $purchaseAmount
    accommodationId: $accommodationId
    roomTypeId: $roomTypeId
    usageHashMask: $usageHashMask
  ) {
    id
    usageHash
    couponId
    purchaseAmount
    discountAmount
    status
    createdAt
  }
}

파라미터

code
String!
required
쿠폰 코드
purchaseAmount
Int!
required
구매 금액
accommodationId
ID
숙소 ID (숙소 전용 쿠폰 검증용)
roomTypeId
ID
객실 유형 ID (특정 객실 유형 제한 쿠폰용)
usageHashMask
String
이전 사용 이력 무효화용 해시 (쿠폰 재적용 시)

응답

couponUsageHistory
CouponUsageHistory
쿠폰 사용 이력
  • id: 사용 이력 ID
  • usageHash: 사용 고유 해시 (결제 완료 시 필요)
  • couponId: 쿠폰 ID
  • purchaseAmount: 구매 금액
  • discountAmount: 할인 금액
  • status: 사용 상태 (“PENDING”)
  • createdAt: 생성일

예제

mutation {
  applyCoupon(
    code: "WELCOME2024"
    purchaseAmount: 100000
    accommodationId: "acc_123"
  ) {
    id
    usageHash
    discountAmount
    status
  }
}

할인 금액 계산 로직

  1. 정액 할인 (FIXED): discount 값을 그대로 적용
  2. 정률 할인 (PERCENT): purchaseAmount * (discount / 100), 단 maxDiscountAmount를 초과할 수 없음
  3. 최소 사용 금액: purchaseAmountminUsableAmount보다 작으면 사용 불가
  4. 할인 금액 검증: discountAmountpurchaseAmount보다 클 수 없음

에러 처리

DATA_NOT_FOUND_ON_ID
해당 코드의 쿠폰을 찾을 수 없습니다.
INVALID_PARAMETER
할인 금액이 유효하지 않거나 구매 금액을 초과합니다.
쿠폰 적용 후 실제 결제 완료 시 usageHash를 사용하여 사용 상태를 “USED”로 변경해야 합니다. 결제가 취소되면 usageHash를 사용하여 사용 이력을 “INVALID”로 변경할 수 있습니다.

expireCoupon

쿠폰을 수동으로 만료 처리합니다. (관리자 전용)

GraphQL Signature

mutation ExpireCoupon($code: String!) {
  expireCoupon(code: $code) {
    id
    code
    isExhausted
    expireAt
  }
}

파라미터

code
String!
required
만료 처리할 쿠폰 코드

응답

coupon
Coupon
만료 처리된 쿠폰 정보
  • id: 쿠폰 ID
  • code: 쿠폰 코드
  • isExhausted: 소진 여부 (true)
  • expireAt: 만료일 (현재 시각으로 변경됨)

예제

mutation {
  expireCoupon(code: "WELCOME2024") {
    id
    code
    isExhausted
    expireAt
  }
}

에러 처리

DATA_NOT_FOUND_ON_ID
해당 코드의 쿠폰을 찾을 수 없습니다.
만료된 쿠폰은 더 이상 사용할 수 없으며, isExhausted가 true로 설정되고 expireAt이 현재 시각으로 변경됩니다.

사용 흐름

쿠폰 발급 및 사용 흐름

  1. 쿠폰 발급: issueCoupon으로 쿠폰 생성 (관리자)
  2. 쿠폰 배포: 생성된 쿠폰 코드를 고객에게 제공
  3. 쿠폰 적용: 고객이 결제 시 applyCoupon으로 할인 금액 계산
  4. 결제 처리: 할인된 금액으로 결제 진행
  5. 사용 완료: 결제 완료 시 usageHash로 사용 상태 업데이트

쿠폰 재적용 흐름 (결제 취소 시)

  1. 기존 쿠폰 무효화: usageHashMask에 이전 usageHash 전달
  2. 새로운 사용 이력 생성: 새로운 usageHash 발급
  3. 재결제: 새로운 할인 금액으로 결제 진행

쿠폰 유형

할인 유형 (discountType)

  • FIXED: 정액 할인 (예: 10,000원 할인)
  • PERCENT: 정률 할인 (예: 10% 할인, 최대 5,000원)

사용 제한

  • maxUsableCount: 쿠폰당 최대 사용 가능 횟수
  • minUsableAmount: 최소 구매 금액 제한
  • expireAt: 쿠폰 만료일
  • mask: 특정 조건 제한 (JSON 형식)
  • accommodationId: 특정 숙소 전용 쿠폰

관련 API