/*
  Сервис реализует функционал управления коммерческими возможностями(КВ).
  КВ это описание доступных технологических планов(ТП) на ОРПОНе(на доме)
*/
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_plan_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 OfferService {
  // Метод получения коммерческой возможности.
  // Метод доступен для: admin, mrf, master, ltp_first, service, application(subscription:read или subscription:edit)
  rpc GetOffer(GetOfferRequest) returns (GetOfferResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer/{id}"
    };
  }
  // Метод получения списка коммерческих возможностей.
  // Метод доступен для: admin, mrf, master, external_seller, ltp_first, owner, employee, service, application(subscription:read или subscription:edit)
  rpc GetOfferList(GetOfferListRequest) returns (stream GetOfferListResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer/list"
    };
  }
  // Метод получения количества коммерческих возможностей.
  // Метод доступен для: admin, mrf, master, external_seller, ltp_first, owner, employee, service, application(subscription:read или subscription:edit)
  rpc GetOfferCount(GetOfferCountRequest) returns (GetOfferCountResponse) {
    option (google.api.http) = {
      get: "/subscription/api/v1/offer/count"
    };
  }
}

// Коммерческая возможность(КВ)
message Offer {
  // Идентификатор
  int32 id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Типы коммерческих возможностей
  enum Type {
    // Значение не указано
    TYPE_UNKNOWN = 0;
    // УК.
    // Услуги, которые назначаются на управляющие компанию
    COMPANY = 1;
    // Ростелеком.
    // Услуги, которые Ростелеком подключает напрямую физическим лицам
    RTK = 2;
    // Общая.
    // Услуги, которые видят клиенты обоих типов
    SHARED = 3;
  }
  // Тип коммерческой возможности
  Type type = 2 [(google.api.field_behavior) = REQUIRED];
  // ОРПОН.
  // Идентификатор дома
  int64 orpon = 3 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор компании
  google.protobuf.Int32Value company_id = 4;
  // Идентификатор технологического плана
  int32 plan_id = 5 [(google.api.field_behavior) = REQUIRED];
  // Подключать ли автоматическую подписку
  bool is_enable_auto_subscribe = 6;
  // Типы статусов коммерческих возможностей
  enum StatusType {
    // Значение не указано
    STATUS_TYPE_UNKNOWN = 0;
    // Активно.
    // Доступно
    ACTIVE = 1;
    // Заблокировано.
    // Приостановлено
    BLOCKED = 2;
  }
  // Тип статуса заказа
  StatusType status_type = 7 [(google.api.field_behavior) = REQUIRED];
  // Цена
  google.protobuf.DoubleValue price = 8;
  // Признак принадлежности к цифровому пути
  bool is_digital_way = 9;
  // Дата создания записи.
  // Заполняется сервером
  google.protobuf.Timestamp created_at = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата последнего изменения.
  // Заполняется и обновляется сервером.
  // Заполняется при создании и изменении.
  // Является версией объекта
  google.protobuf.Timestamp changed_at = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Адрес размещения офферты.
  // Полный url до файла
  google.protobuf.StringValue offer_url = 12;
  // Снапшот состояния технологического плана на момент создания предложения.
  // В данный момент это ссылка в базе на запись, в будущем это будет снапшот
  keyapis.subscription.v1.Plan plan = 13;
  // Цена по скидке
  google.protobuf.DoubleValue discount_price = 14;
  // Справочник условий на скидки
  enum DiscountRequirementType {
    // Значение не указано.
    // Если указана цена по скидке, а условие не проставлено, скидка не отображается и не применяется
    DISCOUNT_REQUIREMENT_TYPE_UNKNOWN = 0;
    // Безусловная скидка
    NO_CONDITIONS = 1;
    // ШПД интернет оплачен
    INTERNET_IS_PAID = 2;
  }
  // Условия на скидку.
  // Если условий много то для срабатывания должны выполнять все условия
  repeated DiscountRequirementType discount_requirement_types = 15;
}
// Фильтр по коммерческим возможностям
message OfferFilter {
  // По типам
  repeated Offer.Type types = 1;
  // По ОРПОНам
  repeated int64 orpons = 2;
  // По идентификаторам компаний
  repeated int32 company_ids = 3;

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

    // Причина ошибки
    oneof reason {
      // Формат ОРПОН некорректен
      OrponsInvalid orpons = 1;
      // Формат идентификатора компании некорректен
      CompanyIdsInvalid company_ids = 2;
    }
  }
}
// Пагинация по коммерческим возможностям
message OfferPaging {
  // Справочник типов значений сортировки
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По идентификатору
    ID = 1;
    // По цене
    PRICE = 2;
  }
  // Тип значения сортировки.
  // По умолчанию: 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 GetOfferRequest {
  // Идентификатор коммерческой возможности
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос получения коммерческой возможности
message GetOfferResponse {
  // Тип результата
  oneof type {
    // Коммерческая возможность
    Offer data = 1;
  }
}

// Запрос получения коммерческих возможностей
message GetOfferListRequest {
  // Фильтр
  OfferFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Пагинация
    OfferPaging paging = 2;
  }
}
// Ответ на запрос получения коммерческих возможностей
message GetOfferListResponse {
  // Ошибка запроса получения коммерческих возможностей
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка фильтрации
      OfferFilter.ValidationError offer_filter_validation = 1;
      // Ошибка пагинации по страницам
      OfferPaging.ValidationError offer_paging_validation = 2;
    }
  }
  // Тип результата
  oneof type {
    // Коммерческая возможность
    Offer data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения количества коммерческих возможностей
message GetOfferCountRequest {
  // Фильтр
  OfferFilter filter = 1;
}
// Ответ на запрос получения количества коммерческих возможностей
message GetOfferCountResponse {
  // Ошибка запроса получения количества коммерческих возможностей
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка фильтрации
      OfferFilter.ValidationError offer_filter_validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Всего коммерческих возможностей
    int32 data = 1;
    // Ошибка
    Error error = 2;
  }
}

