openapi: 3.0.3
info:
  title: KOS OpenAPI
  description: >
    KOS OpenAPI는 KOS 솔루션을 사용하는 병원들의 개발팀만 사용 가능합니다.


    자세한 사항은 해당 병원의 KOS 영업 담당자를 통해 문의 바랍니다.


    이 문서는 [OpenAPI Spec](/openapi.yaml) 파일을 통해 확인할 수 있습니다.


    ### API 요청 방법


    1. KOS OpenAPI는 조회, 수정, 삭제 등 모두 POST 방식으로 요청합니다.


    2. 인증 관련을 제외한 모든 요청은 `Authorization` 헤더에 인증 토큰(Auth Token)이 포함되어야 합니다. 자세한
    내용은 [인증 방법](/docs/openapi/authorization)을 참고하세요.


    3. 모든 에러 응답은 종류와 무관하게 `400` 상태 코드를 반환합니다. 에러 응답의 상세 내용을 통해 에러 원인을 확인할 수
    있습니다. 자세한 내용은 [에러 응답](#에러-응답)을 참고하세요.


    ### 날짜 및 시간 형식


    조회와 명령에 사용되는 모든 날짜 및 시간 형식은 [ISO
    8601](https://ko.wikipedia.org/wiki/ISO_8601) 포맷의 문자열을 사용합니다.


    ```text

    YYYY-MM-DDTHH:MM:SSZ

    예시: 2021-01-01T00:00:00Z

    ```


    모든 날짜 및 시간은 UTC 시간대여야 합니다.


    ### 국가 코드 형식


    모든 국가 코드는 [ISO 3166-1
    alpha-2](https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2) 포맷의 문자열을 사용합니다.


    ```text

    예시: KR, US, JP, CN...

    ```


    :::warning


    단, 국가별로 보여줄 상품을 지정할 수 있고, 해당 국가에 맞는 수가를 설정하기 위한, '타겟 국가'의 **'그 외 국가'는
    `ETC`** 로 표기합니다.


    자세한 설명은 [타겟 국가](/docs/openapi/target-country)를 참고하세요.


    :::


    ### 에러 응답


    조회 혹은 명령을 정상적으로 처리할 수 없는 경우, `400` HTTP 상태 코드와 함께 아래와 같은 에러 응답이 돌아옵니다.


    ```json

    {
      "status": 400,
      "message": "InvalidCommandException",
      "className": "InvalidCommandException",
      "errorProperties": [
        {
          "key": "{{ Key }}",
          "reason": "{{ ErrorReason }}"
        }
      ]
    }

    ```


    - `key`: 누락된 필드명 혹은 잘못된 값을 가진 필드명

    - `reason`: 에러 원인
      - `TooShort`: 문자열이 너무 짧음
      - `TooLong`: 문자열이 너무 길음
      - `Required`: 필수 항목이 누락됨
      - `Duplicated`: 중복됨
      - `InvalidTimeRange`: 시간 범위 유효성 검사 실패
      - `NotAvailable`: 사용 불가
      - `NotFound`: 대상이 없음
      - `TooSmall`: 너무 작은 값
      - `TooBig`: 너무 큰 값
  version: 1.0.1
servers:
  - url: https://open-api.kos-solution.com
    description: 운영 환경
  - url: https://open-api.dev.kos-solution.com
    description: 개발 환경
paths:
  /image/open/v1/commands/generate-uploading-url:
    post:
      tags:
        - Image
      summary: 이미지 업로드 url 발급
      description: 이미지 업로드 url을 발급합니다.
      operationId: generateUploadingImageUrl
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GenerateUploadingImageUrl"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GenerateUploadingImageUrlResponse"
      security:
        - auth_token: []
  /image/open/v1/commands/register-visitor-images:
    post:
      tags:
        - Image
      summary: 내원객 이미지 등록
      description: 내원객에 이미지를 등록합니다
      operationId: registerVisitorImages
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.RegisterVisitorImages"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /open/authorization/commands/exchange-token:
    post:
      tags:
        - Authorization
      summary: 인증 토큰 교환
      operationId: exchangeToken
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.ExchangeTokenCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.ExchangeTokenResponse"
  /procedure-menu/open/categories/queries/get-categories:
    post:
      tags:
        - Product
      summary: 상품 카테고리 목록 조회
      operationId: getCategories
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenGetCategoriesQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetCategoriesQueryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/products/queries/get-product:
    post:
      tags:
        - Product
      summary: 상품 조회
      description: |-
        상품 상세 정보를 조회합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>상품이 존재하지 않을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "productId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>해당 채널에 노출 가능한 옵션이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "productId", "reason": "NotFound"}]
         }
         ```
         </details>
      operationId: getProduct
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenGetProductQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.OpenProductDetailContract"
      security:
        - auth_token: []
  /procedure-menu/open/products/queries/get-products:
    post:
      tags:
        - Product
      summary: 상품 목록 조회
      description: 상품 목록을 조회합니다.
      operationId: getProducts
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenGetProductsQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetOpenProductsQueryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/products/queries/search-product-option-summaries:
    post:
      tags:
        - Product
      summary: 상품 옵션 검색
      operationId: searchProductOptionSummaries
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.SearchProductOptionSummariesQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.OpenSearchProductOptionSummariesQu\
                  eryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/promotions/v1/queries/get-promotion:
    post:
      tags:
        - Promotion
      summary: 프로모션 조회 (deprecated)
      operationId: getPromotion
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.procedure.GetPromotionQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetPromotionQueryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/promotions/v1/queries/get-promotion-categories:
    post:
      tags:
        - Promotion
      summary: 프로모션 카테고리 목록 조회 (deprecated)
      operationId: getPromotionCategories
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.Empty"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetPromotionCategoriesQueryRespons\
                  e"
      security:
        - auth_token: []
  /procedure-menu/open/promotions/v1/queries/get-promotion-summaries:
    post:
      tags:
        - Promotion
      summary: 프로모션 목록 조회 (deprecated)
      operationId: getPromotions
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetPromotionsQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetPromotionSummariesQueryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/target-countries/queries/get-target-countries:
    post:
      tags:
        - TargetCountry
      summary: 타겟 국가 목록 조회
      operationId: getTargetCountries
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.Empty"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetTargetCountriesQueryResponse"
      security:
        - auth_token: []
  /procedure-menu/open/v1/product-options/queries/get-product-options:
    post:
      tags:
        - Product
      summary: 상품 옵션 목록 조회
      operationId: getProductOptions
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.procedure.GetProductOptionsQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.procedure.GetProductOptionsQueryResponse"
      security:
        - auth_token: []
  /purchase/open/prepaid-card/v1/queries/get-prepaid-card-charging-events:
    post:
      tags:
        - PrepaidCard
      summary: 선불카드 사용 이력 조회
      operationId: getPrepaidCardChargingEvents
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.purchase.GetPrepaidCardChargingEventsQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.purchase.GetPrepaidCardChargingEventsQueryRe\
                  sponse"
      security:
        - auth_token: []
  /purchase/open/prepaid-card/v1/queries/get-prepaid-card-summaries:
    post:
      tags:
        - PrepaidCard
      summary: 선불카드 목록 조회
      operationId: getPrepaidCardSummaries
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.purchase.GetPrepaidCardSummariesQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.purchase.GetPrepaidCardSummariesQueryRespons\
                  e"
      security:
        - auth_token: []
  /purchase/open/prepaid-card/v1/queries/get-visitor-prepaid-card-balance:
    post:
      tags:
        - PrepaidCard
      summary: 내원객 선불카드 잔액 조회 (잔액 + 잔여 포인트 + 최근 충전일)
      operationId: getVisitorPrepaidCardBalance
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.purchase.GetVisitorPrepaidCardBalanceQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.purchase.GetVisitorPrepaidCardBalanceQueryRe\
                  sponse"
      security:
        - auth_token: []
  /purchase/open/v1/queries/get-purchase-summaries:
    post:
      tags:
        - Purchase
      summary: 수납 내역 조회
      description: 수납 ID 목록으로 수납 내역을 조회합니다.
      operationId: getPurchaseSummaries
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetPurchaseSummariesQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetPurchaseSummariesQueryResponse"
      security:
        - auth_token: []
  /purchase/open/v1/queries/get-purchase-summaries-by-visitor-id:
    post:
      tags:
        - Purchase
      summary: 내원객 수납 내역 조회
      operationId: getPurchaseSummariesByVisitor
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.purchase.GetPurchaseSummariesQueryByVisitorI\
                d"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.purchase.GetPurchaseSummariesQueryByVisitorI\
                  dResponse"
      security:
        - auth_token: []
  /schedule/open/v1/commands/cancel-reservation:
    post:
      tags:
        - Schedule
      summary: 예약 취소
      description: |-
        기존 예약을 취소합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>취소하고자 하는 예약이 예약됨 상태가 아닐경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "status",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>

         <details>
         <summary>예약 취소 정책에 의해 취소가 허용되지 않을 경우 (취소 마감 시간 초과 포함)</summary>

         ```json
         {
           status: 400,
           message: "ReservationNotAllowedByPolicy",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "cancellationPolicy",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>
      operationId: cancelReservation
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.CancelReservationCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /schedule/open/v1/commands/create-occupied-time:
    post:
      tags:
        - Schedule
      summary: 시간 점유 생성
      description: >-
        시간 점유를 생성합니다.

         - startDateTimeUtc ~ endDateTimeUtc 시간대를 점유합니다.
         - 시간이 유효하지 않다면 에러가 발생합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>startDateTimeUtc가 올바른 시각이 아닐 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "startDateTimeUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>endDateTimeUtc가 올바른 시각이 아닐 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "endDateTimeUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>startDateTimeUtc가 endDateTimeUtc보다 큰 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "endDateTimeUtc",
               "reason": "InvalidTimeRange"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>startDateTimeUtc와 endDateTimeUtc가 동일하거나, 24시간 이상 차이날 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "endDateTimeUtc",
               "reason": "InvalidTimeRange"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>startDateTimeUtc와 endDateTimeUtc가 서로 다른 날짜일 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "endDateTimeUtc",
               "reason": "InvalidTimeRange"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>존재하지 않는 reservationGroupId, zoneId를 입력했을 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidCommandException",
           className: "InvalidCommandException",
           errorProperties: [
             {
               key: "{{ reservationGroupId 혹은 zoneId }}",
               reason: "NotFound"
             }
           ]
         }
         ```
         </details>
      operationId: createOccupiedTime
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenCreateOccupiedTimeCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.OpenCreateOccupiedTimeCommandResponse"
      security:
        - auth_token: []
  /schedule/open/v1/commands/reserve:
    post:
      tags:
        - Schedule
      summary: 새로운 예약 생성 (deprecated)
      description: |-
        @deprecated 신규 개발 시 [V2 API](/docs/openapi/reserve-v-2)를 사용하세요.

         새로운 예약을 생성합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>동일한 내원객에 대해, 시간이 겹치는 예약이 있음</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "startDateTime",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>
      operationId: reserveCommand
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.ReserveCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.ReserveCommandResponse"
      security:
        - auth_token: []
  /schedule/open/v1/commands/reserve-by-visitor-id:
    post:
      tags:
        - Schedule
      summary: 내원객 ID기반 새로운 예약 생성 (deprecated)
      description: >-
        @deprecated 신규 개발 시 [V2 API](/docs/openapi/reserve-by-visitor-id-v-2)를
        사용하세요.

         새로운 예약을 생성합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>동일한 내원객에 대해, 시간이 겹치는 예약이 있음</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "startDateTime",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>

         <details>
         <summary>visitorId에 해당하는 내원객이 존재하지 않을 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "visitorId",
               reason: "NotFound"
             },
           ],
         }
         ```
         </details>
      operationId: reserveByVisitorId
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.ReserveByVisitorIdCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.ReserveCommandResponse"
      security:
        - auth_token: []
  /schedule/open/v1/commands/update-reservation:
    post:
      tags:
        - Schedule
      summary: 예약 정보 수정 (deprecated)
      description: >-
        @deprecated 신규 개발 시 [V2 API](/docs/openapi/update-reservation-v-2)를
        사용하세요.

         기존 스케줄의 예약 정보를 수정합니다.
         - 예약 정보 수정 시, 기존의 예약 정보가 덮어씌워집니다.
         - 변경되지 않은 필드더라도, 전체 필드를 다시 보내야 합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>필수 항목이 누락된 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidCommandException",
           className: "InvalidCommandException",
           errorProperties: [
             {
               key: "{{ 누락된 키 }}",
               reason: "Required"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>reservationGroupId, zoneId로 조회한 스케줄이 없을 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidCommandException",
           className: "InvalidCommandException",
           errorProperties: [
             {
               key: "{{ reservationGroupId 혹은 zoneId }}",
               reason: "NotFound"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>해당 스케줄에 여러 예약 일정이 존재하여 V1에서 수정할 수 없는 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [
             {
               "key": "occupiedResources",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>예약 변경 정책에 의해 변경이 허용되지 않을 경우 (변경 마감 시간 초과 포함)</summary>

         ```json
         {
           status: 400,
           message: "ReservationNotAllowedByPolicy",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "modificationPolicy",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>
      operationId: updateReservation
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.UpdateReservationCommand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /schedule/open/v1/commands/update-schedule-consultation-info:
    post:
      tags:
        - Schedule
      summary: 스케줄 상담 정보 수정
      description: |-
        스케줄의 상담 정보를 수정합니다.

         - 수정할 필드만 전달합니다. 전달하지 않은 필드는 변경되지 않습니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>scheduleId에 해당하는 스케줄이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "scheduleId", "reason": "NotFound"}]
         }
         ```
         </details>
      operationId: updateScheduleConsultationInfo
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenUpdateScheduleConsultationInfoComma\
                nd"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /schedule/open/v1/queries/find-schedule-by-purchase-id:
    post:
      tags:
        - Schedule
      summary: 수납 ID로 스케줄 조회
      description: 수납 ID로 스케줄을 조회합니다.
      operationId: findScheduleByPurchaseId
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.FindScheduleByPurchaseIdQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.FindScheduleByPurchaseIdQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-reservation-groups:
    post:
      tags:
        - Schedule
      summary: 예약 그룹 목록 조회
      description: |-
        병원에 등록된 예약 그룹 목록을 조회합니다.

         - 예약 그룹은 예약 슬롯을 구성하는 단위입니다.
         - 각 예약 그룹에는 구역, 운영 시간, 정원 등의 설정이 포함됩니다.
      operationId: getReservationGroups
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.Empty"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationGroupsQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-reservation-slots-by-group:
    post:
      tags:
        - Schedule
      summary: 예약 그룹으로 예약 슬롯 조회
      description: |-
        예약 그룹을 기준으로 예약 슬롯을 조회합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>`timezone` 이 잘못되었을 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "timezone",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>

         <details>
         <summary>`reservationGroup` 이 조회되지 않았을 경우</summary>

         ```json
         {
           status: 400,
           message: "NotFoundException",
           className: "NotFoundException",
           errorProperties: [
             {
               key: "id",
               reason: "NotFound"
             },
           ],
         }
         ```

         </details>

         <details>
         <summary>`reservationGroup` 의 포맷이 잘못되었을 경우</summary>

         ```json
         {
           status: 400,
           message: "InvalidRequestException",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "id",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>
      operationId: getReservationSlotsByGroup
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetReservationSlotsByGroupQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationSlotsQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-reservation-slots-by-product:
    post:
      tags:
        - Schedule
      summary: 상품 옵션으로 예약 슬롯 조회
      description: |-
        상품 옵션 ID를 기준으로 예약 가능한 슬롯을 조회합니다.

         - 상품 옵션들이 연결된 예약 그룹 중 대표 그룹 하나가 선택되어 해당 그룹의 슬롯이 반환됩니다.
         - 대표 그룹은 가장 큰 슬롯 간격(`intervalMinutes`)을 가진 그룹 중 기본 그룹이 우선 선택됩니다.
         - 휴무일 및 예약 그룹 시작일 이전의 슬롯은 제외됩니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>`startDateUtc`가 ISO 8601 포맷이 아닌 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [
             {
               "key": "startDateUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>`endDateUtc`가 ISO 8601 포맷이 아닌 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [
             {
               "key": "endDateUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>`endDateUtc`가 `startDateUtc`보다 이전일 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [
             {
               "key": "endDateUtc",
               "reason": "InvalidTimeRange"
             }
           ]
         }
         ```
         </details>
      operationId: getReservationSlotsByProduct
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetReservationSlotsByProductQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationSlotsQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-reservation-slots-by-schedule-id:
    post:
      tags:
        - Schedule
      summary: 스케줄 ID로 예약 슬롯 조회 (deprecated)
      description: >-
        @deprecated 신규 개발 시 [V2
        API](/docs/openapi/get-reservation-slots-by-schedule-id-v-2)를 사용하세요.

         스케줄 ID를 기준으로 예약 슬롯을 조회합니다.
         - 주로 기존 스케줄의 예약 시간을 변경하는 전 단계에 사용됩니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>`startDateTimeUtc`가 [ISO 8601](https://www.wikiwand.com/ko/ISO_8601) 포맷이 아닌경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "startDateTimeUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>`endDateTimeUtc`가 [ISO 8601](https://www.wikiwand.com/ko/ISO_8601) 포맷이 아닌경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "endDateTimeUtc",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>

         <details>
         <summary>`scheduleId`가 누락되었거나 포맷이 잘못된 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [
             {
               "key": "scheduleId",
               "reason": "NotAvailable"
             }
           ]
         }
         ```
         </details>
      operationId: getReservationSlotsByScheduleId
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetReservationSlotsByScheduleIdQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationSlotsQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-schedule-detail:
    post:
      tags:
        - Schedule
      summary: 스케줄 상세 조회
      description: |-
        스케줄의 상세 정보를 조회합니다.

         - `scheduleId`로 특정 스케줄의 예약, 상담, 시술, 수납 등 전체 상세 정보를 조회합니다.
      operationId: getScheduleDetail
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.schedule.GetScheduleDetailQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.schedule.schedule.GetScheduleDetailQueryResp\
                  onse"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-schedules-by-visitor:
    post:
      tags:
        - Schedule
      summary: 내원객의 스케줄 목록 조회
      description: |-
        내원객의 스케줄 목록을 조회합니다.

         - `visitorId`로 특정 내원객의 스케줄을 조회합니다.
         - `startDateTimeUtc`, `endDateTimeUtc`로 조회 기간을 제한할 수 있습니다.
         - `deleted`를 `true`로 설정하면 삭제된 스케줄도 포함하여 조회합니다.
      operationId: getSchedulesByVisitor
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.schedule.GetSchedulesByVisitorQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.schedule.schedule.GetSchedulesByVisitorQuery\
                  Response"
      security:
        - auth_token: []
  /schedule/open/v1/queries/get-schedules-summarized-by-tasks:
    post:
      tags:
        - Schedule
      summary: 내원객의 시술 내역 조회
      description: |-
        내원객이 병원에서 받은 시술 내역을 조회합니다.

         - `visitorId`로 특정 내원객의 시술 내역을 조회합니다.
         - `paymentRequired`를 설정하면 수납 필요 여부로 필터링할 수 있습니다.
         - `deleted`를 `true`로 설정하면 삭제된 스케줄의 시술도 포함하여 조회합니다.
      operationId: getSchedulesSummarizedByTask
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.schedule.GetSchedulesSummarizedByTa\
                skQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.schedule.schedule.GetSchedulesSummarizedByTa\
                  skQueryResponse"
      security:
        - auth_token: []
  /schedule/open/v2/commands/reserve:
    post:
      tags:
        - Schedule
      summary: 새로운 예약 생성 (V2)
      description: >-
        여러 예약 일정으로 새로운 예약을 생성합니다. (신규 내원객)
         - 내원객 정보를 함께 전달하면 자동으로 내원객를 생성하거나 기존 내원객를 찾습니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>visitorName이 빈 값이거나 공백으로만 이루어져 있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "visitorName", "reason": "NotAvailable"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources가 비어있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>예약 일정의 날짜가 서로 다를 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].startDateTimeUtc", "reason": "NotAvailable"}]
         }
         ```
         </details>

         <details>
         <summary>zoneId에 해당하는 구역이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>예약 일정의 구역(zoneId)이 예약 그룹에 속하지 않을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "occupiedResources[n].zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources[n]의 예약 일정 설정이 누락된 경우</summary>

         예약 일정 설정 은 예약을 통해 병원의 어떤 자원을 점유하는지에 대한 설정입니다.
         아래 설정들은 **서로 배타적인(oneof) 관계**이며, **반드시 하나만 설정되어야 합니다.**

         - reservationGroup (예약 그룹 기반 리소스 점유 설정)

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].configuration", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>동일한 내원객에 대해 시간이 겹치는 예약이 있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "startDateTime", "reason": "NotAvailable"}]
         }
         ```
         </details>
      operationId: reserveV2
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenReserveCommandV2"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.OpenReserveCommandV2Response"
      security:
        - auth_token: []
  /schedule/open/v2/commands/reserve-by-visitor-id:
    post:
      tags:
        - Schedule
      summary: 내원객 ID 기반 새로운 예약 생성 (V2)
      description: >-
        여러 예약 일정으로 새로운 예약을 생성합니다. (기존 내원객 ID 기반)

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>visitorId에 해당하는 내원객이 존재하지 않을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "visitorId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources가 비어있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources", "reason": "Required"}]
         }
         ```
         </details>


         <details>
         <summary>예약 일정의 날짜가 서로 다를 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].startDateTimeUtc", "reason": "NotAvailable"}]
         }
         ```
         </details>

         <details>
         <summary>zoneId에 해당하는 구역이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>예약 일정의 구역(zoneId)이 예약 그룹에 속하지 않을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "occupiedResources[n].zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources[n]의 예약 일정 설정이 누락된 경우</summary>

         예약 일정 설정 은 예약을 통해 병원의 어떤 자원을 점유하는지에 대한 설정입니다.
         아래 설정들은 **서로 배타적인(oneof) 관계**이며, **반드시 하나만 설정되어야 합니다.**

         - reservationGroup (예약 그룹 기반 리소스 점유 설정)

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].configuration", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>동일한 내원객에 대해 시간이 겹치는 예약이 있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "startDateTime", "reason": "NotAvailable"}]
         }
         ```
         </details>
      operationId: reserveByVisitorIdV2
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenReserveByVisitorIdCommandV2"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.OpenReserveCommandV2Response"
      security:
        - auth_token: []
  /schedule/open/v2/commands/update-reservation:
    post:
      tags:
        - Schedule
      summary: 예약 정보 수정 (V2)
      description: >-
        기존 예약의 예약 일정을 수정합니다.
         - 여러 예약 일정을 지원합니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>scheduleId에 해당하는 스케줄이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "scheduleId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources가 비어있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>occupiedResources[n]의 예약 일정 설정이 누락된 경우</summary>

         예약 일정 설정 은 예약을 통해 병원의 어떤 자원을 점유하는지에 대한 설정입니다.
         아래 설정들은 **서로 배타적인(oneof) 관계**이며, **반드시 하나만 설정되어야 합니다.**

         - reservationGroup (예약 그룹 기반 리소스 점유 설정)

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].configuration", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>예약 일정의 날짜가 서로 다를 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "occupiedResources[n].startDateTimeUtc", "reason": "NotAvailable"}]
         }
         ```
         </details>

         <details>
         <summary>zoneId에 해당하는 구역이 없을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>예약 일정의 구역(zoneId)이 예약 그룹에 속하지 않을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "occupiedResources[n].zoneId", "reason": "NotFound"}]
         }
         ```
         </details>

         <details>
         <summary>예약 변경 정책에 의해 변경이 허용되지 않을 경우 (변경 마감 시간 초과 포함)</summary>

         ```json
         {
           status: 400,
           message: "ReservationNotAllowedByPolicy",
           className: "InvalidRequestException",
           errorProperties: [
             {
               key: "modificationPolicy",
               reason: "NotAvailable"
             },
           ],
         }
         ```
         </details>
      operationId: updateReservationV2
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.OpenUpdateReservationCommandV2"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /schedule/open/v2/queries/get-reservation-slots-by-groups:
    post:
      tags:
        - Schedule
      summary: 여러 예약 그룹으로 예약 슬롯 조회 (V2)
      description: >-
        여러 예약 그룹의 예약 슬롯을 한 번에 조회합니다.
         - 장바구니에 여러 상품이 담긴 경우, 모든 예약 그룹의 슬롯을 조회하여 교집합을 계산할 수 있습니다.

         ### [에러 응답](/docs/openapi/kos-openapi#에러-응답)

         <details>
         <summary>`reservationGroupIds`가 비어있을 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "reservationGroupIds", "reason": "Required"}]
         }
         ```
         </details>

         <details>
         <summary>시간 형식이 잘못된 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "startDateTimeUtc", "reason": "NotAvailable"}]
         }
         ```
         또는
         ```json
         {
           "status": 400,
           "message": "InvalidRequestException",
           "className": "InvalidRequestException",
           "errorProperties": [{"key": "endDateTimeUtc", "reason": "NotAvailable"}]
         }
         ```
         </details>

         <details>
         <summary>종료 시간이 시작 시간보다 이전인 경우</summary>

         ```json
         {
           "status": 400,
           "message": "InvalidCommandException",
           "className": "InvalidCommandException",
           "errorProperties": [{"key": "endDateTimeUtc", "reason": "InvalidTimeRange"}]
         }
         ```
         </details>
      operationId: getReservationSlotsByGroupsV2
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetReservationSlotsByGroupsQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationSlotsByGroupsQueryRespons\
                  e"
      security:
        - auth_token: []
  /schedule/open/v2/queries/get-reservation-slots-by-schedule-id:
    post:
      tags:
        - Schedule
        - Schedule
      summary: 스케줄 기반 예약 슬롯 조회 (V2)
      description: 특정 스케줄 ID를 기반으로 각 예약 일정별 가능한 슬롯들을 조회합니다.
      operationId: getReservationSlotsByScheduleIdV2
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetReservationSlotsByScheduleIdQueryV2"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.GetReservationSlotsByScheduleIdQueryV2R\
                  esponse"
      security:
        - auth_token: []
  /schedule/open/zone/v1/queries/get-zone:
    post:
      tags:
        - Schedule
      summary: 구역 조회
      description: |-
        특정 구역의 정보를 조회합니다.

         - `zoneId`로 구역의 이름, 활성화 여부 등 상세 정보를 조회합니다.
      operationId: getZone
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.schedule.zone.GetZoneQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.schedule.zone.GetZoneQueryResponse"
      security:
        - auth_token: []
  /schedule/open/zone/v1/queries/get-zones:
    post:
      tags:
        - Schedule
      summary: 구역 전체 조회
      description: |-
        병원에 등록된 모든 구역 목록을 조회합니다.

         - 시술실, 상담실 등 병원 내 구역 정보를 반환합니다.
      operationId: getZones
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.Empty"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.schedule.zone.GetZonesResponse"
      security:
        - auth_token: []
  /ticket/open/v1/queries/get-ticket-bundles:
    post:
      tags:
        - Ticket
      summary: 내원객의 시술권 목록 조회
      operationId: getTicketBundlesQuery
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.GetTicketBundlesQuery"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.ticket.GetTicketBundlesQueryResponse"
      security:
        - auth_token: []
  /visitor/open/v1/commands/disable-advertising-agreement-to-visitors:
    post:
      tags:
        - Visitor
      summary: 마케팅 수신 동의 해제
      description: 마케팅 수신 동의를 해제합니다.
      operationId: disableAdvertisingAgreementToVisitors
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.DisableAdvertisingAgreementToVisitorsCo\
                mmand"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.Empty"
      security:
        - auth_token: []
  /visitor/open/v1/queries/find-duplicated-visitor-id:
    post:
      tags:
        - Visitor
      summary: 이미 등록된 내원객 조회
      description: 조건에 맞는 내원객 id를 조회합니다.
      operationId: findDuplicatedVisitorId
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.FindDuplicatedVisitorId"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.FindDuplicatedVisitorIdResponse"
      security:
        - auth_token: []
  /visitor/open/v1/queries/find-visitor:
    post:
      tags:
        - Visitor
      summary: 내원객 검색 (deprecated)
      description: 조건에 맞는 내원객을 검색합니다. (deprecated)
      operationId: findVisitor
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.FindVisitor"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.FindVisitorResponse"
      security:
        - auth_token: []
  /visitor/open/v1/queries/search-visitors:
    post:
      tags:
        - Visitor
      summary: 내원객 정보 검색
      description: 조건에 맞는 내원객 정보를 검색합니다.
      operationId: searchVisitors
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/protos.open.SearchVisitors"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/protos.open.SearchVisitorsResponse"
      security:
        - auth_token: []
components:
  schemas:
    protos.DateTimeRangeUtc:
      type: object
      properties:
        startDateTimeUtc:
          type: string
          description: |-
            *
             Greater Than Equal
        endDateTimeUtc:
          type: string
          description: |-
            *
             Less Than
    protos.Empty:
      type: object
      properties: {}
    protos.Phone:
      required:
        - countryCode
        - phoneNumber
      type: object
      properties:
        countryCode:
          type: string
          description: >-
            국제전화 국가 번호
             예: 82, 81, 1, 44 ... [참고](https://ko.wikipedia.org/wiki/%EA%B5%AD%EC%A0%9C%EC%A0%84%ED%99%94_%EA%B5%AD%EA%B0%80_%EB%B2%88%ED%98%B8)
        phoneNumber:
          type: string
          description: |-
            전화번호
             예: 10123456789
    protos.Sort:
      type: object
      properties:
        by:
          type: string
        order:
          enum:
            - Order_UNKNOWN
            - ASC
            - DESC
          type: string
          format: enum
    protos.Transls:
      type: object
      properties:
        translation:
          type: object
          additionalProperties:
            type: string
    protos.account.AccountRoleV2Contract:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        roleTags:
          type: array
          items:
            enum:
              - ROLE_TAG_UNSPECIFIED
              - ADMIN
              - DOCTOR
              - COUNSELOR
              - NURSE
              - SKINCARE
              - CALL_COUNSELOR
              - COORDINATOR
            type: string
            format: enum
    protos.image.RegisterVisitorImageConfiguration:
      type: object
      properties:
        fileName:
          type: string
        visitorId:
          type: string
        source:
          enum:
            - VISITOR_IMAGE_SOURCE_UNSPECIFIED
            - HOSPITAL
            - VISITOR
            - AGREEMENT
            - PEN_CHART
          type: string
          format: enum
        equipment:
          $ref: "#/components/schemas/protos.tenant.Code"
        scheduleId:
          type: string
        shootingDateTimeUtc:
          type: string
        memo:
          type: string
        category:
          $ref: "#/components/schemas/protos.tenant.Code"
        path:
          type: string
    protos.open.DisableAdvertisingAgreementToVisitorsCommand:
      required:
        - phoneNumber
      type: object
      properties:
        phoneNumber:
          type: string
          description: 전화번호
    protos.open.ExchangeTokenCommand:
      required:
        - key
      type: object
      properties:
        key:
          type: string
          description: KOS 팀으로 부터 전달 받은 API Key
          format: uuid
    protos.open.ExchangeTokenResponse:
      type: object
      properties:
        token:
          type: string
          description: |-
            OpenAPI 사용을 위한 Auth Token

             토큰 유효 기간은 약 24시간이며, KOS 정책에 따라 변경될 수 있습니다.
             토큰이 만료된 경우 API 호출 시 `401` 응답이 반환되며,
             인증 토큰 교환 API를 다시 호출하여 토큰을 재발급 받아야 합니다.
    protos.open.FindDuplicatedVisitorId:
      type: object
      properties:
        name:
          type: string
        phone:
          $ref: "#/components/schemas/protos.Phone"
        passportNumber:
          type: string
        birthDateUtc:
          type: string
        passportSurname:
          type: string
        passportGivenNames:
          type: string
        snsInfo:
          $ref: "#/components/schemas/protos.visitor.SnsInfo"
        email:
          type: string
    protos.open.FindDuplicatedVisitorIdResponse:
      type: object
      properties:
        data:
          type: string
    protos.open.FindScheduleByPurchaseIdQuery:
      required:
        - purchaseId
      type: object
      properties:
        purchaseId:
          type: string
          description: 수납 ID
          format: object-id
      description: 수납 ID로 스케줄 조회 요청
    protos.open.FindScheduleByPurchaseIdQueryResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.schedule.schedule.ScheduleContract"
      description: 수납 ID로 스케줄 조회 응답
    protos.open.FindVisitor:
      type: object
      properties:
        visitorName:
          type: string
        phone:
          $ref: "#/components/schemas/protos.Phone"
    protos.open.FindVisitorResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.open.VisitorInformation"
    protos.open.GenerateUploadingImageUrl:
      type: object
      properties:
        fileName:
          type: string
          description: 병원별로 유니크한 파일 이름 필요
    protos.open.GenerateUploadingImageUrlResponse:
      type: object
      properties:
        data:
          type: string
    protos.open.GetPromotionsQuery:
      type: object
      properties:
        promotionCategoryId:
          type: string
          description: 프로모션 카테고리 ID
    protos.open.GetPurchaseSummariesQuery:
      required:
        - purchaseIds
      type: object
      properties:
        purchaseIds:
          type: array
          items:
            type: string
          description: 수납 ID 목록
      description: 수납 내역 조회 요청
    protos.open.GetPurchaseSummariesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseSummary"
      description: 수납 내역 조회 응답
    protos.open.GetReservationGroupsQueryResponse:
      required:
        - data
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationGroupContract"
    protos.open.GetReservationSlotsByGroupQuery:
      required:
        - reservationGroupId
        - startDate
        - endDate
        - timezone
      type: object
      properties:
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
          format: object-id
        startDate:
          type: string
          description: 조회 범위 시작 시각
          format: date-time
        endDate:
          type: string
          description: 조회 범위 끝 시각
          format: date-time
        timezone:
          type: string
          description: >-
            시간대
             ex) Asia/Seoul [참고](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#:~:text=Asia/Seoul)
    protos.open.GetReservationSlotsByGroupsQuery:
      required:
        - reservationGroupIds
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        reservationGroupIds:
          type: array
          items:
            type: string
          description: 조회할 예약 그룹 ID 목록
        startDateTimeUtc:
          type: string
          description: 조회 범위 시작 시각 (UTC ISO 8601)
          format: date-time
        endDateTimeUtc:
          type: string
          description: 조회 범위 종료 시각 (UTC ISO 8601)
          format: date-time
      description: V2 슬롯 조회 요청 - 여러 예약 그룹의 슬롯을 한 번에 조회
    protos.open.GetReservationSlotsByGroupsQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.ReservationGroupSlots"
      description: V2 슬롯 조회 응답 - 그룹별로 슬롯을 묶어서 반환
    protos.open.GetReservationSlotsByProductQuery:
      required:
        - requestedProductOptionIds
        - requestedProductOptionIdsOfPromotion
        - startDateUtc
        - endDateUtc
      type: object
      properties:
        requestedProductOptionIds:
          type: array
          items:
            type: string
          description: 조회할 상품 옵션 ID 목록. 옵션들이 연결된 예약 그룹 중 대표 그룹이 선택되어 해당 슬롯이 반환됩니다.
        requestedProductOptionIdsOfPromotion:
          type: array
          items:
            type: string
          description: "@deprecated 프로모션 시술 옵션 ID 목록. `requestedProductOptionIds`를 사용하세요."
        startDateUtc:
          type: string
          description: 조회 범위 시작 시각 (ISO 8601, e.g. `2024-01-01T00:00:00Z`)
          format: date-time
        endDateUtc:
          type: string
          description: 조회 범위 끝 시각 (ISO 8601, e.g. `2024-01-31T23:59:59Z`)
          format: date-time
    protos.open.GetReservationSlotsByScheduleIdQuery:
      required:
        - scheduleId
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케줄 ID
          format: object-id
        startDateTimeUtc:
          type: string
          description: 조회 범위 시작 시각
          format: date-time
        endDateTimeUtc:
          type: string
          description: 조회 범위 끝 시각
          format: date-time
    protos.open.GetReservationSlotsByScheduleIdQueryV2:
      required:
        - scheduleId
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케줄 ID
          format: object-id
        startDateTimeUtc:
          type: string
          description: 조회 범위 시작 시각
          format: date-time
        endDateTimeUtc:
          type: string
          description: 조회 범위 끝 시각
          format: date-time
      description: V2 스케줄 기반 슬롯 조회 요청
    protos.open.GetReservationSlotsByScheduleIdQueryV2Response:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.ReservationGroupOccupiedResourceSlot"
      description: V2 스케줄 기반 슬롯 조회 응답 - 리소스별로 슬롯을 묶어서 반환 (업데이트 시 매칭용)
    protos.open.GetReservationSlotsQueryResponse:
      required:
        - data
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.ReservationSlot"
    protos.open.GetTicketBundlesQuery:
      required:
        - visitorId
      type: object
      properties:
        visitorId:
          type: string
          description: 내원객 ID
    protos.open.OccupiedReservationGroupResource:
      required:
        - reservationGroupId
        - zoneId
      type: object
      properties:
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
          format: object-id
        zoneId:
          type: string
          description: 점유할 구역 ID
          format: object-id
        doctor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Doctor"
          description: 리소스 담당 의사
      description: 예약 그룹 점유 리소스 상세 설정
    protos.open.OccupiedResource:
      required:
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        startDateTimeUtc:
          type: string
          description: 점유 시작 시각 (UTC ISO 8601)
          format: date-time
        endDateTimeUtc:
          type: string
          description: 점유 종료 시각 (UTC ISO 8601)
          format: date-time
        reservationGroup:
          allOf:
            - $ref: "#/components/schemas/protos.open.OccupiedReservationGroupResource"
          description: 예약 그룹 기반 리소스 점유 설정
      description: |-
        V2 점유 리소스 모델 (추상적 모델)
         점유 시간 정보를 공통으로 가지며, 구체적인 리소스 구성은 configuration(oneof)을 통해 정의됩니다.
    protos.open.OpenCreateOccupiedTimeCommand:
      required:
        - startDateTimeUtc
        - endDateTimeUtc
        - zoneId
        - reservationGroupId
      type: object
      properties:
        startDateTimeUtc:
          type: string
          description: 점유 시작 시각
        endDateTimeUtc:
          type: string
          description: 점유 종료 시각
        memo:
          type: string
          description: 점유 관련 메모
        zoneId:
          type: string
          description: 점유할 구역 ID
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
    protos.open.OpenCreateOccupiedTimeCommandResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.open.OpenCreateOccupiedTimeCommandResponseDa\
            ta"
      description: 시간 점유 생성 응답
    protos.open.OpenCreateOccupiedTimeCommandResponseData:
      type: object
      properties:
        occupiedTimeId:
          type: string
          description: 생성된 시간 점유 고유 ID
    protos.open.OpenGetCategoriesQuery:
      type: object
      properties:
        sort:
          allOf:
            - $ref: "#/components/schemas/protos.Sort"
          description: 정렬 기준
        opened:
          type: boolean
          description: |-
            노출 여부
             - `null`: 전체 조회
             - `true`: 노출되는 카테고리만 조회
             - `false`: 노출되지 않는 카테고리만 조회
    protos.open.OpenGetProductQuery:
      required:
        - id
      type: object
      properties:
        id:
          type: string
          description: 상품 ID
          format: object-id
    protos.open.OpenGetProductsQuery:
      type: object
      properties:
        categoryId:
          type: string
          description: 카테고리 ID
          format: object-id
        includePromotions:
          type: boolean
          description: "@deprecated 프로모션 포함 여부"
        title:
          type: string
          description: 상품 이름 (검색 키워드)
        deleted:
          type: boolean
          description: |-
            삭제 여부
             `true` = 삭제된 상품만 조회, `false` = 삭제된 상품 제외 조회, `null` = 전체 조회
        targetCountryCode:
          type: string
          description: >-
            타겟 국가 코드
             - ISO 3166-1 alpha-2 (https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2?useskin=vector)
             - 단, '그 외 국가'는 `ETC`로 표기
        isEvent:
          type: boolean
          description: |-
            이벤트 상품 필터
             `true` = 이벤트 상품만 조회, `false` = 이벤트 상품 제외 조회, `null` = 전체 조회
        optionIds:
          type: array
          items:
            type: string
          description: 특정 상품 옵션 ID 목록으로 필터링
    protos.open.OpenReserveByVisitorIdCommandV2:
      required:
        - visitorId
        - zoneId
        - occupiedResources
      type: object
      properties:
        visitorId:
          type: string
          description: 내원객 ID
          format: object-id
        zoneId:
          type: string
          description: 접수 구역 ID (내원객이 방문할 구역)
          format: object-id
        occupiedResources:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.OccupiedResource"
          description: 예약 일정 목록
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 수면 마취 필요 여부
        funnelDetail:
          type: string
          description: 상세 유입 경로
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 희망 시술 목록
        reservationMemo:
          type: string
          description: 예약 메모
      description: V2 예약 생성 (기존 내원객 ID 기반)
    protos.open.OpenReserveCommandV2:
      required:
        - visitorName
        - visitorPhone
        - zoneId
        - occupiedResources
      type: object
      properties:
        visitorName:
          type: string
          description: 내원객 이름
        visitorPhone:
          allOf:
            - $ref: "#/components/schemas/protos.Phone"
          description: 내원객 전화번호
        visitorEmail:
          type: string
          description: 내원객 이메일
          format: email
        visitorNationality:
          type: string
          description: 내원객 국적 (ISO 3166-1 alpha-2)
        visitorLanguage:
          type: string
          description: >-
            내원객 언어
             지원 목록: ko, ja, en, zh-CN, zh-yue, es, th, ru, id, ms, vi, mn, uz, nl, de, pt, etc
        visitorBirthDayUtc:
          type: string
          description: 내원객 생년월일
          format: date-time
        visitorSnsInfo:
          allOf:
            - $ref: "#/components/schemas/protos.visitor.SnsInfo"
          description: 내원객 SNS 정보
        visitorPassportNumber:
          type: string
          description: 내원객 여권번호
        visitorPassportSurname:
          type: string
          description: 내원객 여권 영문 성
        visitorPassportGivenNames:
          type: string
          description: 내원객 여권 영문 이름
        zoneId:
          type: string
          description: 접수 구역 ID (내원객이 방문할 구역)
          format: object-id
        occupiedResources:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.OccupiedResource"
          description: 예약 일정 목록
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 수면 마취 필요 여부
        funnelDetail:
          type: string
          description: 상세 유입 경로
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 희망 시술 목록
        reservationMemo:
          type: string
          description: 예약 메모
        visitorConnectedInformation:
          allOf:
            - $ref: "#/components/schemas/protos.open.VisitorConnectedInformation"
          description: 내원객 연동 정보
      description: |-
        여러 예약 일정으로 새로운 예약을 생성합니다. (신규 내원객 정보 기반)

         ### 내원객 중복 검색 정책

         요청에 포함된 내원객 정보로 기존 내원객을 검색하여, 일치하는 내원객이 있으면 해당 내원객으로 예약을 생성합니다.
         일치하는 내원객이 없으면 새로운 내원객을 생성한 후 예약을 생성합니다.

         중복 검색은 다음 조건들을 **우선순위 순서대로** 확인하며, 먼저 일치하는 조건이 있으면 해당 내원객을 사용합니다:

         | 우선순위 | 검색 조건 |
         |---------|----------|
         | 1 | `visitorName` + `visitorPhone` |
         | 2 | `visitorPassportNumber` |
         | 3 | `visitorSnsInfo` |
         | 4 | `visitorEmail` |
         | 5 | `visitorName` + `visitorBirthDayUtc` |

         > **참고**: 각 조건은 독립적으로 검색되며, 모든 필드가 AND로 결합되지 않습니다.
    protos.open.OpenReserveCommandV2Response:
      required:
        - scheduleId
      type: object
      properties:
        scheduleId:
          type: string
          description: 생성된 스케줄 ID
          format: uuid
      description: V2 예약 생성 응답
    protos.open.OpenUpdateReservationCommandV2:
      required:
        - scheduleId
        - zoneId
        - occupiedResources
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케줄 (예약 및 내원 정보) ID
          format: object-id
        zoneId:
          type: string
          description: 접수 구역 ID
          format: object-id
        occupiedResources:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.OccupiedResource"
          description: 변경할 예약 일정 목록
        reservationAssignee:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationAssignee"
          description: 예약 담당자
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 마취 필요 여부
        counselor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Counselor"
          description: 희망 상담사
        funnel:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationFunnel"
          description: 예약 경로
        reservationMemo:
          type: string
          description: 예약 메모
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 요청 시술/티켓/옵션
        connectedChannel:
          enum:
            - Channel_UNSPEICIFED
            - GANGNAMUNNI
            - HOMEPAGE
            - KOS_CONNECT
          type: string
          description: 유입 채널
          format: enum
      description: V2 예약 수정
    protos.open.OpenUpdateScheduleConsultationInfoCommand:
      required:
        - scheduleId
      type: object
      properties:
        scheduleId:
          type: string
          description: 수정할 스케줄 ID
          format: uuid
        consultationMemo:
          type: string
          description: 상담 메모. 빈 문자열(`""`)로 전달하면 메모가 삭제됩니다.
      description: 상담 정보 수정 요청. 수정할 필드만 전달하면 됩니다. 전달하지 않은 필드는 변경되지 않습니다.
    protos.open.RegisterVisitorImages:
      type: object
      properties:
        images:
          type: array
          items:
            $ref: "#/components/schemas/protos.image.RegisterVisitorImageConfiguration"
    protos.open.ReservationGroupOccupiedResourceSlot:
      type: object
      properties:
        occupiedResourceId:
          type: string
          description: 점유 리소스 ID (스케줄 내 고유 ID)
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
        zoneId:
          type: string
          description: 구역 ID
        slots:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.ReservationSlot"
          description: 해당 리소스의 가용 슬롯 목록
      description: 예약 그룹 점유 리소스별 슬롯 목록
    protos.open.ReservationGroupSlots:
      type: object
      properties:
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
        zoneId:
          type: string
          description: 구역 ID
        slots:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.ReservationSlot"
          description: 해당 그룹의 슬롯 목록
      description: 예약 그룹별 슬롯 목록
    protos.open.ReservationSlot:
      required:
        - reservationGroupId
        - zone
        - startDateTimeUtc
        - endDateTimeUtc
        - capacity
        - reservationCount
      type: object
      properties:
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
        zone:
          allOf:
            - $ref: "#/components/schemas/protos.open.ReservationSlotZoneConfiguration"
          description: 구역 정보
        startDateTimeUtc:
          type: string
          description: 예약 시작 시각 (ISO 8601)
          format: date-time
        endDateTimeUtc:
          type: string
          description: 예약 종료 시각 (ISO 8601)
          format: date-time
        capacity:
          type: integer
          description: 해당 슬롯의 최대 예약 가능 인원
          format: int32
        reservationCount:
          type: integer
          description: 현재 예약된 인원 수
          format: int32
    protos.open.ReservationSlotZoneConfiguration:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 구역 ID
          format: object-id
        name:
          type: string
          description: 구역 이름
    protos.open.ReserveByVisitorIdCommand:
      required:
        - visitorId
        - reservationGroupId
        - zoneId
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        visitorId:
          type: string
          description: 내원객 ID
          format: object-id
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
          format: object-id
        zoneId:
          type: string
          description: 예약 영역 ID
          format: object-id
        startDateTimeUtc:
          type: string
          description: 예약 시작 시각
          format: date-time
        endDateTimeUtc:
          type: string
          description: 예약 종료 시각
          format: date-time
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 수면 마취 필요 여부
        funnelDetail:
          type: string
          description: 상세 유입 경로
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 희망 시술 목록
        reservationMemo:
          type: string
          description: 예약 메모
    protos.open.ReserveCommand:
      required:
        - visitorName
        - visitorPhone
        - reservationGroupId
        - zoneId
        - startDateTimeUtc
        - endDateTimeUtc
      type: object
      properties:
        visitorName:
          type: string
          description: 내원객 이름
        visitorPhone:
          allOf:
            - $ref: "#/components/schemas/protos.Phone"
          description: 내원객 전화번호
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
          format: object-id
        zoneId:
          type: string
          description: 예약 영역 ID
          format: object-id
        startDateTimeUtc:
          type: string
          description: 예약 시작 시각
          format: date-time
        endDateTimeUtc:
          type: string
          description: 예약 종료 시각
          format: date-time
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 수면 마취 필요 여부
        funnelDetail:
          type: string
          description: 상세 유입 경로
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 희망 시술 목록
        reservationMemo:
          type: string
          description: 예약 메모
        visitorNationality:
          type: string
          description: >-
            내원객 국적
             예: KR, JP, CN, US ... [참고](https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2?useskin=vector)
        visitorLanguage:
          type: string
          description: >-
            내원객 언어
             지원 목록: ko, ja, en, zh-CN, zh-yue, es, th, ru, id, ms, vi, mn, uz, nl, de, pt, etc
        visitorEmail:
          type: string
          description: 내원객 이메일
          format: email
        visitorBirthDayUtc:
          type: string
          description: 내원객 생년월일
          format: date-time
        visitorSnsInfo:
          allOf:
            - $ref: "#/components/schemas/protos.visitor.SnsInfo"
          description: 내원객 SNS 정보
        visitorPassportSurname:
          type: string
          description: 내원객 여권 영문명
        visitorPassportGivenNames:
          type: string
          description: 내원객 여권 영문명
        visitorPassportNumber:
          type: string
          description: 내원객 여권 번호
        visitorConnectedInformation:
          allOf:
            - $ref: "#/components/schemas/protos.open.VisitorConnectedInformation"
          description: 내원객 연동 정보
      description: |-
        새로운 예약을 생성합니다.

         ### 내원객 중복 검색 정책

         요청에 포함된 내원객 정보로 기존 내원객을 검색하여, 일치하는 내원객이 있으면 해당 내원객으로 예약을 생성합니다.
         일치하는 내원객이 없으면 새로운 내원객을 생성한 후 예약을 생성합니다.

         중복 검색은 다음 조건들을 **우선순위 순서대로** 확인하며, 먼저 일치하는 조건이 있으면 해당 내원객을 사용합니다:

         | 우선순위 | 검색 조건 |
         |---------|----------|
         | 1 | `visitorName` + `visitorPhone` |
         | 2 | `visitorPassportNumber` |
         | 3 | `visitorSnsInfo` |
         | 4 | `visitorEmail` |
         | 5 | `visitorName` + `visitorBirthDayUtc` |

         > **참고**: 각 조건은 독립적으로 검색되며, 모든 필드가 AND로 결합되지 않습니다.
    protos.open.ReserveCommandResponse:
      required:
        - reservationId
      type: object
      properties:
        reservationId:
          type: string
          description: 예약 ID
          format: uuid
    protos.open.SearchProductOptionSummariesQuery:
      required:
        - searchText
      type: object
      properties:
        searchText:
          type: string
          description: 검색 키워드
        targetCountryCode:
          type: string
          description: >-
            타겟 국가 코드
             - ISO 3166-1 alpha-2 (https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2?useskin=vector)
             - 단, '그 외 국가'는 `ETC`로 표기
    protos.open.SearchVisitors:
      type: object
      properties:
        offset:
          type: integer
          format: int32
        limit:
          type: integer
          format: int32
        partOfVisitorName:
          type: string
        dateOfBirth:
          type: string
          description: "`yyyy-MM-dd 00:00:00.000'Z'` 형태의 ISO 8601 포맷을 전달해야 함"
        chartNumber:
          type: string
        email:
          type: string
        phone:
          allOf:
            - $ref: "#/components/schemas/protos.Phone"
          description: |-
            ex)
             { "countryCode": "82", "phoneNumber": "1000000000" }
    protos.open.SearchVisitorsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.open.VisitorInformation"
    protos.open.VisitorConnectedInformation:
      type: object
      properties:
        line:
          allOf:
            - $ref: "#/components/schemas/protos.open.VisitorConnectedInformation_Line"
          description: Line 연동 정보
        unni:
          allOf:
            - $ref: "#/components/schemas/protos.open.VisitorConnectedInformation_Unni"
          description: 강남언니 연동 정보
      description: 내원객 연동 정보
    protos.open.VisitorConnectedInformation_Line:
      type: object
      properties:
        id:
          type: string
        channelId:
          type: string
        liffId:
          type: string
        displayName:
          type: string
    protos.open.VisitorConnectedInformation_Unni:
      type: object
      properties:
        id:
          type: string
        nickname:
          type: string
    protos.open.VisitorInformation:
      type: object
      properties:
        id:
          type: string
        chartNumber:
          type: string
        name:
          type: string
        phoneNumber:
          $ref: "#/components/schemas/protos.Phone"
        dateOfBirth:
          type: string
        gender:
          enum:
            - GENDER_UNSPECIFIED
            - MALE
            - FEMALE
          type: string
          format: enum
        nationality:
          type: string
        additionalPhoneNumber:
          $ref: "#/components/schemas/protos.Phone"
        passportSurname:
          type: string
        passportGivenNames:
          type: string
    protos.procedure.Category:
      required:
        - id
        - name
        - order
        - deleted
        - opened
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 카테고리 ID
        name:
          type: string
          description: 카테고리 이름
        order:
          type: integer
          description: 정렬 순서
          format: int32
        deleted:
          type: boolean
          description: 삭제 여부
        opened:
          type: boolean
          description: 노출 여부
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: 다국어 번역 정보
    protos.procedure.CommonProcedureConfiguration:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.procedure.GetCategoriesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.Category"
    protos.procedure.GetOpenProductsQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.OpenProductDetailContract"
    protos.procedure.GetProductOptionsQuery:
      required:
        - refOptionIds
        - optionIds
        - includePromotions
      type: object
      properties:
        refOptionIds:
          type: array
          items:
            type: string
          description: 참조 옵션 ID 목록
        optionIds:
          type: array
          items:
            type: string
          description: 상품 옵션 ID 목록
        includePromotions:
          type: boolean
          description: "@deprecated 프로모션 포함 여부"
    protos.procedure.GetProductOptionsQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductOptionDetail"
    protos.procedure.GetPromotionCategoriesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionCategoryContract"
    protos.procedure.GetPromotionQuery:
      type: object
      properties:
        id:
          type: string
        targetCountryCode:
          type: string
          description: >-
            # 국가 코드
             - ISO 3166-1 alpha-2 (https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2?useskin=vector)
             - 단, '그 외 국가'는 `ETC`로 표기
    protos.procedure.GetPromotionQueryResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.procedure.PromotionContract"
    protos.procedure.GetPromotionSummariesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionSummaryContract"
    protos.procedure.GetTargetCountriesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.TargetCountryContract"
    protos.procedure.MedicineAndMachine:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 기기/약물 ID
        name:
          type: string
          description: 기기/약물 이름
    protos.procedure.OpenProductDetailContract:
      required:
        - id
        - categories
        - options
        - title
        - description
        - deleted
        - closed
        - cautions
        - medicineAndMachines
        - badges
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 상품 ID
        categories:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductCategory"
          description: 카테고리 목록
        options:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.OpenProductOptionDetail"
          description: 상품 옵션 목록
        title:
          type: string
          description: 상품 이름
        description:
          type: string
          description: 상품 설명
        deleted:
          type: boolean
          description: 삭제 여부
        closed:
          type: boolean
          description: |-
            상품 사용 여부
             - false: 사용
             - true: 사용 안함
        cautions:
          type: array
          items:
            type: string
          description: "@deprecated Use `caution` instead"
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        order:
          type: integer
          description: 정렬 순서
          format: int32
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
        caution:
          type: string
          description: 주의사항
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
             - description
             - caution
             - coverImageUrl
             - contentImageUrl
        coverImageUrl:
          type: string
          description: 커버 이미지 URL
        startDateTimeUtc:
          type: string
          description: |-
            *
             상품 판매 시작일시 (UTC ISO 8601)

             @deprecated `offeringPeriod` 또는 `displayPeriod`를 사용해주세요.

             기존 "판매 기간" 개념은 다음 두 기간으로 분리되었습니다.
             - `offeringPeriod`: 상품 예약/수납 가능 기간
             - `displayPeriod`: 상품 노출 기간

             하위 호환성을 위해 이 필드는 유지되며,
             `offeringPeriod`의 시작일시에 해당하는 값이 전달됩니다.
        endDateTimeUtc:
          type: string
          description: |-
            *
             상품 판매 종료일 (UTC ISO 8601)

             @deprecated `offeringPeriod` 또는 `displayPeriod`를 사용해주세요.
             기존 "판매 기간" 개념은 다음 두 기간으로 분리되었습니다.
             - `offeringPeriod`: 상품 예약/수납 가능 기간
             - `displayPeriod`: 상품 노출 기간

             하위 호환성을 위해 이 필드는 유지되며,
             `offeringPeriod`의 종료일시에 해당하는 값이 전달됩니다.
        isEvent:
          type: boolean
          description: 이벤트 상품 여부
        contentImageUrl:
          type: string
          description: 콘텐츠 이미지 URL
        offeringPeriod:
          allOf:
            - $ref: "#/components/schemas/protos.DateTimeRangeUtc"
          description: 상품 예약/수납 가능 기간. 미설정 시 상시 제공.
        displayPeriod:
          allOf:
            - $ref: "#/components/schemas/protos.DateTimeRangeUtc"
          description: 상품 노출기간. 미설정 시 상시 노출.
    protos.procedure.OpenProductGroupOptionComposition:
      required:
        - refSingleOptionId
        - price
        - title
        - unit
        - count
        - procedure
        - medicineAndMachines
      type: object
      properties:
        refSingleOptionId:
          type: string
          description: 참조 단일 옵션 ID
        price:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.OpenProductOptionPrice"
          description: 가격 정보
        title:
          type: string
          description: 구성 이름
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        count:
          type: integer
          description: 시술 횟수
          format: int32
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: 시술 정보
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
    protos.procedure.OpenProductOptionDetail:
      required:
        - id
        - title
        - description
        - type
        - compositions
        - deleted
        - badges
        - displayChannels
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 옵션 ID
        title:
          type: string
          description: 옵션 이름
        description:
          type: string
          description: 옵션 설명
        type:
          enum:
            - ProductOptionType_UNKNOWN
            - SINGLE
            - GROUP
            - CONSULTATION
          type: string
          description: 옵션 유형 (SINGLE, GROUP, CONSULTATION)
          format: enum
        price:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.OpenProductOptionPrice"
          description: 가격 정보
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        count:
          type: integer
          description: 시술 횟수
          format: int32
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: 시술 정보
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        compositions:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.OpenProductGroupOptionComposition"
          description: 그룹 옵션 구성 목록
        deleted:
          type: boolean
          description: 삭제 여부
        promotionConfigurations:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionConfiguration"
          description: "@deprecated 프로모션 설정 목록"
        frequentlyUsedOption:
          type: boolean
          description: 자주 찾는 시술 여부
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
        displayChannels:
          type: array
          items:
            enum:
              - DisplayChannel_UNKNOWN
              - HOMEPAGE
              - GANGNAMUNNI
              - KOS_CONNECT
            type: string
            format: enum
          description: 노출 채널 목록
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
             - description
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
    protos.procedure.OpenProductOptionPrice:
      required:
        - amount
        - additional
      type: object
      properties:
        amount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 정가
        additional:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductOptionSpecialPrice"
          description: 특별 가격 목록 (고객 유형별)
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        taxation:
          enum:
            - Taxation_UNKNOWN
            - TAXABLE
            - TAX_FREE
            - MIXED
          type: string
          description: 과세 여부
          format: enum
    protos.procedure.OpenSearchProductOptionSummariesContract:
      required:
        - id
        - title
        - type
        - productId
        - productTitle
        - compositions
        - medicineAndMachines
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 옵션 ID
        title:
          type: string
          description: 옵션 이름
        type:
          enum:
            - ProductOptionType_UNKNOWN
            - SINGLE
            - GROUP
            - CONSULTATION
          type: string
          description: 옵션 유형 (SINGLE, GROUP, CONSULTATION)
          format: enum
        price:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.ProductOptionPrice"
          description: 가격 정보
        productId:
          type: string
          description: |-
            상품 ID
             @deprecated Use `productConfiguration.id` instead
        productTitle:
          type: string
          description: |-
            상품 이름
             @deprecated Use `productConfiguration.title` instead
        compositions:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductGroupOptionComposition"
          description: (그룹 옵션인 경우) 그룹 옵션의 시술 구성
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        count:
          type: integer
          description: 시술 횟수
          format: int32
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: 시술 정보
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        description:
          type: string
          description: 옵션 설명
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
             - productTitle
             - description
        productIsEvent:
          type: boolean
          description: |-
            이벤트 상품 여부
             @deprecated Use `productConfiguration.isEvent` instead
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
        productConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.OpenSearchProductOptionSummariesCo\
                ntract_ProductConfiguration"
          description: 상품 구성 정보
    protos.procedure.OpenSearchProductOptionSummariesContract_ProductConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        isEvent:
          type: boolean
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
        offeringPeriod:
          allOf:
            - $ref: "#/components/schemas/protos.DateTimeRangeUtc"
          description: 상품 예약/수납 가능 기간. 미설정 시 상시 제공.
        displayPeriod:
          allOf:
            - $ref: "#/components/schemas/protos.DateTimeRangeUtc"
          description: 상품 노출기간. 미설정 시 상시 노출.
    protos.procedure.OpenSearchProductOptionSummariesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.OpenSearchProductOptionSummariesCo\
              ntract"
    protos.procedure.Price:
      type: object
      properties:
        amount:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        taxation:
          enum:
            - Taxation_UNKNOWN
            - TAXABLE
            - TAX_FREE
            - MIXED
          type: string
          description: 과세 여부
          format: enum
    protos.procedure.PriceAmount:
      type: object
      properties:
        value:
          type: integer
          format: int32
        currency:
          type: string
    protos.procedure.Procedure:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        commonProcedureConfiguration:
          $ref: "#/components/schemas/protos.procedure.CommonProcedureConfiguration"
        deleted:
          type: boolean
        createDate:
          type: string
        searchPhoneticName:
          type: string
          description: 클라이언트 및 백엔드 내부에서 검색을 위해 존재하는 필드
    protos.procedure.ProductCategory:
      required:
        - id
        - name
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 카테고리 ID
        name:
          type: string
          description: 카테고리 이름
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: 다국어 번역 정보
    protos.procedure.ProductGroupOptionComposition:
      required:
        - price
        - title
        - procedure
        - medicineAndMachines
      type: object
      properties:
        refSingleOptionId:
          type: string
          description: "@deprecated - 2024. 10. 11 사용되지 않음. 언제나 빈 값이 전달됨"
        price:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.ProductOptionPrice"
          description: 가격
        title:
          type: string
          description: "@deprecated - 2024. 10. 11 사용되지 않음 언제나 빈 문자열이 전달됨"
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        count:
          type: integer
          description: 시술 횟수
          format: int32
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: 시술 정보
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
    protos.procedure.ProductOptionDetail:
      required:
        - id
        - title
        - description
        - type
        - compositions
        - deleted
        - badges
        - displayChannels
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 옵션 ID
        title:
          type: string
          description: 옵션 이름
        description:
          type: string
          description: 옵션 설명
        type:
          enum:
            - ProductOptionType_UNKNOWN
            - SINGLE
            - GROUP
            - CONSULTATION
          type: string
          description: |-
            옵션 유형
             - SINGLE: 단일 옵션
             - GROUP: 그룹 옵션
             - CONSULTATION: 상담 옵션
          format: enum
        price:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.ProductOptionPrice"
          description: 가격 정보
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: "@deprecated - 진료항목의 단위를 사용할것"
        count:
          type: integer
          description: 시술 횟수
          format: int32
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: "@deprecated - 진료항목의 시술을 사용할것"
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: "@deprecated - 진료항목의 기기 및 약물을 사용할것"
        compositions:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductGroupOptionComposition"
          description: (그룹 옵션인 경우) 그룹 옵션의 시술 구성
        deleted:
          type: boolean
          description: 삭제 여부
        promotionConfigurations:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionConfiguration"
          description: "@deprecated 프로모션 설정 목록"
        frequentlyUsedOption:
          type: boolean
          description: 자주 찾는 시술 여부
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
        displayChannels:
          type: array
          items:
            enum:
              - DisplayChannel_UNKNOWN
              - HOMEPAGE
              - GANGNAMUNNI
              - KOS_CONNECT
            type: string
            format: enum
          description: 노출 채널 목록
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
             - description
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
    protos.procedure.ProductOptionPrice:
      required:
        - amount
        - additional
      type: object
      properties:
        amount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 정가
        additional:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.ProductOptionSpecialPrice"
          description: 고객 수가 유형별 가격
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        taxation:
          enum:
            - Taxation_UNKNOWN
            - TAXABLE
            - TAX_FREE
            - MIXED
          type: string
          description: 과세 여부
          format: enum
    protos.procedure.ProductOptionPriceVisitorType:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 고객 수가 유형 ID
        name:
          type: string
          description: 고객 수가 유형 이름
    protos.procedure.ProductOptionSpecialPrice:
      required:
        - amount
        - visitorType
      type: object
      properties:
        amount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 가격
        visitorType:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.ProductOptionPriceVisitorType"
          description: 고객 수가 유형 정보
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        taxation:
          enum:
            - Taxation_UNKNOWN
            - TAXABLE
            - TAX_FREE
            - MIXED
          type: string
          description: 과세 여부
          format: enum
    protos.procedure.PromotionCategoryContract:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        order:
          type: integer
          format: int32
        deleted:
          type: boolean
    protos.procedure.PromotionConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        startDate:
          type: string
        endDate:
          type: string
        optionId:
          type: string
        discountedPrice:
          $ref: "#/components/schemas/protos.procedure.Price"
    protos.procedure.PromotionContract:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        description:
          type: string
        options:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionOptionContract"
        categoryIds:
          type: array
          items:
            type: string
        cautions:
          type: array
          items:
            type: string
        startDate:
          type: string
        endDate:
          type: string
        deleted:
          type: boolean
        closed:
          type: boolean
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
        coverImageUrl:
          type: string
        detailDescription:
          type: string
    protos.procedure.PromotionOptionContract:
      type: object
      properties:
        id:
          type: string
        productConfiguration:
          $ref: "#/components/schemas/protos.procedure.PromotionOptionProductConfiguratio\
            n"
        discountedPrice:
          $ref: "#/components/schemas/protos.procedure.Price"
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
    protos.procedure.PromotionOptionProductConfiguration:
      type: object
      properties:
        productId:
          type: string
        productTitle:
          type: string
        optionId:
          type: string
        optionTitle:
          type: string
        optionPrice:
          $ref: "#/components/schemas/protos.procedure.Price"
        optionType:
          enum:
            - ProductOptionType_UNKNOWN
            - SINGLE
            - GROUP
            - CONSULTATION
          type: string
          format: enum
    protos.procedure.PromotionSummaryContract:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        description:
          type: string
        options:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.PromotionOptionContract"
        categoryIds:
          type: array
          items:
            type: string
        startDate:
          type: string
        endDate:
          type: string
        deleted:
          type: boolean
        closed:
          type: boolean
        order:
          type: integer
          format: int32
        badges:
          type: integer
          items:
            enum:
              - Badge_UNKNOWN
              - NEW
              - POPULAR
              - RECOMMENDED
            type: string
            format: enum
          description: >-
            뱃지 목록 (int32 value 전달)

            ※ 반드시 KEY가 아닌 VALUE(int32)를 전달해야 합니다.| KEY (참고용) | VALUE (전달값) |
            DESCRIPTION |

            |---|---|---|

            | Badge_UNKNOWN | 0 | - |

            | NEW | 1 | 신규 |

            | POPULAR | 2 | 인기 |

            | RECOMMENDED | 3 | 추천 |
          format: int32
        coverImageUrl:
          type: string
    protos.procedure.TargetCountryContract:
      type: object
      properties:
        code:
          type: string
          description: >-
            # 국가 코드
             - ISO 3166-1 alpha-2 (https://ko.wikipedia.org/wiki/ISO_3166-1_alpha-2?useskin=vector)
             - 단, '그 외 국가'는 `ETC`로 표기
        order:
          type: integer
          format: int32
        suggestingVisitorTypeId:
          type: string
          description: 비어 있는 경우, 기본 수가 유형인 '정상가' 를 사용함.
    protos.procedure.Unit:
      type: object
      properties:
        type:
          enum:
            - UnitType_UNKNOWN
            - UNIT
            - CC
            - VIAL
            - PEN
            - STRING
            - SHOT
            - PAD
            - MINUTE
            - KJ
            - QUANTITY
            - DOT
            - J
            - MG
            - G
            - PULSE
            - BOTTLE
            - SYRINGE
            - PASS
            - IU
            - KHZ
            - MHZ
          type: string
          format: enum
        value:
          type: number
          format: double
    protos.procedure.medical_service.MedicalService:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
        status:
          enum:
            - MedicalServiceStatus_UNKNOWN
            - DRAFT
            - PUBLISHED
          type: string
          format: enum
        deleted:
          type: boolean
        configuration:
          $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceConf\
            iguration"
        draftedDateTimeUtc:
          type: string
        updatedDateTimeUtc:
          type: string
        priceAmount:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        description:
          type: string
        caution:
          type: string
        recommendedInterval:
          type: integer
          format: int32
        contributionConstant:
          type: integer
          format: int32
        durationTime:
          type: number
          format: double
    protos.procedure.medical_service.MedicalServiceConfiguration:
      type: object
      properties:
        code:
          type: string
        procedure:
          $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceProc\
            edure"
        machines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceMach\
              ine"
        medicines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceMedi\
              cine"
        unit:
          $ref: "#/components/schemas/protos.procedure.Unit"
        healthcareReimbursement:
          enum:
            - HealthcareReimbursement_UNKNOWN
            - REIMBURSABLE
            - NON_REIMBURSABLE
          type: string
          format: enum
        taxation:
          enum:
            - Taxation_UNKNOWN
            - TAXABLE
            - TAX_FREE
            - MIXED
          type: string
          format: enum
    protos.procedure.medical_service.MedicalServiceMachine:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        searchPhoneticName:
          type: string
          description: 백엔드 내부에서 검색을 위해 존재하는 필드
    protos.procedure.medical_service.MedicalServiceMedicine:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        searchPhoneticName:
          type: string
          description: 백엔드 내부에서 검색을 위해 존재하는 필드
    protos.procedure.medical_service.MedicalServiceProcedure:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        searchPhoneticName:
          type: string
          description: 백엔드 내부에서 검색을 위해 존재하는 필드
    protos.purchase.BusinessCashReceiptConfiguration:
      type: object
      properties:
        businessNumber:
          type: string
          description: 사업자번호(10 자리)
    protos.purchase.CardCompany:
      type: object
      properties:
        name:
          type: string
    protos.purchase.CardTransactionConfiguration:
      type: object
      properties:
        approvalNumber:
          type: string
        cardCompany:
          $ref: "#/components/schemas/protos.purchase.CardCompany"
        installmentConfiguration:
          $ref: "#/components/schemas/protos.purchase.InstallmentConfiguration"
        cardNumber:
          type: string
        acquirerName:
          type: string
    protos.purchase.CashReceiptConfiguration:
      type: object
      properties:
        type:
          enum:
            - CASH_RECEIPT_TYPE_UNKNOWN
            - PERSONAL
            - BUSINESS
            - VOLUNTARY
          type: string
          format: enum
        personalConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.PersonalCashReceiptConfiguration"
          description: "`type`이 `PERSONAL`일 경우 필수"
        businessConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.BusinessCashReceiptConfiguration"
          description: "`type`이 `BUSINESS`일 경우 필수"
    protos.purchase.CashTransactionConfiguration:
      type: object
      properties:
        incomeTaxDeductionNumber:
          type: string
          description: 현금영수증 승인번호
        cashReceiptConfiguration:
          $ref: "#/components/schemas/protos.purchase.CashReceiptConfiguration"
    protos.purchase.EasyPayProvider:
      type: object
      properties:
        name:
          type: string
    protos.purchase.EasyPayTransactionConfiguration:
      type: object
      properties:
        easyPayProvider:
          $ref: "#/components/schemas/protos.purchase.EasyPayProvider"
        installmentConfiguration:
          $ref: "#/components/schemas/protos.purchase.InstallmentConfiguration"
        incomeTaxDeductionNumber:
          type: string
        approvalNumber:
          type: string
    protos.purchase.GetPrepaidCardChargingEventsQuery:
      type: object
      properties:
        id:
          type: string
    protos.purchase.GetPrepaidCardChargingEventsQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PrepaidCardChargingEvent"
    protos.purchase.GetPrepaidCardSummariesQuery:
      type: object
      properties:
        visitorId:
          type: string
        available:
          type: boolean
    protos.purchase.GetPrepaidCardSummariesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PrepaidCardSummaryContract"
    protos.purchase.GetPurchaseSummariesQueryByVisitorId:
      type: object
      properties:
        visitorId:
          type: string
    protos.purchase.GetPurchaseSummariesQueryByVisitorIdResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseSummary"
    protos.purchase.GetVisitorPrepaidCardBalanceQuery:
      type: object
      properties:
        visitorId:
          type: string
    protos.purchase.GetVisitorPrepaidCardBalanceQueryResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.purchase.VisitorPrepaidCardBalanceContract"
    protos.purchase.InstallmentConfiguration:
      type: object
      properties:
        month:
          type: integer
          format: int32
    protos.purchase.MedicalLoanCompany:
      type: object
      properties:
        name:
          type: string
    protos.purchase.MedicalLoanTransactionConfiguration:
      type: object
      properties:
        medicalLoanCompany:
          $ref: "#/components/schemas/protos.purchase.MedicalLoanCompany"
    protos.purchase.PersonalCashReceiptConfiguration:
      type: object
      properties:
        phoneNumber:
          type: string
          description: 휴대폰번호(10 자리 또는 11 자리. - 제외)
    protos.purchase.PlatformTransactionConfiguration:
      type: object
      properties:
        platform:
          $ref: "#/components/schemas/protos.purchase.TransactionPlatform"
    protos.purchase.PrepaidCardAmount:
      type: object
      properties:
        balance:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        total:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
    protos.purchase.PrepaidCardChargingEvent:
      type: object
      properties:
        type:
          enum:
            - PrepaidCardChargingEventType_UNKNOWN
            - PAYMENT
            - PAYMENT_CANCEL
            - REFUND
            - CHARGE
            - EXPIRATION
            - SUBTRACT
          type: string
          format: enum
        createdDateTimeUtc:
          type: string
        visitor:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardVisitor"
        amount:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardChargingEventAmount"
        chargingId:
          type: string
        memo:
          type: string
    protos.purchase.PrepaidCardChargingEventAmount:
      type: object
      properties:
        type:
          enum:
            - PrepaidCardChargingEventAmountType_UNKNOWN
            - BALANCE
            - POINT
          type: string
          format: enum
        amount:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
    protos.purchase.PrepaidCardSummaryContract:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        remainingBalance:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardAmount"
        remainingPoint:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardAmount"
        expirationDateTimeUtc:
          type: string
        createdDateTimeUtc:
          type: string
        ownerId:
          type: string
        description:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            *
             # 다국어 지원대상 필드
             - title
             - description
        updatedDateTimeUtc:
          type: string
    protos.purchase.PrepaidCardTransactionConfiguration:
      type: object
      properties:
        prepaidCardId:
          type: string
        chargingId:
          type: string
        prepaidCardName:
          type: string
    protos.purchase.PrepaidCardVisitor:
      type: object
      properties:
        visitorId:
          type: string
        name:
          type: string
        chartNumber:
          type: string
        owner:
          type: boolean
    protos.purchase.PriceAdjustment:
      type: object
      properties:
        method:
          enum:
            - PriceAdjustmentMethod_UNSPECIFIED
            - FIXED_AMOUNT
            - PERCENTAGE
          type: string
          format: enum
        value:
          type: number
          format: double
    protos.purchase.PurchaseAssignee:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.purchase.PurchaseConversion:
      type: object
      properties:
        type:
          enum:
            - PURCHASE_CONVERSION_TYPE_UNSPECIFIED
            - PREPAID_CARD_CONVERSION
          type: string
          format: enum
        refConversionId:
          type: string
    protos.purchase.PurchaseItem:
      type: object
      properties:
        id:
          type: string
        optionConfiguration:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemOptionConfiguration"
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        type:
          enum:
            - PurchaseItemType_UNSPECIFIED
            - PRODUCT_OPTION
            - ETCETRA_PRODUCT
            - PREPAID_CARD_PRODUCT
          type: string
          format: enum
        adjustedPrice:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        etceteraConfiguration:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemEtceteraConfiguration"
        prepaidCardConfiguration:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemPrepaidCardConfiguratio\
            n"
        priceV2:
          $ref: "#/components/schemas/protos.procedure.Price"
        adjustPriceV2:
          $ref: "#/components/schemas/protos.procedure.Price"
        basePrice:
          $ref: "#/components/schemas/protos.procedure.Price"
        priceAdjustments:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItemPriceAdjustment"
        migratedDateTimeUtc:
          type: string
    protos.purchase.PurchaseItemEtceteraConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            다국어 지원대상 필드
             - title
    protos.purchase.PurchaseItemOptionComposition:
      type: object
      properties:
        procedure:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemProcedure"
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
        count:
          type: integer
          format: int32
        unit:
          $ref: "#/components/schemas/protos.procedure.Unit"
        price:
          $ref: "#/components/schemas/protos.procedure.ProductOptionPrice"
        medicalService:
          $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
    protos.purchase.PurchaseItemOptionConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        productTitle:
          type: string
        optionType:
          enum:
            - ProductOptionType_UNKNOWN
            - SINGLE
            - GROUP
            - CONSULTATION
          type: string
          format: enum
        compositions:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItemOptionComposition"
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
        procedure:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemProcedure"
        count:
          type: integer
          format: int32
        unit:
          $ref: "#/components/schemas/protos.procedure.Unit"
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        promotionConfiguration:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemOptionPromotionConfigur\
            ation"
        medicalService:
          $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            다국어 지원대상 필드
             - title
             - productTitle
    protos.purchase.PurchaseItemOptionPromotionConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
    protos.purchase.PurchaseItemPrepaidCardConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        balance:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        point:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        expirationDateTimeUtc:
          type: string
        prepaidCardId:
          type: string
        description:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            *
             # 다국어 지원대상 필드
             - title
             - description
        expirationDurationInDays:
          type: integer
          description: |-
            *
             선불카드 상품의 사용기간
          format: int32
    protos.purchase.PurchaseItemPriceAdjustment:
      type: object
      properties:
        id:
          type: string
        priceAdjustment:
          $ref: "#/components/schemas/protos.purchase.PriceAdjustment"
        source:
          enum:
            - PriceAdjustmentSource_UNSPECIFIED
            - DIRECT
            - DISTRIBUTED
          type: string
          format: enum
    protos.purchase.PurchaseItemProcedure:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.purchase.PurchasePriceAdjustment:
      type: object
      properties:
        id:
          type: string
        priceAdjustment:
          $ref: "#/components/schemas/protos.purchase.PriceAdjustment"
        status:
          enum:
            - PriceAdjustmentStatus_UNSPECIFIED
            - PENDING
            - DISTRIBUTED
          type: string
          format: enum
    protos.purchase.PurchaseSummary:
      type: object
      properties:
        id:
          type: string
        transactions:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseSummaryTransaction"
        items:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItem"
        status:
          enum:
            - PURCHASE_STATUS_UNSPECIFIED
            - REFUNDED
            - PARTIALLY_REFUNDED
            - ACCEPTED
            - PAID
            - INITIALIZED
          type: string
          format: enum
        lastUpdatedDateTimeUtc:
          type: string
        createdDateTimeUtc:
          type: string
        assignee:
          $ref: "#/components/schemas/protos.purchase.PurchaseAssignee"
        purchaseMemo:
          type: string
        priceAdjustments:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchasePriceAdjustment"
        pendingItems:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItem"
        revokingItems:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.RevokingPurchaseItem"
        refundingItems:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.RefundingPurchaseItem"
        process:
          enum:
            - PURCHASE_PROCESS_UNSPECIFIED
            - NOT_IN_PROCESS
            - PENDING
            - REVOKING
            - REFUNDING
            - PREPAID_CARD_ITEM_SUBSTITUTING
          type: string
          format: enum
        visitorId:
          type: string
        conversion:
          $ref: "#/components/schemas/protos.purchase.PurchaseConversion"
        migratedDateTimeUtc:
          type: string
        assignees:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseAssignee"
    protos.purchase.PurchaseSummaryTransaction:
      type: object
      properties:
        id:
          type: string
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        status:
          enum:
            - TransactionStatus_UNSPECIFIED
            - REQUESTED
            - APPROVED
            - CANCELED
            - SPENT
            - FAILED
          type: string
          format: enum
        paymentType:
          enum:
            - TransactionPaymentType_UNSPECIFIED
            - CASH
            - CARD
            - PREPAID_CARD
            - PLATFORM
            - TRANSFER
            - EASY_PAY
            - MEDICAL_LOAN
          type: string
          format: enum
        cardConfiguration:
          $ref: "#/components/schemas/protos.purchase.CardTransactionConfiguration"
        cashConfiguration:
          $ref: "#/components/schemas/protos.purchase.CashTransactionConfiguration"
        transferConfiguration:
          $ref: "#/components/schemas/protos.purchase.TransferTransactionConfiguration"
        platformConfiguration:
          $ref: "#/components/schemas/protos.purchase.PlatformTransactionConfiguration"
        prepaidCardConfiguration:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardTransactionConfiguration"
        easyPayConfiguration:
          $ref: "#/components/schemas/protos.purchase.EasyPayTransactionConfiguration"
        assignee:
          $ref: "#/components/schemas/protos.purchase.PurchaseAssignee"
        canceledRefId:
          type: string
        createdDateTimeUtc:
          type: string
          description: |-
            *
             deprecated 이전에는 생성일시와 결제일시가 동일하게 사용됐습니다.
             이후부터는 paymentDateTime.lastUpdatedDateTimeUtc을 사용하세요.
             paymentDateTime이 없을 경우 하위 호환을 위해서만 사용합니다.
        primaryData:
          $ref: "#/components/schemas/protos.purchase.TransactionPrimaryData"
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        paymentDateTime:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.TransactionPaymentDateTime"
          description: paymentDateTime.lastUpdatedDateTimeUtc가 없다면, 하위 호환을 위해
            createdDateTimeUtc를 사용하세요.
        medicalLoanConfiguration:
          $ref: "#/components/schemas/protos.purchase.MedicalLoanTransactionConfiguration"
    protos.purchase.RefundingPurchaseItem:
      type: object
      properties:
        targetItemId:
          type: string
        adjustedPrice:
          $ref: "#/components/schemas/protos.procedure.Price"
    protos.purchase.RevokingPurchaseItem:
      type: object
      properties:
        targetItemId:
          type: string
    protos.purchase.Transaction:
      type: object
      properties:
        id:
          type: string
        price:
          $ref: "#/components/schemas/protos.procedure.PriceAmount"
        status:
          enum:
            - TransactionStatus_UNSPECIFIED
            - REQUESTED
            - APPROVED
            - CANCELED
            - SPENT
            - FAILED
          type: string
          format: enum
        paymentType:
          enum:
            - TransactionPaymentType_UNSPECIFIED
            - CASH
            - CARD
            - PREPAID_CARD
            - PLATFORM
            - TRANSFER
            - EASY_PAY
            - MEDICAL_LOAN
          type: string
          format: enum
        cardConfiguration:
          $ref: "#/components/schemas/protos.purchase.CardTransactionConfiguration"
        cashConfiguration:
          $ref: "#/components/schemas/protos.purchase.CashTransactionConfiguration"
        transferConfiguration:
          $ref: "#/components/schemas/protos.purchase.TransferTransactionConfiguration"
        platformConfiguration:
          $ref: "#/components/schemas/protos.purchase.PlatformTransactionConfiguration"
        prepaidCardConfiguration:
          $ref: "#/components/schemas/protos.purchase.PrepaidCardTransactionConfiguration"
        easyPayConfiguration:
          $ref: "#/components/schemas/protos.purchase.EasyPayTransactionConfiguration"
        assigneeId:
          type: string
        canceledRefId:
          type: string
        createdDateTimeUtc:
          type: string
          description: |-
            *
             deprecated 이전에는 생성일시와 결제일시가 동일하게 사용됐습니다.
             이후부터는 paymentDateTime.lastUpdatedDateTimeUtc을 사용하세요.
             paymentDateTime이 없을 경우 하위 호환을 위해서만 사용합니다.
        primaryData:
          $ref: "#/components/schemas/protos.purchase.TransactionPrimaryData"
        suppliedAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 과세 공급가액
        taxFreeAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 면세 금액 (aka. 면세 공급가액)
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: 부가가치세
        paymentDateTime:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.TransactionPaymentDateTime"
          description: paymentDateTime.lastUpdatedDateTimeUtc가 없다면, 하위 호환을 위해
            createdDateTimeUtc를 사용하세요.
        medicalLoanConfiguration:
          $ref: "#/components/schemas/protos.purchase.MedicalLoanTransactionConfiguration"
    protos.purchase.TransactionPaymentDateTime:
      type: object
      properties:
        lastUpdatedDateTimeUtc:
          type: string
        requestedDateTimeUtc:
          type: string
        approvedDateTimeUtc:
          type: string
        canceledDateTimeUtc:
          type: string
        spentDateTimeUtc:
          type: string
        failedDateTimeUtc:
          type: string
    protos.purchase.TransactionPlatform:
      type: object
      properties:
        name:
          type: string
    protos.purchase.TransactionPrimaryData:
      type: object
      properties:
        rawData:
          type: string
          description: 결제단말기로 부터 수신한 응답의 원본. 직렬화된 JSON 데이터.
        vendor:
          enum:
            - PaymentTerminalVendor_UNSPECIFIED
            - KOVAN
            - KSNET
            - STRIPE
            - KPN
          type: string
          format: enum
        terminalTransactionId:
          type: string
        terminalId:
          type: string
        merchantId:
          type: string
        approvalNumber:
          type: string
        vatAmount:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.PriceAmount"
          description: Deprecated. Use `Transaction.vatAmount` instead.
        failureReasonMessage:
          type: string
        cardCompanyName:
          type: string
        cardNumber:
          type: string
        paymentUrl:
          type: string
        installmentConfiguration:
          $ref: "#/components/schemas/protos.purchase.InstallmentConfiguration"
        acquirerName:
          type: string
        easyPayProviderCode:
          type: string
    protos.purchase.TransferTransactionConfiguration:
      type: object
      properties:
        incomeTaxDeductionNumber:
          type: string
          description: 현금영수증 승인번호
        cashReceiptConfiguration:
          $ref: "#/components/schemas/protos.purchase.CashReceiptConfiguration"
    protos.purchase.VisitorPrepaidCardBalanceContract:
      type: object
      properties:
        remainingBalance:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.PrepaidCardAmount"
          description: 보유 선불카드의 합산 현금 잔액
        remainingPoint:
          allOf:
            - $ref: "#/components/schemas/protos.purchase.PrepaidCardAmount"
          description: 보유 선불카드의 합산 포인트 잔액
        lastBalanceChargedDateTimeUtc:
          type: string
          description: 가장 최근 현금 충전 일시 (ISO 8601 UTC). 현금 충전 이력이 없으면 미설정.
        lastPointChargedDateTimeUtc:
          type: string
          description: 가장 최근 포인트 충전 일시 (ISO 8601 UTC). 포인트 충전 이력이 없으면 미설정.
    protos.schedule.BreaktimeContract:
      type: object
      properties:
        startTime:
          type: string
        endTime:
          type: string
    protos.schedule.CancelReservationCommand:
      required:
        - scheduleId
        - reason
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케줄 ID
        reason:
          enum:
            - CANCEL_RESERVATION_REASON_UNSPECIFIED
            - CANCELED
            - NO_SHOW
          type: string
          description: 취소 사유
          format: enum
    protos.schedule.Counselor:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 계정 ID
          format: object-id
        name:
          type: string
          description: 계정 이름
    protos.schedule.Doctor:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 계정 ID
          format: object-id
        name:
          type: string
          description: 계정 이름
    protos.schedule.IntervalCapacityContract:
      type: object
      properties:
        enabled:
          type: boolean
        intervalCapacity:
          type: integer
          format: int32
        zoneId:
          type: string
    protos.schedule.OccupiedResource:
      type: object
      properties:
        id:
          type: string
        type:
          enum:
            - OccupiedResourceType_UNSPECIFIED
            - RESERVATION_GROUP
          type: string
          format: enum
        reservationTime:
          $ref: "#/components/schemas/protos.DateTimeRangeUtc"
        reservationGroup:
          $ref: "#/components/schemas/protos.schedule.ReservationGroupResource"
    protos.schedule.OperationTimeContract:
      type: object
      properties:
        enabled:
          type: boolean
        startTime:
          type: string
        endTime:
          type: string
        breaktime:
          $ref: "#/components/schemas/protos.schedule.BreaktimeContract"
    protos.schedule.OperationTimetableContract:
      type: object
      properties:
        monday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        tuesday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        wednesday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        thursday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        friday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        saturday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
        sunday:
          $ref: "#/components/schemas/protos.schedule.OperationTimeContract"
    protos.schedule.ReservationAssignee:
      required:
        - id
        - name
      type: object
      properties:
        id:
          type: string
          description: 담당자 ID
        name:
          type: string
          description: 담당자 이름
    protos.schedule.ReservationFunnel:
      type: object
      properties:
        funnel:
          $ref: "#/components/schemas/protos.tenant.Code"
        funnelDetail:
          type: string
        funnelCategory:
          $ref: "#/components/schemas/protos.tenant.Code"
    protos.schedule.ReservationGroupContract:
      required:
        - id
        - title
        - memo
        - startDate
        - intervalMinutes
        - intervalCapacities
        - isDefault
        - operationTimetable
        - order
      type: object
      properties:
        id:
          type: string
          description: 예약 그룹 ID
        title:
          type: string
          description: 예약 그룹 이름
        memo:
          type: string
          description: 메모
        startDate:
          type: string
          description: 예약 시작 가능 날짜
        intervalMinutes:
          type: integer
          description: 예약 단위 시간 (분)
          format: int32
        intervalCapacities:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.IntervalCapacityContract"
          description: 구역별 단위 시간당 예약수 설정
        isDefault:
          type: boolean
          description: 기본 예약 그룹 여부
        sameDayCloseBufferMinutes:
          type: integer
          format: int32
        operationTimetable:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.OperationTimetableContract"
          description: 운영 시간
        order:
          type: integer
          description: 정렬 순서
          format: int32
        reservationPolicy:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy"
          description: |-
            *
             예약 정책
             정책에 대한 세부 필드값이 없는 경우 병원 기본 운영의 정책을 사용합니다.
    protos.schedule.ReservationGroupResource:
      type: object
      properties:
        reservationGroupId:
          type: string
        zoneId:
          type: string
        doctors:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.Doctor"
    protos.schedule.ReservationPolicy:
      type: object
      properties:
        reservation:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy_ReservationRule"
          description: |-
            *
             예약 생성 규칙
        reschedule:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy_ClosingRule"
          description: |-
            *
             예약 변경 가능 마감 규칙
        cancel:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy_ClosingRule"
          description: |-
            *
             예약 취소 가능 마감 규칙
      description: |-
        *
         예약 정책
    protos.schedule.ReservationPolicy_ClosingRule:
      required:
        - allowed
        - configuration
      type: object
      properties:
        allowed:
          type: boolean
          description: |-
            *
             허용 여부
        minimumAdvance:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy_MinimumAdvanceCon\
                figuration"
          description: |-
            *
             최소 마감 설정
      description: |-
        *
         마감 규칙
    protos.schedule.ReservationPolicy_MinimumAdvanceConfiguration:
      type: object
      properties:
        minReservationStartDateTimeLeadMinutes:
          type: integer
          description: |-
            *
             예약 시작 시간 기준 마감 최소 시간 (분)
          format: int32
        minReservationStartDateLeadDays:
          type: integer
          description: |-
            *
             예약 일 기준 마감 최소 일 (일)
          format: int32
      description: |-
        *
         최소 마감 설정
    protos.schedule.ReservationPolicy_ReservationRule:
      type: object
      properties:
        maxAdvanceDays:
          type: integer
          description: |-
            *
             현재 날짜 기준 선택가능한 최대 예약 일
          format: int32
        minimumAdvance:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationPolicy_MinimumAdvanceCon\
                figuration"
          description: |-
            *
             예약 최소 마감 설정
      description: 예약 규칙
    protos.schedule.ReservationRequestedOptionConfiguration:
      required:
        - optionId
        - optionTitle
        - price
      type: object
      properties:
        optionId:
          type: string
          description: 상품 옵션 ID
        optionTitle:
          type: string
          description: 상품 옵션 이름
        productTitle:
          type: string
          description: 상품 이름
        promotionTitle:
          type: string
          description: 프로모션 이름
        price:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationRequestedOptionPrice"
          description: 가격 정보
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - optionTitle
             - productTitle
    protos.schedule.ReservationRequestedOptionPrice:
      type: object
      properties:
        amount:
          type: integer
          format: int32
        currency:
          type: string
        reason:
          $ref: "#/components/schemas/protos.schedule.ReservationRequestedOptionPriceReas\
            on"
    protos.schedule.ReservationRequestedOptionPriceReason:
      type: object
      properties:
        type:
          enum:
            - RESERVATION_REQUESTED_OPTION_PRICE_REASON_TYPE_UNSPECIFIED
            - GENERAL
            - PROMOTION
            - VISITOR_TYPE
          type: string
          format: enum
        promotionId:
          type: string
        visitorTypeId:
          type: string
    protos.schedule.ReservationRequestedProcedure:
      required:
        - type
      type: object
      properties:
        type:
          enum:
            - RESERVATION_REQUESTED_PROCEDURE_TYPE_UNSPECIFIED
            - OPTION
            - TICKET
          type: string
          description: "요청 시술 유형 (OPTION: 상품 옵션, TICKET: 시술권)"
          format: enum
        optionConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationRequestedOptionConfigura\
                tion"
          description: 상품 옵션 설정 (type이 OPTION인 경우)
        ticketConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationRequestedTicketConfigura\
                tion"
          description: 시술권 설정 (type이 TICKET인 경우)
    protos.schedule.ReservationRequestedTicketConfiguration:
      required:
        - ticketId
        - ticketTitle
        - optionTitle
      type: object
      properties:
        ticketId:
          type: string
          description: 시술권 ID
        ticketTitle:
          type: string
          description: 시술권 이름
        optionTitle:
          type: string
          description: 옵션 이름
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
        productTitle:
          type: string
          description: 상품 이름
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - ticketTitle
             - optionTitle
             - productTitle
    protos.schedule.RoomContract:
      type: object
      properties:
        id:
          type: string
        zoneId:
          type: string
        title:
          type: string
        order:
          type: integer
          format: int32
    protos.schedule.UpdateReservationCommand:
      required:
        - scheduleId
        - reservationGroupId
        - startDateTime
        - endDateTime
        - consultationRequired
        - sedationRequired
        - zoneId
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케쥴 (예약 및 내원 정보) ID
          format: object-id
        reservationGroupId:
          type: string
          description: 예약 그룹 ID
          format: object-id
        startDateTime:
          type: string
          description: 예약 시작 시간
          format: date-time
        endDateTime:
          type: string
          description: 예약 종료 시간
          format: date-time
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 마취 필요 여부
        counselor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Counselor"
          description: 희망 상담사
        doctor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Doctor"
          description: 희망 의사
        funnel:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationFunnel"
          description: 예약 경로
        reservationMemo:
          type: string
          description: 예약 메모
        zoneId:
          type: string
          description: 구역 ID
          format: object-id
        reservationAssignee:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationAssignee"
          description: 예약 담당자
    protos.schedule.VisitorLocation:
      type: object
      properties:
        zoneId:
          type: string
    protos.schedule.consultation.ConsultationContent:
      type: object
      properties:
        text:
          type: string
    protos.schedule.consultation.ConsultationContract:
      type: object
      properties:
        id:
          type: string
        visitor:
          $ref: "#/components/schemas/protos.schedule.consultation.ConsultationVisitor"
        scheduleId:
          type: string
        consultationStartedDateTimeUtc:
          type: string
        counselors:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.Counselor"
        consultationDoctors:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.Doctor"
        consultationProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.consultation.ConsultationProcedure"
        content:
          $ref: "#/components/schemas/protos.schedule.consultation.ConsultationContent"
        result:
          $ref: "#/components/schemas/protos.tenant.Code"
        createdDateTimeUtc:
          type: string
        updatedDateTimeUtc:
          type: string
    protos.schedule.consultation.ConsultationOptionConfiguration:
      type: object
      properties:
        purchaseItemOptionConfiguration:
          $ref: "#/components/schemas/protos.purchase.PurchaseItemOptionConfiguration"
        price:
          $ref: "#/components/schemas/protos.procedure.Price"
        basePrice:
          $ref: "#/components/schemas/protos.procedure.Price"
        priceAdjustments:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItemPriceAdjustment"
    protos.schedule.consultation.ConsultationProcedure:
      type: object
      properties:
        type:
          enum:
            - CONSULTATION_PROCEDURE_TYPE_UNSPECIFIED
            - OPTION
            - TICKET
          type: string
          format: enum
        optionConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.consultation.ConsultationOptionConf\
                iguration"
          description: 상품 옵션 설정 (type이 OPTION인 경우)
        ticketConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.consultation.ConsultationTicketConf\
                iguration"
          description: 시술권 설정 (type이 TICKET인 경우)
    protos.schedule.consultation.ConsultationTicketConfiguration:
      type: object
      properties:
        ticketId:
          type: string
          description: 시술권 ID
        ticketTitle:
          type: string
          description: 시술권 이름
        optionTitle:
          type: string
          description: 옵션 이름
        medicalService:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
          description: 진료 항목
        productTitle:
          type: string
          description: 상품 이름
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - ticketTitle
             - optionTitle
             - productTitle
    protos.schedule.consultation.ConsultationVisitor:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        isFirstVisit:
          type: boolean
    protos.schedule.flow.FlowTask:
      required:
        - type
        - sequence
        - title
        - status
        - paymentRequired
        - assignees
        - doctors
        - calledDoctors
        - anesthesiaType
      type: object
      properties:
        type:
          enum:
            - FLOW_TASK_TYPE_UNSPECIFIED
            - PROCEDURE
            - ETCETERA
          type: string
          description: 태스크 유형
          format: enum
        sequence:
          type: integer
          description: 순서
          format: int32
        title:
          type: string
          description: 태스크 이름
        status:
          enum:
            - FLOW_TASK_STATUS_UNSPECIFIED
            - WAITING
            - READY
            - DONE
            - NOT_STARTED
            - CANCELED
          type: string
          description: 태스크 상태
          format: enum
        paymentRequired:
          type: boolean
          description: 수납 필요 여부
        assignees:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.flow.FlowTaskAssignee"
          description: 담당자 목록
        doctors:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.flow.FlowTaskDoctor"
          description: 의사 목록
        room:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.RoomContract"
          description: 배정된 방
        assigneeMemo:
          type: string
          description: 담당자 메모
        doctorMemo:
          type: string
          description: 의사 메모
        completedDateTimeUtc:
          type: string
          description: 완료 시각 (UTC ISO 8601)
        readyDateTimeUtc:
          type: string
          description: 준비 시각 (UTC ISO 8601)
        doctorCallDateTime:
          type: string
          description: 의사 호출 시각
        procedureConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.flow.FlowTaskProcedureConfiguration"
          description: 시술 구성 정보 (type == PROCEDURE 일 때만 사용)
        etceteraConfiguration:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.flow.FlowTaskEtceteraConfiguration"
          description: 기타 시술 정보 (type == ETCETERA 일 때만 사용)
        purchaseId:
          type: string
          description: 수납 ID
        calledDoctors:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.flow.FlowTaskCalledDoctor"
          description: 호출된 의사 목록
        anesthesiaType:
          enum:
            - ANESTHESIA_TYPE_UNSPECIFIED
            - SEDATION
            - SPRAY
            - CREAM
            - DENTAL
            - GAS
            - ICE
            - CREAM_DENTAL
          type: string
          description: 마취 유형
          format: enum
        memo:
          type: string
          description: 메모
        roomAssignedDateTimeUtc:
          type: string
          description: 방 배정 시각 (UTC ISO 8601)
        doctorAssignedDateTimeUtc:
          type: string
          description: 의사 배정 시각 (UTC ISO 8601)
        responsibleDoctor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.flow.FlowTaskResponsibleDoctor"
          description: 책임 의사
        signed:
          type: boolean
          description: 서명 여부
        signedDateTimeUtc:
          type: string
          description: 서명 시각 (UTC ISO 8601)
        order:
          type: integer
          description: 정렬 순서
          format: int32
        doctorsCalledZone:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.flow.FlowTaskZone"
          description: 의사 호출 구역
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
    protos.schedule.flow.FlowTaskAssignee:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        role:
          $ref: "#/components/schemas/protos.account.AccountRoleV2Contract"
    protos.schedule.flow.FlowTaskCalledDoctor:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.schedule.flow.FlowTaskDoctor:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.schedule.flow.FlowTaskEtceteraConfiguration:
      type: object
      properties:
        etceteraTaskId:
          type: string
        name:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - name
    protos.schedule.flow.FlowTaskProcedureConfiguration:
      type: object
      properties:
        productOptionConfiguration:
          $ref: "#/components/schemas/protos.schedule.flow.FlowTaskProcedureConfiguration\
            _ProductOptionConfiguration"
        ticketConfiguration:
          $ref: "#/components/schemas/protos.schedule.flow.FlowTaskProcedureConfiguration\
            _TicketConfiguration"
        medicalServiceConfiguration:
          $ref: "#/components/schemas/protos.schedule.flow.FlowTaskProcedureConfiguration\
            _MedicalServiceConfiguration"
    protos.schedule.flow.FlowTaskProcedureConfiguration_MedicalServiceConfiguration:
      required:
        - id
        - code
        - title
        - translsMap
      type: object
      properties:
        id:
          type: string
          description: 진료 항목 ID
        code:
          type: string
          description: 진료 항목 코드
        title:
          type: string
          description: 진료 항목 이름
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        machines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceMach\
              ine"
          description: 기기 목록
        medicines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.medical_service.MedicalServiceMedi\
              cine"
          description: 약물 목록
    protos.schedule.flow.FlowTaskProcedureConfiguration_ProductOptionConfiguration:
      required:
        - optionId
        - optionTitle
        - medicineAndMachines
        - procedure
      type: object
      properties:
        optionId:
          type: string
          description: 상품 옵션 ID
        optionTitle:
          type: string
          description: 상품 옵션 이름
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
          description: 기기 및 약물 목록
        procedure:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Procedure"
          description: 시술 정보
        unit:
          allOf:
            - $ref: "#/components/schemas/protos.procedure.Unit"
          description: 단위
        productTitle:
          type: string
          description: 상품 이름
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - optionTitle
             - productTitle
    protos.schedule.flow.FlowTaskProcedureConfiguration_TicketConfiguration:
      type: object
      properties:
        ticketId:
          type: string
        round:
          $ref: "#/components/schemas/protos.schedule.flow.ProcedureRound"
    protos.schedule.flow.FlowTaskResponsibleDoctor:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        realName:
          type: string
    protos.schedule.flow.FlowTaskZone:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
    protos.schedule.flow.ProcedureRound:
      type: object
      properties:
        total:
          type: integer
          format: int32
        current:
          type: integer
          format: int32
    protos.schedule.schedule.EtceteraWorkConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
    protos.schedule.schedule.GetScheduleDetailQuery:
      required:
        - scheduleId
      type: object
      properties:
        scheduleId:
          type: string
          description: 조회할 스케줄 ID
    protos.schedule.schedule.GetScheduleDetailQueryResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.schedule.schedule.ScheduleContract"
    protos.schedule.schedule.GetSchedulesByVisitorQuery:
      required:
        - visitorId
      type: object
      properties:
        visitorId:
          type: string
          description: 조회할 내원객 ID
        startDateTimeUtc:
          type: string
          description: 조회 범위 시작 시각 (ISO 8601, e.g. `2024-01-01T00:00:00Z`)
        endDateTimeUtc:
          type: string
          description: 조회 범위 끝 시각 (ISO 8601, e.g. `2024-01-31T23:59:59Z`)
        deleted:
          type: boolean
          description: "삭제된 스케줄 포함 여부 (기본값: false)"
    protos.schedule.schedule.GetSchedulesByVisitorQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleContract"
    protos.schedule.schedule.GetSchedulesSummarizedByTaskQuery:
      required:
        - visitorId
      type: object
      properties:
        visitorId:
          type: string
          description: 조회할 내원객 ID
        paymentRequired:
          type: boolean
          description: 수납 필요 여부로 필터링 (미설정 시 전체 조회)
        deleted:
          type: boolean
          description: "삭제된 스케줄 포함 여부 (기본값: false)"
    protos.schedule.schedule.GetSchedulesSummarizedByTaskQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleSummarizedByTask"
    protos.schedule.schedule.Reaction:
      type: object
      properties:
        id:
          type: string
    protos.schedule.schedule.ScheduleContract:
      required:
        - id
        - visitor
        - flowStep
        - reservation
        - createdDateTimeUtc
        - tasks
        - purchaseIds
        - prescriptionIds
        - etceteraWorks
        - occupiedResources
      type: object
      properties:
        id:
          type: string
          description: 스케줄 ID
        visitor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.schedule.ScheduleVisitorContract"
          description: 내원객 정보
        flowStep:
          enum:
            - FLOW_STATUS_UNSPECIFIED
            - RESERVED
            - RECEPTION
            - CONSULTATION_WAITING
            - CONSULTATION
            - PROCEDURE_WAITING
            - PROCEDURE
            - PROCEDURE_DONE
            - COMPLETED
          type: string
          description: 현재 플로우 단계
          format: enum
        flowStepUpdatedDateTimeUtc:
          type: string
          description: 플로우 단계 변경 시각 (UTC ISO 8601)
        reservation:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.schedule.ScheduleDetailReservationC\
                ontract"
          description: 예약 정보
        consultation:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.schedule.ScheduleDetailConsultation\
                Contract"
          description: "@deprecated 상담 정보 (단건)"
        createdDateTimeUtc:
          type: string
          description: 생성 시각 (UTC ISO 8601)
        purchases:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleDetailPurchaseCont\
              ract"
          description: "@deprecated 수납 목록"
        tasks:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.flow.FlowTask"
          description: 시술 태스크 목록
        purchaseIds:
          type: array
          items:
            type: string
          description: 수납 ID 목록
        prescriptionIds:
          type: array
          items:
            type: string
          description: 처방전 ID 목록
        etceteraWorks:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleEtceteraWork"
          description: 기타 업무 목록
        zone:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.schedule.ZoneSummaryContract"
          description: 접수 구역 정보
        orderMemo:
          type: string
          description: 오더 메모
        receptionDateTimeUtc:
          type: string
          description: 접수 시각 (UTC ISO 8601)
        deleted:
          type: boolean
          description: 삭제 여부
        reactions:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleReaction"
          description: 반응 목록
        occupiedResources:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.OccupiedResource"
          description: 예약 일정(점유 리소스) 목록
        visitorLocation:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.VisitorLocation"
          description: 내원객 위치
        visitorRequest:
          type: string
          description: 내원객 요청사항
        updatedDateTimeUtc:
          type: string
          description: 수정 시각 (UTC ISO 8601)
        receptionNumber:
          type: integer
          description: 접수 번호
          format: int32
        consultations:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.consultation.ConsultationContract"
          description: 상담 (다건)
    protos.schedule.schedule.ScheduleDetailConsultationContract:
      type: object
      properties:
        counselor:
          $ref: "#/components/schemas/protos.schedule.Counselor"
        doctor:
          $ref: "#/components/schemas/protos.schedule.Doctor"
        consultationMemo:
          type: string
    protos.schedule.schedule.ScheduleDetailPurchaseContract:
      type: object
      properties:
        id:
          type: string
        transactions:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.Transaction"
        items:
          type: array
          items:
            $ref: "#/components/schemas/protos.purchase.PurchaseItem"
        status:
          enum:
            - SCHEDULE_DETAIL_PURCHASE_STATUS_UNSPECIFIED
            - REFUNDED
            - PARTIALLY_REFUNDED
            - APPROVED
          type: string
          format: enum
        lastUpdatedDateTimeUtc:
          type: string
    protos.schedule.schedule.ScheduleDetailReservationContract:
      required:
        - reservationGroupId
        - startDateTime
        - endDateTime
        - zoneId
        - status
        - requestedProcedures
        - connectedChannel
      type: object
      properties:
        reservationGroupId:
          type: string
          description: "@deprecated 예약 그룹 ID"
        startDateTime:
          type: string
          description: 예약 시작 시각
        endDateTime:
          type: string
          description: 예약 종료 시각
        consultationRequired:
          type: boolean
          description: 상담 필요 여부
        sedationRequired:
          type: boolean
          description: 수면 마취 필요 여부
        counselor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Counselor"
          description: 희망 상담사
        doctor:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.Doctor"
          description: "@deprecated 희망 의사"
        funnel:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationFunnel"
          description: 예약 경로
        reservationMemo:
          type: string
          description: 예약 메모
        zoneId:
          type: string
          description: "@deprecated 구역 ID"
        reservationAssignee:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.ReservationAssignee"
          description: 예약 담당자
        status:
          enum:
            - RESERVATION_STATUS_UNSPECIFIED
            - RESERVED
            - CANCELED
            - NO_SHOW
            - IN_PROGRESS
            - COMPLETED
          type: string
          description: 예약 상태
          format: enum
        requestedProcedures:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.ReservationRequestedProcedure"
          description: 희망 시술 목록
        connectedChannel:
          enum:
            - Channel_UNSPEICIFED
            - GANGNAMUNNI
            - HOMEPAGE
            - KOS_CONNECT
          type: string
          description: 유입 채널
          format: enum
    protos.schedule.schedule.ScheduleEtceteraWork:
      type: object
      properties:
        sequence:
          type: integer
          format: int32
        status:
          enum:
            - STATUS_UNSPECIFIED
            - WAITING
            - COMPLETED
            - CANCELED
          type: string
          format: enum
        memo:
          type: string
        assignees:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleEtceteraWorkAssign\
              ee"
        etceteraWorkConfiguration:
          $ref: "#/components/schemas/protos.schedule.schedule.EtceteraWorkConfiguration"
    protos.schedule.schedule.ScheduleEtceteraWorkAssignee:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        role:
          $ref: "#/components/schemas/protos.account.AccountRoleV2Contract"
    protos.schedule.schedule.ScheduleReaction:
      type: object
      properties:
        reaction:
          $ref: "#/components/schemas/protos.schedule.schedule.Reaction"
        accounts:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleReactionAccount"
    protos.schedule.schedule.ScheduleReactionAccount:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.schedule.schedule.ScheduleSummarizedByTask:
      required:
        - scheduleId
        - startDateTimeUtc
        - endDateTimeUtc
        - tasks
      type: object
      properties:
        scheduleId:
          type: string
          description: 스케줄 ID
        startDateTimeUtc:
          type: string
          description: 예약 시작 시각 (UTC ISO 8601)
        endDateTimeUtc:
          type: string
          description: 예약 종료 시각 (UTC ISO 8601)
        tasks:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.flow.FlowTask"
          description: 시술 태스크 목록
    protos.schedule.schedule.ScheduleVisitorCategoryContract:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        order:
          type: integer
          format: int32
        color:
          enum:
            - CodeColor_UNSPECIFIED
            - RED
            - LAVA
            - ORANGE
            - GREEN
            - CYAN
            - BLUE
            - PURPLE
            - MAGENTA
            - GRAY
          type: string
          format: enum
    protos.schedule.schedule.ScheduleVisitorContract:
      required:
        - id
        - name
        - chartNumber
      type: object
      properties:
        id:
          type: string
          description: 내원객 ID
        name:
          type: string
          description: 내원객 이름
        phone:
          allOf:
            - $ref: "#/components/schemas/protos.Phone"
          description: 전화번호
        chartNumber:
          type: string
          description: 차트 번호
        gender:
          enum:
            - GENDER_UNSPECIFIED
            - MALE
            - FEMALE
          type: string
          description: 성별
          format: enum
        dateOfBirth:
          type: string
          description: 생년월일
        nationality:
          type: string
          description: 국적
        memo:
          type: string
          description: 메모
        visitorType:
          allOf:
            - $ref: "#/components/schemas/protos.schedule.schedule.ScheduleVisitorTypeContrac\
                t"
          description: 고객 유형
        isNew:
          type: boolean
          description: 신규 고객 여부
        categories:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.schedule.ScheduleVisitorCategoryCon\
              tract"
          description: 고객 카테고리 목록
        snsInfo:
          allOf:
            - $ref: "#/components/schemas/protos.visitor.SnsInfo"
          description: SNS 정보
        phoneticName:
          type: string
          description: 발음 표기 이름
    protos.schedule.schedule.ScheduleVisitorTypeContract:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
    protos.schedule.schedule.ZoneSummaryContract:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
    protos.schedule.zone.GetZoneQuery:
      required:
        - zoneId
      type: object
      properties:
        zoneId:
          type: string
          description: 조회할 구역 ID
    protos.schedule.zone.GetZoneQueryResponse:
      type: object
      properties:
        data:
          $ref: "#/components/schemas/protos.schedule.zone.ZoneContract"
    protos.schedule.zone.GetZonesResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.schedule.zone.ZoneContract"
    protos.schedule.zone.ZoneContract:
      required:
        - id
        - title
        - order
        - isDefault
      type: object
      properties:
        id:
          type: string
          description: 구역 ID
        title:
          type: string
          description: 구역 이름
        order:
          type: integer
          description: 정렬 순서
          format: int32
        isDefault:
          type: boolean
          description: 기본 구역 여부
    protos.tenant.Code:
      type: object
      properties:
        id:
          type: string
        category:
          enum:
            - CODE_CATEGORY_UNSPECIFIED
            - FUNNEL
            - EXPOSURE_CHANNEL
            - ETCETRA_PRODUCT_CATEGORY
            - IMAGE_EQUIPMENT
            - CALL_CONSULTATION_RESULT
            - IMAGE_CATEGORY
            - FUNNEL_CATEGORY
            - VISITOR_CATEGORY
            - ACCOUNT_STATUS
            - CONSULTATION_RESULT
          type: string
          format: enum
        name:
          type: string
        order:
          type: integer
          format: int32
        closed:
          type: boolean
        color:
          enum:
            - CodeColor_UNSPECIFIED
            - RED
            - LAVA
            - ORANGE
            - GREEN
            - CYAN
            - BLUE
            - PURPLE
            - MAGENTA
            - GRAY
          type: string
          format: enum
        default:
          type: boolean
    protos.ticket.GetTicketBundlesQueryResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/protos.ticket.TicketBundleContract"
    protos.ticket.PriceAmount:
      type: object
      properties:
        value:
          type: number
          format: double
        currency:
          type: string
    protos.ticket.ReferenceOptionConfiguration:
      type: object
      properties:
        optionId:
          type: string
        optionTitle:
          type: string
        productTitle:
          type: string
        promotionConfiguration:
          $ref: "#/components/schemas/protos.ticket.ReferenceOptionPromotionConfiguration"
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - optionTitle
             - productTitle
    protos.ticket.ReferenceOptionPromotionConfiguration:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
    protos.ticket.TicketBundleContract:
      type: object
      properties:
        purchaseId:
          type: string
        purchaseItemId:
          type: string
        optionConfiguration:
          $ref: "#/components/schemas/protos.ticket.ReferenceOptionConfiguration"
        ticketSets:
          type: array
          items:
            $ref: "#/components/schemas/protos.ticket.TicketSetContract"
        price:
          $ref: "#/components/schemas/protos.ticket.PriceAmount"
        title:
          type: string
        visitorId:
          type: string
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
    protos.ticket.TicketContract:
      type: object
      properties:
        id:
          type: string
        status:
          enum:
            - TicketStatus_UNSPECIFIED
            - AVAILABLE
            - USED
            - CANCELED
            - IN_USE
          type: string
          format: enum
        price:
          $ref: "#/components/schemas/protos.ticket.PriceAmount"
        createdDateTimeUtc:
          type: string
    protos.ticket.TicketSetContract:
      type: object
      properties:
        medicineAndMachines:
          type: array
          items:
            $ref: "#/components/schemas/protos.procedure.MedicineAndMachine"
        procedure:
          $ref: "#/components/schemas/protos.procedure.Procedure"
        unit:
          $ref: "#/components/schemas/protos.procedure.Unit"
        tickets:
          type: array
          items:
            $ref: "#/components/schemas/protos.ticket.TicketContract"
        title:
          type: string
        ticketGroupId:
          type: string
        medicalService:
          $ref: "#/components/schemas/protos.procedure.medical_service.MedicalService"
        translsMap:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/protos.Transls"
          description: |-
            # 다국어 지원대상 필드
             - title
    protos.visitor.SnsInfo:
      type: object
      properties:
        snsType:
          enum:
            - etc
            - kakaotalk
            - line
            - instagram
            - whatsapp
            - wechat
          type: string
          format: enum
        accountId:
          type: string
  securitySchemes:
    auth_token:
      type: apiKey
      description: "[인증 토큰 교환](/docs/openapi/exchange-token) 을 통해 받아온 Auth Token"
      name: Authorization
      in: header
tags:
  - name: Authorization
    description: >
      ## 인증 방법


      인증 관련을 제외한 모든 API 요청은 인증 토큰(Auth Token)을 필요로 합니다.


      인증 토큰은 HTTP Header에 포함되어야 합니다.


      ```http request

      Authorization: {{Auth Token}}

      ```


      _\* `Bearer` 와 같은 접두사는 필요하지 않습니다._


      :::danger


      **절대로 API Key와 인증 토큰을 클라이언트 노출하지 마세요.**


      클라이언트에 노출되거나, 클라이언트에서 저장되지 않도록 주의해야 합니다.


      인증 토큰 교환 또한 절대로 클라이언트에서 이루어지면 안됩니다.


      노출된다면 악의적인 사용자가 인증 토큰을 획득하여 API를 사용할 수 있습니다.


      만약, 노출되었다면 즉시 KOS 팀을 통해 새로운 API Key를 발급 받아야 합니다.


      :::


      인증 토큰을 발급 받기 위해선, KOS 팀으로 부터 전달 받은 API Key가 필요합니다.


      [인증 토큰 교환](/docs/openapi/exchange-token) API를 통해 인증 토큰을 발급 받을 수 있습니다.


      ## 토큰 유효 기간


      인증 토큰은 **약 24시간** 동안 유효합니다. (유효 기간은 KOS 정책에 따라 변경될 수 있습니다.)


      ## 토큰 만료 처리


      토큰이 만료된 상태에서 API를 호출하면 `401` 상태 코드가 반환됩니다.


      이 경우, [인증 토큰 교환](/docs/openapi/exchange-token) API를 다시 호출하여 새로운 토큰을 발급받은 뒤
      요청을 재시도하세요.
  - name: Image
    description: |
      이미지 관련 API
  - name: PrepaidCard
    description: |-
      선불카드(멤버십) 관련 API

      ## 선불카드

      (추가 예정)
  - name: Product
    description: |
      상품, 싱품 옵션, 상품 카테고리 관련 API

      ## 상품 카테고리

      상품들을 카테고라이징 하는 값이에요. 하나의 상품에 여러개의 카테고리 설정이 가능해요.

      ## 상품

      병원이 내원객에게 판매하는 상품을 의미해요. 하나의 상품에는 여러개의 옵션들을 구성할 수 있어요.

      ## 상품 옵션

      내원객이 병원에서 받을 시술에 대한 자세한 정보와 가격을 담고있는 엔터티예요.

      예약 시, 희망 시술에도 옵션이 사용되고, 수납할 때도 옵션 단위로 수납을 진행해요.

      ### 단일 옵션

      시술이 1개인 경우 단일 옵션으로 사용돼요.

      e.g.

      - 올리지오 100샷
      - 올리지오 300샷
      - 올리지오 600샷

      ### 그룹 옵션

      시술이 2개 이상일 경우 그룹 옵션으로 설정돼요. 시술들을 묶어서 팔고싶은 경우 사용돼요.

      판매하는 시술이 N개일 뿐 단일 옵션의 조합이 아니예요.

      e.g.

      - 올링크(올리지오 200샷 + 슈링크유니버스 300샷)
      - 수면 울쎄라 300샷 + 써마지FLX 300샷 1회 + 프리미엄 수액

      ### 상담 옵션

      내원객이 상품은 결정했지만, 어떤 옵션으로 시술받아야 할지 모르는 경우에 사용되는 옵션이에요.

      따라서 상담 옵션은 이름과 설명의 속성만 가지고있고, 시술 관련 정보(가격, 시술, 기기/약물 등)들을 포함하고있지않아요.
  - name: Promotion
    description: |
      프로모션 관련 API (지원 종료)

      :::warning

      (지원 종료 이유 추가 예정)

      :::
  - name: Purchase
    description: |-
      수납 관련 API

      ## 수납

      (추가 예정)
  - name: Schedule
    description: |-
      예약 및 내원 관련 API

      ## 스케줄(Schedule)

      (추가 예정)

      ## 예약 그룹(Reservation Group)

      (추가 예정)

      ## 구역(Zone)

      (추가 예정)
  - name: TargetCountry
    description: |-
      타겟 국가 관련 API

      ## 타겟 국가

      (추가 예정)
  - name: Ticket
    description: |-
      시술권 관련 API

      ## 시술권

      (추가 예정)
  - name: Visitor
    description: |
      내원객 관련 API
