/*
  Сервис подъездов
*/
syntax = "proto3";

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "keyapis/access_control/v1/keyapis_access_control_access_control_v1.proto";

package keyapis.access_control.v1;

option java_package = "ru.keyapis.access_control.v1";
option java_outer_classname = "KeyapisAccessControlV1Proto";
option java_multiple_files = false;
option java_string_check_utf8 = true;
option go_package = "/keyapis_access_control_v1";
option cc_enable_arenas = true;
option csharp_namespace = "Keyapis.AccessControl.V1";
option objc_class_prefix = "KEYAPISACCESSCONTROLV1";
option php_namespace = "Keyapis\\AccessControl\\V1";
option ruby_package = "Keyapis::AccessControl::V1";
option optimize_for = LITE_RUNTIME;

// Сервис подъездов
service EntranceService {
  // Метод создания подъезда.
  // Для ролей employee, owner можно сохранять только подъезды квартирограмм, привязанные к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // Метод доступен для: admin, service, owner, employee
  rpc PostEntrance(PostEntranceRequest) returns (PostEntranceResponse) {
    option (google.api.http) = {
      post: "/access_control/api/v1/entrance",
      body: "*"
    };
  }

  // Метод удаления подъезда.
  // Реализуется как удаление квартир по указанному дому и номеру подъезда.
  // Для ролей employee, owner можно удалять только подъезды квартирограмм, привязанные к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // Метод доступен для: admin, service, owner, employee
  rpc DeleteEntrance(DeleteEntranceRequest) returns (DeleteEntranceResponse) {
    option (google.api.http) = {
      delete: "/access_control/api/v1/entrance/{orpon}/{entrance_number}"
    };
  }

  // Метод получения списка подъездов.
  // При переданном company_ids учитывается тип связи компании и квартирограммы.
  // Если EntranceFilter.CompanyRelationType = DEVICE_SERVICE, то проверяется связка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE.
  // Если EntranceFilter.CompanyRelationType = MANAGEMENT, то проверяется связка в flatgramm_companies.
  // Если EntranceFilter.CompanyRelationType = DEFAULT, то проверяется связка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE.
  // Если EntranceFilter.CompanyRelationType = COMPANY_RELATION_TYPE_UNKNOWN, вернется ошибка валидации.
  // При не переданном company_ids поле EntranceFilter.CompanyRelationType вызовет ошибку валидации.
  // Для ролей employee, owner можно получать только подъезды квартирограмм, привязанные к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // Метод доступен для: admin, service, owner, employee
  rpc GetEntranceList(GetEntranceListRequest) returns (stream GetEntranceListResponse) {
    option (google.api.http) = {
      get: "/access_control/api/v1/entrance/list",
    };
  }

  // Метод создания связи подъезда и устройства.
  // Для ролей employee, owner можно сохранять только связи с подъездами квартирограмм, привязанным к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // EntranceDevice.RelationType в данном методе не используется.
  // Метод доступен для: admin, service, owner, employee
  rpc PutEntranceDeviceAttach(PutEntranceDeviceAttachRequest) returns (PutEntranceDeviceAttachResponse) {
    option (google.api.http) = {
      put: "/access_control/api/v1/entrance/{entrance_device.orpon}/{entrance_device.entrance_number}/device/{entrance_device.device_id}/attach"
    };
  }

  // Метод удаления связи подъезда и устройства.
  // Для ролей employee, owner можно удалять только связи с подъездами квартирограмм, привязанным к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // EntranceDevice.RelationType в данном методе не используется.
  // Метод доступен для: admin, service, owner, employee
  rpc PutEntranceDeviceDetach(PutEntranceDeviceDetachRequest) returns (PutEntranceDeviceDetachResponse) {
    option (google.api.http) = {
      put: "/access_control/api/v1/entrance/{entrance_device.orpon}/{entrance_device.entrance_number}/device/{entrance_device.device_id}/detach"
    };
  }

  // Метод получения списка связок подъезд-устройство.
  // Для ролей employee, owner можно получать только связи с подъездами квартирограмм, привязанным к домофонной компании пользователя (привязка компании с типом dc_company_flatgramm.type = DEVICE_SERVICE).
  // Метод доступен для: admin, service, owner, employee
  rpc GetEntranceDeviceList (GetEntranceDeviceListRequest) returns (stream GetEntranceDeviceListResponse) {
    option (google.api.http) = {
      get: "/access_control/api/v1/entrance/device/list",
    };
  }
}

// Подъезд
message Entrance {
  // ОРПОН дома
  int64 orpon = 1 [(google.api.field_behavior) = REQUIRED];
  // Номер подъезда.
  // # Диапазон: 1..100
  int32 entrance_number = 2 [(google.api.field_behavior) = REQUIRED];
  // Номер начального помещения.
  // # Диапазон: 1..9999
  int32 start_room_number = 3 [(google.api.field_behavior) = REQUIRED];
  // Количество помещений на этаже.
  // # Диапазон: 1..1000
  int32 rooms_count_per_floor = 4 [(google.api.field_behavior) = REQUIRED];
  // Количество этажей.
  // # Диапазон: 1..100
  int32 floors_count = 5 [(google.api.field_behavior) = REQUIRED];
}

// Фильтр подъездов
message EntranceFilter {
  // По идентификаторам квартирограмм
  repeated int32 flatgramm_ids = 1;
  // По ОРПОН
  repeated int64 orpons = 2;
  // По идентификаторам компаний
  repeated int32 company_ids = 3;
  // Справочник типов связи компании с подъездами
  enum CompanyRelationType {
    // Значение не указано
    COMPANY_RELATION_TYPE_UNKNOWN = 0;
    // Значение по умолчанию
    DEFAULT = 1;
    // Управляющая компания владеет квартирограммой
    MANAGEMENT = 2;
    // Домофонная компания обслуживает квартирограмму
    DEVICE_SERVICE = 3;
  }
  // Тип связи компании с подъездами
  CompanyRelationType company_relation_type = 4;
}

// Постраничный вывод
message EntrancePaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По ОРПОНу и номеру подъезда
    ORPON_THEN_ENTRANCE_NUMBER = 1;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: ORPON_THEN_ENTRANCE_NUMBER
  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 GetEntranceListRequest {
  // Фильтр по подъездам
  EntranceFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Стандартный постраничный вывод
    EntrancePaging paging = 2;
  }
}
// Ответ на запрос на получение списка подъездов
message GetEntranceListResponse {
  // Ошибка запроса на получение списка подъездов
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Подъезд
    Entrance data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос создания связи подъезда и устройства
message PutEntranceDeviceAttachRequest {
  // Связь подъезда и устройства
  EntranceDevice entrance_device = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос сохранения связи подъезда и устройства
message PutEntranceDeviceAttachResponse {
  // Ошибка запроса на создание связи подъезда и устройства
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос удаления связи подъезда и устройства
message PutEntranceDeviceDetachRequest {
  // Связь подъезда и устройства
  EntranceDevice entrance_device = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос удаления связи подъезда и устройства
message PutEntranceDeviceDetachResponse {
  // Ошибка запроса на удаления связи подъезда и устройства
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос сохранения подъезда
message PostEntranceRequest {
  // Подъезд
  Entrance data = 1 [(google.api.field_behavior) = REQUIRED];
}
// Ответ на запрос сохранения подъезда
message PostEntranceResponse {
  // Ошибка сохранения подъезда
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Подъезд
    Entrance data = 1;
    // Ошибка при удалении
    Error error = 2;
  }
}

// Запрос на удаление подъезда
message DeleteEntranceRequest {
  // ОРПОН дома
  int64 orpon = 1 [(google.api.field_behavior) = REQUIRED];
  // Номер подъезда.
  // # Диапазон: 1..100
  int32 entrance_number = 2 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос удаления подъезда
message DeleteEntranceResponse {
  // Ошибка удаления подъезда
  message Error {
    // Существуют устройства, связанные с квартирами данного подъезда.
    // Следует отвязать устройства перед удалением подъезда
    message LinkedDevicesExists {}

    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
      // Существуют связанные устройства
      LinkedDevicesExists linked_devices_exists = 2;
    }
  }
  // Тип результата
  oneof type {
    // Ошибка при удалении
    Error error = 1;
  }
}


// Связка подъезда и устройства.
// Реализуется через связь всех помещений в подъезде и устройства
message EntranceDevice {
  // ОРПОН дома
  int64 orpon = 1 [(google.api.field_behavior) = REQUIRED];
  // Номер подъезда.
  // # Диапазон: 1..100
  int32 entrance_number = 2 [(google.api.field_behavior) = REQUIRED];
  // Идентификатор устройства.
  // # Диапазон: 1..2147483647
  int32 device_id = 3 [(google.api.field_behavior) = REQUIRED];
  // Тип связки
  enum RelationType {
    // Значение не указано
    RELATION_TYPE_UNKNOWN = 0;
    // Полная связь
    FULL = 1;
    // Частичная связь
    PARTIAL = 2;
  }
  // Тип связки.
  // Игнорируется в методах создания и удаления связи
  RelationType relation_type = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Фильтр связок подъезд-устройство
message EntranceDeviceFilter {
  // По идентификаторам квартирограмм
  repeated int32 flatgramm_ids = 1;
  // По ОРПОН
  repeated int64 orpons = 2;
  // По номерам подъезда
  repeated int32 entrance_numbers = 3;
  // По идентификаторам привязанных устройств
  repeated int32 device_ids = 4;
}

// Постраничный вывод
message EntranceDevicePaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По ОРПОНу и номеру подъезда
    ORPON_THEN_ENTRANCE_NUMBER = 1;
    // По идентификатору устройства
    DEVICE_ID = 2;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: ORPON_THEN_ENTRANCE_NUMBER
  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 GetEntranceDeviceListRequest {
  // Фильтр по связкам подъезд-устройство
  EntranceDeviceFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Стандартный постраничный вывод
    EntranceDevicePaging paging = 2;
  }
}
// Ответ на запрос на получение списка связок подъезд-устройство
message GetEntranceDeviceListResponse {
  // Ошибка запроса на получение списка связок подъезд-устройство
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Связка подъезд-устройство
    EntranceDevice data = 1;
    // Ошибка
    Error error = 2;
  }
}

