/*
  Сервис реализует функционал управления подписками пользователей.
  Подписка это доступный на квартиру набор услуг на перриод времени
*/
syntax = "proto3";

import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/wrappers.proto";
import "keyapis/subscription/v1/keyapis_subscription_offer_v1.proto";

package keyapis.subscription.v1;

option java_package = "ru.keyapis.subscription.v1";
option java_outer_classname = "KeyapisSubscriptionV1Proto";
option java_multiple_files = false;
option java_string_check_utf8 = true;
option go_package = "/keyapis_subscription_v1";
option cc_enable_arenas = true;
option csharp_namespace = "Keyapis.Subscription.V1";
option objc_class_prefix = "KEYAPISSUBSCRIPTIONV1";
option php_namespace = "Keyapis\\Subscription\\V1";
option ruby_package = "Keyapis::Subscription::V1";
option optimize_for = LITE_RUNTIME;

// Сервис подписок
service SubscriptionService {
  // Метод получения подписки.
  // Метод доступен для: admin, mrf, master, ltp_first, service, application(subscription:read или subscription:edit)
  rpc GetSubscription(GetSubscriptionRequest) returns (GetSubscriptionResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/subscription/{id}"
    };
  }
  // Метод получения списка подписок.
  // Метод доступен для: admin, mrf, master, ltp_first, service, application(subscription:read или subscription:edit)
  rpc GetSubscriptionList(GetSubscriptionListRequest) returns (stream GetSubscriptionListResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/subscription/list"
    };
  }
  // Метод получения количества подписок.
  // Метод доступен для: admin, mrf, master, ltp_first, service, application(subscription:read или subscription:edit)
  rpc GetSubscriptionCount(GetSubscriptionCountRequest) returns (GetSubscriptionCountResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/subscription/count"
    };
  }
}

// Подписка
message Subscription {
  // Идентификатор.
  // Может быть явно задан при создании.
  // Тип: Guid
  string id = 1;
  // ОРПОН.
  // Идентификатор дома
  int64 orpon = 2 [(google.api.field_behavior) = REQUIRED];
  // Номер квартиры
  string flat_number = 3 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор коммерческой возможности(КВ).
  // Заполняется сервером на основе идентификатора из технологического плана(ТП)
  int32 offer_id = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Типы статусов подписки
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Настроена.
    // Подписка переведена в статус настройки.
    // Это промо-период, либо монтажник проверяет работу оборудования.
    // Услуги подписки не оплачены, но доступны для использования.
    // Финальный статус
    SETUP = 1;
    // Активна.
    // Подписка активирована.
    // С этого момента считаем что нужно считать денежки.
    // Услуги подписки оплачены и доступны для использования.
    // Финальный статус
    ACTIVE = 2;
    // Заблокирована.
    // Подписка фин. заблокирована.
    // Подписка в фин. блокировке.
    // Услуги подписки не оплачены и не доступны.
    // Финальный статус
    BLOCKED = 3;
    // Отменена.
    // Подписка отменена.
    // Пользователь отменил подписку.
    // Услуги подписки больше не существуют и не доступны абоненту
    CANCELED = 4;
    // Запланированная отмена.
    // Пользователь решил отказаться от услуги, но уже заплатил.
    // Подписка запланирована к отмене, будет действовать до истечения срока действия в подписке.
    // Услуги подписки оплачены и доступны для использования.
    // Финальный статус
    SCHEDULED_CANCELED = 5;
  }
  // Cтатус подписки.
  // При создании может быть: SETUP, ACTIVE
  StatusType status_type = 5 [(google.api.field_behavior) = REQUIRED];
  // Предыдущий статус подписки.
  // В справочник входят только финальные статусы.
  // Заполняется сервером при изменении статусов
  StatusType previous_status_type = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Цена
  google.protobuf.DoubleValue price = 7;
  // Дата создания записи.
  // Заполняется сервером
  google.protobuf.Timestamp created_at = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата последнего изменения.
  // Заполняется и обновляется сервером.
  // Заполняется при создании и изменении.
  // Является версией объекта
  google.protobuf.Timestamp changed_at = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Признак для определения автоподписок.
  // Редактировать флаг запрещено.
  // Проставляется сервером в true при создании через задачу на автоподписку
  bool is_enable_auto_subscribe = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Типы биллинга подпискии
  enum BillingType {
    // Значение не указано
    BILLING_TYPE_UNKNOWN = 0;
    // АСР МРФ.
    // Обслуживание счетов и расчёты с клиентами происходят в АСР МРФ
    ASR_MRF = 1;
    // АСР Ключ.
    // Обслуживание счетов и расчёты с клиентами происходят внутри Ключа
    ASR_KEY = 2;
    // АСР УК.
    // Обслуживание счетов и расчёты с клиентами происходят во внешнем АСР от управляющей компании
    ASR_MC = 3;
  }
  // Тип биллинга
  BillingType billing_type = 11;
  // Срок действия.
  // Проставляется при создании
  google.protobuf.Timestamp expired_at = 12;
  // Идентификатор подписки, в зависимости от которой подключена данная.
  // Заполняется в подписках на опции.
  // Тип: Guid
  google.protobuf.StringValue parent_id = 13;
  // Аккаунт
  google.protobuf.Int64Value account = 14;
  // Снапшот состояния коммерческой возможности на момент создания подписки.
  // В данный момент это ссылка в базе на запись, в будущем это будет снапшот
  keyapis.subscription.v1.Offer offer = 15;
  // Цена по скидки.
  // Заполнена если оплата подписки прошла по скидке, иначе очищается
  google.protobuf.DoubleValue discount_price = 16;
}
// Фильтр подписок
message SubscriptionFilter {
  // По ОРПОНам
  repeated int64 orpons = 1;
  // По номерам квартир
  repeated string flat_numbers = 2;

  // Ошибки валидации фильтра по подпискам.
  // Эти проверки выполняются до обращения в базу данных
  message ValidationError {
    // Причины:
    // - Формат ОРПОН некорректен;
    // - ОРПОН передан некорректно, к примеру, значение <= 1
    message OrponsInvalid {}
    // Причины:
    // - Формат квартиры некорректен (например, длина номера квартира более 4 знаков или отрицательное значение)
    message FlatNumbersInvalid {}

    // Причина ошибки
    oneof reason {
      // Формат ОРПОН некорректен
      OrponsInvalid orpons = 1;
      // Формат квартиры некорректен
      FlatNumbersInvalid flat_numbers = 2;
    }
  }
}
// Пагинация по подпискам
message SubscriptionPaging {
  // Справочник типов значений сортировки
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По идентификатору
    ID = 1;
  }
  // Тип значения сортировки.
  // По умолчанию: ID
  OrderByType order_by_type = 1;
  // Справочник типов направлений сортировки
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Тип направления сортировки.
  // По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Минимальное значение: 1.
  // Максимальное значение: 100.
  // По умолчанию: 20.
  // Если значение 0 (не передано), то выставляем значение по умолчанию
  int32 limit = 3;
  // Сдвиг.
  // По умолчанию: 0
  int32 offset = 4;

  // Ошибка валидации постраничной пагинации по подпискам.
  // Эти проверки выполняются до обращения в базу данных
  message ValidationError {
    // Причины:
    // - Значение количества < 0 или > 100
    message LimitInvalid {}
    // Причины:
    // - Значение сдвига < 0
    message OffsetInvalid {}

    // Причина ошибки
    oneof reason {
      // Количество передано некорректно
      LimitInvalid limit = 1;
      // Сдвиг передан некорректно
      OffsetInvalid offset = 2;
    }
  }
}

// Запрос получения подписки
message GetSubscriptionRequest {
  // Идентификатор подписки
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос получения подписки
message GetSubscriptionResponse {
  // Тип результата
  oneof type {
    // Подписка
    Subscription data = 1;
  }
}

// Запрос получения списка подписок
message GetSubscriptionListRequest {
  // Фильтр
  SubscriptionFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Пагинация
    SubscriptionPaging paging = 2;
  }
}
// Ответ на запрос получения списка подписок
message GetSubscriptionListResponse {
  // Ошибка запроса получения списка подписки
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка фильтрации
      SubscriptionFilter.ValidationError subscription_filter_validation = 1;
      // Ошибка пагинации  по страницам
      SubscriptionPaging.ValidationError subscription_paging_validation = 2;
    }
  }
  // Тип результата
  oneof type {
    // Подписка
    Subscription data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения количества подписок
message GetSubscriptionCountRequest {
  // Фильтр
  SubscriptionFilter filter = 1;
}
// Ответ на запрос получения количества подписок
message GetSubscriptionCountResponse {
  // Ошибка запроса получения количества подписок
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка фильтрации подписок
      SubscriptionFilter.ValidationError subscription_filter_validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Всего подписок
    int32 data = 1;
    // Ошибка
    Error error = 2;
  }
}
