/*
  Сервис реализует функционал управления Шаблонами КВ.
  Шаблон КВ описывает набор технологических планов и правила их применимости для массового создания КВ
*/
syntax = "proto3";

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.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 OfferTemplateService {
  // Метод получения шаблона КВ.
  // Разрешения: subscription:offer_template:card.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc GetOfferTemplate(GetOfferTemplateRequest) returns (GetOfferTemplateResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer_template/{id}"
    };
  }
  // Метод получения списка шаблонов КВ.
  // Разрешения: subscription:offer_template:list.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc GetOfferTemplateList(GetOfferTemplateListRequest) returns (stream GetOfferTemplateListResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer_template/list"
    };
  }
  // Метод получения списка Шаблонов КВ, соответствующих коммерческим возможностям дома.
  // По ОРПОН дома определяет фактически настроенные КВ и возвращает соответствующие им Шаблоны КВ.
  // Разрешения: subscription:offer_template:list.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc GetOfferTemplateByOrponList(GetOfferTemplateByOrponListRequest) returns (stream GetOfferTemplateByOrponListResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer_template_by_orpon/{orpon}/list"
    };
  }
  // Метод получения количества шаблонов КВ.
  // Разрешения: subscription:offer_template:list.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc GetOfferTemplateCount(GetOfferTemplateCountRequest) returns (GetOfferTemplateCountResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer_template/count"
    };
  }
  // Метод получения количества Шаблонов КВ, соответствующих коммерческим возможностям дома.
  // По ОРПОН дома определяет фактически настроенные КВ и возвращает количество соответствующих им Шаблонов КВ.
  // Разрешения: subscription:offer_template:list.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc GetOfferTemplateByOrponCount(GetOfferTemplateByOrponCountRequest) returns (GetOfferTemplateByOrponCountResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer_template_by_orpon/{orpon}/count"
    };
  }
  // Метод создания/редактирования шаблона КВ.
  // При отсутствии идентификатора создаёт новый шаблон, при наличии — редактирует существующий.
  // Разрешения: subscription:offer_template:save.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc PostOfferTemplate(PostOfferTemplateRequest) returns (PostOfferTemplateResponse) {
    option (google.api.http) = {
      post: "/subscription/api/v1/offer_template"
      body: "*"
    };
  }
  // Метод архивации шаблона КВ.
  // Переводит шаблон в статус ARCHIVED.
  // Разрешения: subscription:offer_template:remove.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc DeleteOfferTemplate(DeleteOfferTemplateRequest) returns (DeleteOfferTemplateResponse) {
    option (google.api.http) = {
      delete: "/subscription/api/v1/offer_template/{id}"
    };
  }
  // Метод восстановления шаблона КВ из архива.
  // Переводит шаблон в статус ACTIVE.
  // Разрешения: subscription:offer_template:restore:save.
  // Метод доступен для: Token: service, device_admin, ltp_first, admin, mrf, bti, manager. При наличии разрешений
  rpc PostOfferTemplateRestore(PostOfferTemplateRestoreRequest) returns (PostOfferTemplateRestoreResponse) {
    option (google.api.http) = {
      post: "/subscription/api/v1/offer_template/{id}/restore"
      body: "*"
    };
  }
}

// Шаблон КВ
message OfferTemplate {
  // Идентификатор.
  // # Тип: Guid
  string id = 1;
  // Справочник типов сервисов
  enum ServiceType {
    // Значение не указано
    SERVICE_TYPE_UNKNOWN = 0;
    // Умный домофон
    INTERCOM = 1;
    // Комплексное видеонаблюдение
    CAMERAS = 2;
    // Умные счётчики
    TELEMETRY = 3;
    // Система контроля и управления доступом
    ACCESS_CONTROL_PANEL = 4;
    // Умный шлагбаум
    BARRIER = 5;
  }
  // Тип сервиса
  ServiceType service_type = 2 [(google.api.field_behavior) = REQUIRED];
  // Наименование КВ.
  // # Диапазон: 3..256
  string title = 3 [(google.api.field_behavior) = REQUIRED];
  // Описание КВ.
  // # Диапазон: 3..1024
  google.protobuf.StringValue description = 4;
  // Справочник статусов шаблона КВ
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Активен
    ACTIVE = 1;
    // Архивирован
    ARCHIVED = 2;
  }
  // Статус шаблона КВ.
  // Заполняется сервером
  StatusType status_type = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Правила применимости Шаблона КВ
  ApplicabilityRules applicability_rules = 6 [(google.api.field_behavior) = REQUIRED];
  // Список элементов Шаблона КВ.
  // Каждый элемент описывает технологический план и параметры создания КВ для него
  repeated Item items = 7 [(google.api.field_behavior) = REQUIRED];
  // Дата и время создания.
  // Заполняется сервером.
  // # Тип: DateTime
  google.protobuf.Timestamp created_at = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата и время последнего изменения.
  // Заполняется и обновляется сервером.
  // Является версией объекта.
  // # Тип: DateTime
  google.protobuf.Timestamp updated_at = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Правила применимости Шаблона КВ
  message ApplicabilityRules {
    // Ограничение по регионам.
    // # Диапазон: 0..100
    repeated int32 rf_ids = 1;
    // Справочник типов договорных схем
    enum ContractType {
      // Значение не указано
      CONTRACT_TYPE_UNKNOWN = 0;
      // Договор заключён с юридическим лицом
      B2B = 1;
      // Договор заключён с физическим лицом
      B2C = 2;
      // Смешанная схема. Ростелеком работает с клиентом через партнёра
      B2B2C = 3;
    }
    // Договорная схема
    ContractType contract_type = 2;
    // Справочник типов клиентов
    enum ClientType {
      // Значение не указано
      CLIENT_TYPE_UNKNOWN = 0;
      // Управляющая компания
      MANAGEMENT_COMPANY = 1;
      // Домофонная компания
      INTERCOM_COMPANY = 2;
    }
    // Тип клиента.
    // Заполняется только когда contract_type принимает одно из значений: B2B, B2B2C
    ClientType client_type = 3;
    // Справочник типов биллинговых систем
    enum BillingSystemType {
      // Значение не указано
      BILLING_SYSTEM_TYPE_UNKNOWN = 0;
      // Автоматизированная система расчётов макрорегионального филиала/АСР МРФ
      ASR_MRF = 1;
      // Платформа Ключ
      KEY_PLATFORM = 2;
    }
    // Биллинговая система.
    // Заполняется только когда contract_type принимает одно из значений: B2B, B2B2C
    BillingSystemType billing_system_type = 4;
    // Принимаются ли платежи за умный домофон на счёт внешней компании
    bool is_external_payment_for_smart_intercom = 5;
    // Аналоговые трубки устанавливаются в квартирах объекта
    bool is_cms_phone = 6;
    // SIP-трубки устанавливаются в квартирах объекта
    bool is_sip_phone = 7;
    // Видеомониторы устанавливаются в квартирах объекта
    bool is_video_monitor = 8;
    // Справочник типов договорной схемы устройства в квартире
    enum RoomDeviceContractType {
      // Значение не указано
      ROOM_DEVICE_CONTRACT_TYPE_UNKNOWN = 0;
      // Житель заключает договор на квартирное устройство с внешней компанией
      ROOM_DEVICE_B2B = 1;
      // Житель заключает договор на квартирное устройство с Ростелекомом
      ROOM_DEVICE_B2C = 2;
    }
    // Тип договорной схемы устройства в квартире
    RoomDeviceContractType room_device_contract_type = 9;
    // Справочник типов минимального бесплатного пакета мобильного приложения
    enum MobileAppPackageType {
      // Значение не указано
      MOBILE_APP_PACKAGE_TYPE_UNKNOWN = 0;
      // Кнопка открытия + Ключи
      OPEN_DOOR_AND_KEYS = 1;
      // Кнопка открытия + Ключи + Аудиовызовы
      OPEN_DOOR_AND_KEYS_AUDIO_CALLS = 2;
      // Кнопка открытия + Ключи + Видеовызовы
      OPEN_DOOR_AND_KEYS_VIDEO_CALLS = 3;
    }
    // Минимальный бесплатный пакет мобильного приложения
    MobileAppPackageType mobile_app_package_type = 10;
    // Переадресация на городские/мобильные номера
    bool is_call_forwarding_enabled = 11;
    // Цифровой клиентский путь
    bool is_digital_way = 12;
  }

  // Элемент Шаблона КВ
  message Item {
    // Идентификатор технологического плана.
    // # Диапазон: 1..2147483647
    int32 plan_id = 1 [(google.api.field_behavior) = REQUIRED];
    // Тип коммерческой возможности
    Offer.Type type = 2 [(google.api.field_behavior) = REQUIRED];
    // Подключать ли автоматическую подписку
    bool is_enable_auto_subscribe = 3;
    // Признак принадлежности к цифровому клиентскому пути
    bool is_digital_way = 4;
    // Адрес размещения офферты.
    // Полный url до файла.
    // # Диапазон: 0..2048
    google.protobuf.StringValue offer_url = 5;
  }

  // Ошибка сохранения.
  // Эти проверки выполняются при работе с базой данных и сторонними сервисами
  message SavingError {
    // Конфликт версий.
    // Причины:
    // - В базе хранится другая версия строки, значения updated_at отличаются
    message Conflict {}
    // Шаблон с таким типом сервиса и правилами применимости уже существует.
    // Нельзя создать два или более шаблона с одинаковым типом сервиса и одинаковыми правилами применимости
    message DuplicateTemplate {}

    // Причина ошибки
    oneof reason {
      // Конфликт версий
      Conflict conflict = 1;
      // Дублирование шаблона
      DuplicateTemplate duplicate_template = 2;
    }
  }
}

// Фильтр по шаблонам КВ
message OfferTemplateFilter {
  // По статусам
  repeated OfferTemplate.StatusType status_types = 1;
  // По типам сервисов
  repeated OfferTemplate.ServiceType service_types = 2;
  // По идентификаторам регионов (из правил применимости)
  repeated int32 rf_ids = 3;
  // По тексту.
  // Если значение не передано, поиск по нему не производится.
  // # Диапазон: 3..64.
  // # Поиск производится по полям:
  // # - Наименование;
  // # - Описание
  google.protobuf.StringValue text = 4;
  // По типам договорных схем (из правил применимости)
  repeated OfferTemplate.ApplicabilityRules.ContractType applicability_rules_contract_types = 5;
  // По типам клиентов (из правил применимости)
  repeated OfferTemplate.ApplicabilityRules.ClientType applicability_rules_client_types = 6;
  // По типам биллинговых систем (из правил применимости)
  repeated OfferTemplate.ApplicabilityRules.BillingSystemType applicability_rules_billing_system_types = 7;
  // По признаку внешней оплаты умного домофона (из правил применимости)
  google.protobuf.BoolValue is_external_payment_for_smart_intercom = 8;
  // По наличию CMS телефона в квартире (из правил применимости)
  google.protobuf.BoolValue applicability_rules_is_cms_phone = 9;
  // По наличию SIP телефона в квартире (из правил применимости)
  google.protobuf.BoolValue applicability_rules_is_sip_phone = 10;
  // По наличию видеомонитора в квартире (из правил применимости)
  google.protobuf.BoolValue applicability_rules_is_video_monitor = 11;
  // По типам договорной схемы устройства в квартире (из правил применимости)
  repeated OfferTemplate.ApplicabilityRules.RoomDeviceContractType applicability_rules_room_device_contract_types = 12;
  // По типам минимального бесплатного пакета мобильного приложения (из правил применимости)
  repeated OfferTemplate.ApplicabilityRules.MobileAppPackageType applicability_rules_mobile_app_package_types = 13;
  // По признаку переадресации на городские/мобильные номера (из правил применимости)
  google.protobuf.BoolValue is_call_forwarding_enabled = 14;
  // По признаку цифрового клиентского пути (из правил применимости)
  google.protobuf.BoolValue is_digital_way = 15;
  // По идентификаторам технологических планов (из элементов шаблона)
  repeated int32 plan_ids = 16;
}

// Пагинация по шаблонам КВ
message OfferTemplatePaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По дате создания
    CREATED_AT = 1;
    // По наименованию
    TITLE = 2;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: CREATED_AT
  OrderByType order_by_type = 1;
  // Справочник типов направлений сортировки.
  // # Тип: byte
  enum DirectionType {
    // Значение не указано
    DIRECTION_TYPE_UNKNOWN = 0;
    // От большего к меньшему
    DESC = 1;
    // От меньшего к большему
    ASC = 2;
  }
  // Тип направления сортировки.
  // # По умолчанию: DESC
  DirectionType direction_type = 2;
  // Количество записей на страницу.
  // Если значение 0 (не передано), то будет взято значение по умолчанию.
  // # Диапазон: 0..100.
  // # По умолчанию: 20
  int32 limit = 3;
  // Сдвиг.
  // # Диапазон: 0..2147483647
  int32 offset = 4;
}

// Запрос получения шаблона КВ
message GetOfferTemplateRequest {
  // Идентификатор шаблона КВ.
  // Тип: Guid
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос получения шаблона КВ
message GetOfferTemplateResponse {
  // Тип результата
  oneof type {
    // Шаблон КВ
    OfferTemplate data = 1;
  }
}

// Запрос получения списка шаблонов КВ
message GetOfferTemplateListRequest {
  // Фильтр
  OfferTemplateFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Пагинация
    OfferTemplatePaging paging = 2;
  }
}
// Ответ на запрос получения списка шаблонов КВ
message GetOfferTemplateListResponse {
  // Ошибка запроса получения списка шаблонов КВ
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Шаблон КВ
    OfferTemplate data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения списка Шаблонов КВ по ОРПОН дома
message GetOfferTemplateByOrponListRequest {
  // ОРПОН. Идентификатор дома
  int64 orpon = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос получения списка Шаблонов КВ по ОРПОН дома
message GetOfferTemplateByOrponListResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Шаблон КВ
    OfferTemplate data = 1;
    // Ошибка
    Error error = 2;
  }
}

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

// Запрос получения количества Шаблонов КВ по ОРПОН дома
message GetOfferTemplateByOrponCountRequest { 
  // ОРПОН. Идентификатор дома
  int64 orpon = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос получения количества Шаблонов КВ по ОРПОН дома
message GetOfferTemplateByOrponCountResponse {
  // Ошибка запроса
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Всего шаблонов КВ
    int32 data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос создания/редактирования шаблона КВ
message PostOfferTemplateRequest {
  // Шаблон КВ.
  // Если id не передан — создаётся новый шаблон.
  // Если id передан — редактируется существующий шаблон
  OfferTemplate data = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос создания/редактирования шаблона КВ
message PostOfferTemplateResponse {
  // Ошибка запроса сохранения шаблона КВ
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Ошибка сохранения
      OfferTemplate.SavingError saving = 2;
    }
  }
  // Тип результата
  oneof type {
    // Шаблон КВ
    OfferTemplate data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос архивации шаблона КВ
message DeleteOfferTemplateRequest {
  // Идентификатор шаблона КВ.
  // Тип: Guid
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос архивации шаблона КВ
message DeleteOfferTemplateResponse {}

// Запрос восстановления шаблона КВ из архива
message PostOfferTemplateRestoreRequest {
  // Идентификатор шаблона КВ.
  // Тип: Guid
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос восстановления шаблона КВ из архива
message PostOfferTemplateRestoreResponse {
  // Тип результата
  oneof type {
    // Восстановленный шаблон КВ
    OfferTemplate data = 1;
  }
}

// Ошибки валидации.
// Эти проверки выполняются до обращения в базу данных
message ValidationError {
  // Путь к полю в формате наименования прото
  string path = 1 [(google.api.field_behavior) = REQUIRED];
  // Валидационное сообщение
  string message = 2 [(google.api.field_behavior) = REQUIRED];
}
