/*
  Сервис ключей
*/
syntax = "proto3";

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.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 RfidService {
  // Метод получения ключа.
  // Метод доступен для: admin, service, ltp_first, owner, employee
  rpc GetRfid(GetRfidRequest) returns (GetRfidResponse) {
    option (google.api.http) = {
      get: "/access_control/api/v1/rfid/{id}"
    };
  }
  // Метод получения списка ключей.
  // Метод доступен для: admin, service, ltp_first, owner, employee
  rpc GetRfidList(GetRfidListRequest) returns (stream GetRfidListResponse) {
    option (google.api.http) = {
      get: "/access_control/api/v1/rfid/list"
    };
  }
  // Метод получения количества ключей.
  // Метод доступен для: admin, service, ltp_first, owner, employee
  rpc GetRfidCount(GetRfidCountRequest) returns (GetRfidCountResponse) {
    option (google.api.http) = {
      get: "/access_control/api/v1/rfid/count"
    };
  }
  // Метод создания ключа.
  // Метод доступен для: admin, service, ltp_first, owner, employee
  rpc PostRfid(PostRfidRequest) returns (PostRfidResponse) {
    option (google.api.http) = {
      post: "/access_control/api/v1/rfid"
      body: "*"
    };
  }
  // Метод удаления ключа.
  // Метод доступен для: admin, service, ltp_first, owner, employee
  rpc DeleteRfid(DeleteRfidRequest) returns (DeleteRfidResponse) {
    option (google.api.http) = {
      delete: "/access_control/api/v1/rfid/{id}"
    };
  }
}

// Ключ.
// # Описание модели
message Rfid {
  // Идентификатор ключа.
  // # Диапазон: 0..2147483647
  int32 id = 1;
  // Идентификатор пользователя
  google.protobuf.Int32Value user_id = 2;
  // Системное описание.
  // Обычно оставляет УК/Админ, пользователь его не видет
  google.protobuf.StringValue description = 3;
  // Идентификатор компании
  google.protobuf.Int32Value company_id = 4;
  // Идентификатор создателя
  google.protobuf.Int32Value creator_id = 5;
  // Код ключа (UID).
  // Уникальное значение.
  // # Паттерн: /^[0-9a-fA-F]{1,14}$/
  string key = 6 [(google.api.field_behavior) = REQUIRED];
  // Тип оплаты
  enum PayType {
    // Значение не указано
    PAY_TYPE_UNKNOWN = 0;
    // Платный
    PAID = 1;
    // Бесплатный
    FREE = 2;
  }
  // Тип оплаты
  PayType pay_type = 7 [(google.api.field_behavior) = REQUIRED];
  // Тип владельца ключа
  enum HolderType {
    // Значение не указано
    HOLDER_TYPE_UNKNOWN = 0;
    // Жилец
    MASTER = 1;
    // Сотрудник УК
    COMPANY = 2;
    // Ключ сотрудника ГАП
    EXTERNAL_SELLER = 3;
    // Системный ключ
    SYSTEM = 4;
  }
  // Тип владельца ключа
  HolderType holder_type = 8 [(google.api.field_behavior) = REQUIRED];
  // Дата создания.
  // # Тип: DateTime
  google.protobuf.Timestamp created_at = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Дата обновления.
  // # Тип: DateTime?
  google.protobuf.Timestamp changed_at = 10;
  // ОРПОН дома.
  // # Диапазон: 1..9223372036854775807
  int64 orpon = 11 [(google.api.field_behavior) = REQUIRED];
  // Номер квартиры.
  // # Диапазон: 1..4
  string room_number = 12 [(google.api.field_behavior) = REQUIRED];
  // Ошибка сохранения ключа.
  // Эти проверки выполняются при работе с базой данных и сторонними сервисами
  message SavingError {
    // Конфликт версий.
    // Причины:
    // - В базе хранится другая версия строки, значения changed_at отличаются
    message Conflict {}
    // Данный ключ уже существует.
    // Причины:
    // - При попытке создания ключа в системе уже существует ключ с таким же кодом
    message KeyExist {}
    // Нельзя изменить код ключа.
    // Причины:
    // - При изменении ключа нельзя менять поле key (код ключа)
    message KeyCodeCannotBeChanged {}
    // Превышено максимально допустимое количество ключей (16) для квартиры
    message ExceededQuantityOfKeysForRoom {}
    // Ключ используется на другой квартире
    message KeyIsUsed {}
    // Нельзя создавать / изменять ключ с переданным типом владельца.
    // Доступные типы владельца:
    // - Жилец (мастер)
    message HolderTypeForbidden {}
    // Причина
    oneof reason {
      // Конфликт версий
      Conflict conflict = 1;
      // Данный ключ уже существует
      KeyExist key_exist = 2;
      // Нельзя изменить код ключа
      KeyCodeCannotBeChanged key_code_cannot_be_changed = 3;
      // Превышено максимально допустимое количество ключей (16) для квартиры
      ExceededQuantityOfKeysForRoom exceeded_quantity_of_keys_for_room = 4;
      // Ключ используется на другой квартире
      KeyIsUsed key_is_used = 5;
      // Нельзя создавать / изменять ключ с переданным типом владельца
      HolderTypeForbidden holder_type_forbidden = 6;
    }
  }
}

// Запрос получения ключа
message GetRfidRequest {
  // Идентификатор ключа.
  // # Диапазон: 0..2147483647
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос получения ключа
message GetRfidResponse {
  // Ошибка
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Ключ
    Rfid data = 1;
    // Ошибка
    Error error = 2;
  }
}

// Запрос получения списка ключей
message GetRfidListRequest {
  // Фильтр
  RfidFilter filter = 1;
  // Вариант разбиения на страницы
  oneof pagination {
    // Стандартный постраничный вывод
    RfidPaging paging = 2;
  }
}

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

// Запрос получения количества ключей
message GetRfidCountRequest {
  // Фильтр
  RfidFilter filter = 1;
}

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

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

// Запрос удаления ключа
message DeleteRfidRequest {
  // Идентификатор ключа.
  // # Диапазон: 0..2147483647
  int32 id = 1 [(google.api.field_behavior) = REQUIRED];
  // Флаг принудительного удаления ключа.
  // При принудительном удалении не гарантируется удаление ключа со всех физических устройств
  bool is_force_delete = 2;
}

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

// Фильтр по ключам
message RfidFilter {
  // По типам владельца
  repeated Rfid.HolderType holder_types = 1;
  // По типам оплаты
  repeated Rfid.PayType pay_types = 2;
  // По ОРПОНам
  repeated int64 orpons = 3;
  // По номерам квартир
  repeated string room_numbers = 4;
  // По идентификаторам пользователей
  repeated int32 user_ids = 5;
  // По идентификаторам компаний
  repeated int32 company_ids = 6;
  // По кодам ключа
  repeated string keys = 7;
}

// Постраничный вывод
message RfidPaging {
  // Справочник типов значений сортировки.
  // # Тип: byte
  enum OrderByType {
    // Значение не указано
    ORDER_BY_TYPE_UNKNOWN = 0;
    // По времени создания
    CREATED_AT = 1;
    // По времени изменения
    CHANGED_AT = 2;
  }
  // Тип значения сортировки.
  // Если значение не передано, то будет взято значение по умолчанию.
  // # По умолчанию: CHANGED_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;
}
