openapi: 3.0.1
info:
  title: Customer - сервис для управления клиентами
  description: |-
    Область ответственности сервиса - предоставление пользователю функционала корзины и кошелька.
  version: 1.0.0

tags:
  - name: account
    description: аккаунт
  - name: currency
    description: доступные валюты
  - name: cart
    description: корзина
  - name: wallet
    description: кошелёк
  - name: history
    description: история

paths:
  /account:
    get:
      tags:
        - account
      summary: Получение текущего аккаунта юзера
      description: Используется при заходе юзера в систему. Айдишник юзера получает из токена, который передаётся в заголовке authorization
      operationId: getAccount
      security:
        - Bearer: []
      responses:
        "200":
          description: успешное получение
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Такого пользователя нет
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - account
      summary: Создать новый аккаунт
      description: Создаёт новый аккаунт для юзера, если такого ещё не было
      operationId: addAccount
      security:
        - Bearer: []
      responses:
        "200":
          description: успешное создание аккаунта
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    patch:
      tags:
        - account
      summary: Отредактировать аккаунт
      description: Изменяет имя и название организации пользователя
      operationId: changeAccount
      security:
        - Bearer: []
      requestBody:
        description: Модель имени
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Name"
      responses:
        "200":
          description: успешное создание аккаунта
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - account
      summary: удалить собственный аккаунт
      description: помечает аккаунт удалённым
      operationId: deleteAccount
      security:
        - Bearer: []
      responses:
        "200":
          description: успешное удаление аккаунта
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /accounts:
    get:
      tags:
        - account
      summary: списко аккаунтов с пагинацией
      description: получает список аккаунтов на указанной странице +  общее количество аккаунтов
      operationId: paginationAccounts
      parameters:
        - name: page
          in: query
          description: Номер страницы, начиная с 1
          required: false
          explode: false
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: размер страницы
          required: false
          explode: false
          schema:
            type: integer
            default: 100
      responses:
        "200":
          description: успешное получение страницы аккаунтов
          content:
            application/json:
              schema:
                type: object
                properties:
                  totalPages:
                    type: integer
                    example: 11
                  accounts:
                    type: array
                    items:
                      $ref: "#/components/schemas/Account"

  /account/{userId}:
    get:
      tags:
        - account
      summary: Получить аккаунт по ID пользователя системы единой авторизации
      description: Метод необходимый в основном только менеджерам, для получения данных о клиенте
      security:
        - Bearer: []
      operationId: getDirectAccount
      parameters:
        - name: userId
          in: path
          description: ID аккаунта
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Успешное получение аккаунта
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Нет такого пользователя
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    patch:
      tags:
        - account
      summary: Выставление статуса верификации
      description: Используется сервисом верификации для выставления статуса верификации, является ли юзер НКО, Юр Лицом или Физ Лицом
      operationId: setAccountVerificationStatus
      security:
        - Bearer: []
      parameters:
        - name: userId
          in: path
          description: ID аккаунта
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  $ref: "#/components/schemas/AccountStatus"
      responses:
        "200":
          description: Успешное выставление статуса
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "404":
          description: Нет такого пользователя
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - account
      summary: Удалить аккаунт по айди
      description: Метод необходимый в основном только менеджерам, для удаления клиента
      operationId: deleteDirectAccount
      security:
        - Bearer: []
      parameters:
        - name: userId
          in: path
          description: ID аккаунта
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Успешное удаление аккаунта
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Нет такого пользователя
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /currencies:
    get:
      tags:
        - currency
      summary: получить список одобренных валют
      operationId: getCurrencies
      responses:
        "200":
          description: успешное получение списка валют
          content:
            application/json:
              schema:
                type: array
                example:
                  - "RUB"
                  - "USD"
                  - "CAD"
                items:
                  type: string
    put:
      tags:
        - currency
      summary: обновляет список одобренных валют
      operationId: updateCurrencies
      security:
        - Bearer: []
      requestBody:
        content:
          application/json:
            schema:
              type: array
              example:
                - "RUB"
                - "USD"
                - "CAD"
              items:
                type: string
      responses:
        "200":
          description: успешное обновление списка валют
          content:
            application/json:
              schema:
                type: array
                example:
                  - "RUB"
                  - "USD"
                  - "CAD"
                items:
                  type: string
        "401":
          description: Uanuthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /cart:
    patch:
      tags:
        - cart
      summary: Добавляем в корзину тариф
      description: Необходимо проверить, что такой тариф существует
      operationId: add2cart
      security:
        - Bearer: []
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
            example: "807f1f77bcf81cd799439011"
      responses:
        "200":
          description: Добавлено в корзину
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Не найден такой тариф
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - cart
      summary: Удаляем из корзины тариф
      operationId: removeFromCart
      security:
        - Bearer: []
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
            example: "807f1f77bcf81cd799439011"
      responses:
        "200":
          description: Удалено из корзины
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Не найден такой тариф
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /cart/pay:
    post:
      tags:
        - cart
      summary: оплатить козину
      operationId: payCart
      security:
        - Bearer: []
      description: Запрос на проведение оплаты корзины
      responses:
        "200":
          description: успешная оплата корзины
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /wallet:
    patch:
      tags:
        - wallet
      summary: Изменить валюту кошелька
      operationId: changeCurrency
      description: >-
        При запросе необходимо:

        - Отвалидировать, что такая валюта одобрена

        - Получить данные из сервиса cbrf (выдам задачу на него чуть позднее)

        - Перевести валюту кошелька в новую валюту. Кошелёк нарочно целочисленный, чтобы не было претензий к точности с плавающей точкой, поэтому, например долларовый счёт считается в центах

      security:
        - Bearer: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [currency]
              properties:
                currency:
                  type: string
                  example: "USD"
      responses:
        "200":
          description: Успешная смена валюты кошелька
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "400":
          description: Такая валюта не одобрена
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Пользователь не найден
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - wallet
      summary: Запрос на получение ссылки на оплату
      operationId: requestMoney
      security:
        - Bearer: []
      description: >-
        - Формируем запрос к сервису оплаты, с необходимыми постбэками

        - Получаем ответ от сервиса оплаты с ссылкой на оплату, которую надо передать пользователю
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [type, currency, amount]
              properties:
                type:
                  $ref: "#/components/schemas/PaymentType"
                currency:
                  type: string
                  description: "ISO-4217 формат"
                  example: "RUB"
                amount:
                  type: integer
                  example: 15020
                bankCard:
                  $ref: "#/components/schemas/BankCard"
                phoneNumber:
                  type: string
                  example: "79000000000"
                login:
                  type: string
                  example: "login_test"
                returnUrl:
                  type: string
                  example: "https://site.ru/cart"
      responses:
        "200":
          description: Успешный запрос денег
          content:
            application/json:
              schema:
                type: object
                properties:
                  link:
                    type: string
                    example: "https://google.ru"
        "500":
          description: Сервис оплаты вернул ошибку
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /history:
    get:
      tags:
        - history
      summary: Получение лога событий связанных с аккаунтом
      operationId: getHistory
      security:
        - Bearer: [ ]
      parameters:
        - name: page
          in: query
          description: Номер страницы, начиная с 1
          required: false
          explode: false
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: Размер страницы
          required: false
          explode: false
          schema:
            type: integer
            default: 100
        - name: type
          in: query
          description: Тип события
          required: false
          explode: false
          schema:
            type: string
        - name: accountID
          in: query
          description: Идентификатор аккаунта. Если не указан, будет использоваться идентификатор из токена.
          required: false
          explode: false
          schema:
            type: string
      responses:
        "200":
          description: Успешное получение событий
          content:
            application/json:
              schema:
                type: object
                properties:
                  totalPages:
                    type: integer
                    example: 11
                  records:
                    type: array
                    items:
                      $ref: "#/components/schemas/History"
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /recent:
    get:
      tags:
        - history
      summary: Получение недавних тарифов
      operationId: getRecentTariffs
      description: Возвращает список уникальных тарифов из истории. Айди аккаунта получается из заголовка.
      security:
        - Bearer: []
      responses:
        '200':
          description: Успешный запрос
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TariffID"
        '400':
          description: Неверный запрос
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        '404':
          description: Тарифы не найдены
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [id]
              properties:
                id:
                  type: string
                  example: "807f1f77bcf81cd799439011"
  /sendReport:
    post:
      tags:
        - history
      summary: отправить акт проделанных работ на почту
      operationId: sendReport
      security:
        - Bearer: []
      description: Запрос на отправку акта проделанных работ
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [id]
              properties:
                id:
                  type: string
                  example: "807f1f77bcf81cd799439011"
      responses:
        "200":
          description: успешная отправка
        "401":
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /history/ltv:
    post:
      tags:
        - history
      summary: Расчет среднего времени жизни платящего клиента (LTV)
      operationId: calculateLTV
      security:
        - Bearer: [ ]
      requestBody:
        description: Период для расчета LTV
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                from:
                  type: integer
                  format: int64
                  description: Начальная дата в формате Unix timestamp. Если 0, устанавливает начало истории.
                to:
                  type: integer
                  format: int64
                  description: Конечная дата в формате Unix timestamp. Если 0, устанавливает текущее время.
              required:
                - from
                - to
      responses:
        '200':
          description: Успешный расчет LTV
          content:
            application/json:
              schema:
                type: object
                properties:
                  ltv:
                    type: integer
                    format: int64
                    description: Среднее количество дней между первым и последним платежом
        '400':
          description: Неверный запрос, если from больше, чем to
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Неавторизован
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"


components:
  schemas:
    Account:
      type: object
      required:
        [_id, userId, cart, wallet, name, status, deleted, createdAt, updatedAt]
      properties:
        _id:
          type: string
          example: "807f1f77bcf81cd799439011"
        userId:
          type: string
          example: "807f1f77bcf81cd799439011"
        name:
          $ref: "#/components/schemas/Name"
        cart:
          type: array
          items:
            type: string
          example:
            - "807f1f77bcf81cd799439011"
            - "807f1f77bcf81cd799439012"
        wallet:
          $ref: "#/components/schemas/Wallet"
        status:
          $ref: "#/components/schemas/AccountStatus"
        isDeleted:
          type: boolean
          example: false
        createdAt:
          type: string
          format: "date-time"
        updatedAt:
          type: string
          format: "date-time"
        deletedAt:
          type: string
          format: "date-time"

    Name:
      type: object
      properties:
        firstname:
          type: string
          example: Иван
        secondname:
          type: string
          example: Иванов
        middlename:
          type: string
          example: Иванович
        orgname:
          type: string
          example: ООО \"Моя Оборона\"

    BankCard:
      type: object
      required: [number, expiryYear, expiryMonth]
      properties:
        number:
          type: string
          example: "RUB"
          description: Номер карты
        expiryYear:
          type: string
          example: "2021"
          description: Год истечения срока карты (YYYY)
        expiryMonth:
          type: string
          example: "05"
          description: Месяц истечения срока карты (MM)
        csc:
          type: string
          example: "05"
          description: Код CVC2 или CVV2, 3 или 4 символа, печатается на обратной стороне карты
        cardholder:
          type: string
          description: Имя владельца карты
          example: "IVAN IVANOV"

    Wallet:
      type: object
      required: [currency, cash, money, purchasesAmount, spent]
      properties:
        currency:
          description: Текущий курс валюты
          type: string
          example: "RUB"
        cash:
          description: Сумма money переведённая на текущий курс
          type: integer
          format: int64
          example: 10701
        purchasesAmount:
          type: integer
          format: int64
          description: Общая сумма денег, которые внёс пользователь
        spent:
          type: integer
          format: int64
          description: Общая сумма потраченных денег за всё время существования аккаунта
        money:
          type: integer
          format: int64
          description: >-
            Деньги на счету в копейках. Чтобы при перессчётах не
            возникало денег изниоткуда. фиксируемся к одной валюте,
            она будет внутренней, никому её не покажем
          example: 10701

    History:
      type: object
      required:
        [id, userId, type, deleted, createdAt, updatedAt, comment, subject]
      properties:
        id:
          type: string
          example: "807f1f77bcf81cd799439011"
        userId:
          type: string
          example: "807f1f77bcf81cd799439011"
        type:
          type: string
          example: "customer.tariffEnded"
        isDeleted:
          type: boolean
          example: false
        createdAt:
          type: string
          format: "date-time"
        updatedAt:
          type: string
          format: "date-time"
        deletedAt:
          type: string
          format: "date-time"
        comment:
          type: string
          example: "я это сделал потому что 42"
        rawDetails:
          type: string
          description: >-
            Я пока не могу предположить, какие будут фильтры по
            истории, поэтому предлагаю в это 
            поле просто класть строку с json. 
            Ибо для каждого типа записи она своя.
          example: '{"tariffs":["807f1f77bcf81cd799439011","807f1f77bcf81cd799439011"]}'

    PaymentType:
      type: string
      enum:
        [
          "bankCard",
          "tinkoffBank",
          "qiwi",
          "sberbank",
          "yoomoney",
          "mobile",
          "installments",
          "cash",
          "sbp",
          "b2bSberbank",
          "alfabank",
        ]

    TariffID:
      type: object
      properties:
        ID:
          type: string
          example: "807f1f77bcf81cd799439011"


    AccountStatus:
      type: string
      enum: ["no", "nko", "org"]

    Error:
      type: object
      required: [code, message]
      properties:
        statusCode:
          type: integer
          format: int64
          example: 404
        message:
          type: string
          example: user not found

  securitySchemes:
    Bearer: # arbitrary name for the security scheme
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Enter the token with the `Bearer: ` prefix, e.g. "Bearer abcde12345".
