# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: keyapis/subscription/v1/keyapis_subscription_events_v1.proto, keyapis/subscription/v1/keyapis_subscription_offer_v1.proto, keyapis/subscription/v1/keyapis_subscription_plan_v1.proto, keyapis/subscription/v1/keyapis_subscription_privilege_v1.proto, keyapis/subscription/v1/keyapis_subscription_service_v1.proto, keyapis/subscription/v1/keyapis_subscription_subscription_v1.proto, keyapis/subscription/v1/keyapis_subscription_system_v1.proto
# plugin: python-betterproto
# This file has been @generated

from collections.abc import AsyncIterator
from datetime import datetime
from typing import TYPE_CHECKING

import betterproto
import grpclib
from betterproto.grpc.grpclib_server import ServiceBase
from pydantic import model_validator
from pydantic.dataclasses import (
    dataclass,
    rebuild_dataclass,
)

if TYPE_CHECKING:
    import grpclib.server
    from betterproto.grpc.grpclib_client import MetadataLike
    from grpclib.metadata import Deadline


class PrivilegeType(betterproto.Enum):
    """Типы привилегий"""

    TYPE_UNKNOWN = 0
    """Значение не указано"""

    INTERCOM_USE = 1
    """
    Умный домофон.
     Базовые функции.
     Право доступа к разделу с домофонами и калиткаи.
     Действие.
     Закрывает услуги: get_devices_intercom
    """

    INTERCOM_OPEN = 2
    """
    Умный домофон.
     Базовые функции.
     Право использовать функционал открытия двери домофона и калитки.
     Действие.
     Закрывает услуги: post_devices_open_intercom
    """

    INTERCOM_CODE_USE = 3
    """
    Умный домофон.
     Коды.
     Право использовать функционал кодов домофонов и калиток.
     Действие.
     Закрывает услуги: get_devices_codes_intercom, post_devices_codes_intercom, delete_devices_codes_intercom
    """

    INTERCOM_RFID_USE = 4
    """
    Умный домофон.
     Ключи.
     Право использовать функционал физических ключей домофонов и калиток.
     Действие.
     Закрывает услуги: get_devices_rfids_intercom, post_devices_rfids_barrier, delete_devices_rfids_barrier
    """

    INTERCOM_EVENT_USE = 5
    """
    Умный домофон.
     События.
     Право использовать функционал журнала событий домофонов и калиток.
     Действие.
     Закрывает услуги: get_events_intercom
    """

    INTERCOM_CAMERA_USE = 6
    """
    Умный домофон.
     Камеры.
     Право использовать функционал просмотра камер и лайв видео с домофонов и калиток.
     Действие.
     Закрывает услуги: get_devices_camera_intercom
    """

    INTERCOM_CAMERA_ARCHIVE = 7
    """
    Умный домофон.
     Камеры.
     Право использовать функционал архива видео с камер домофонов и калиток.
     Действие.
     Закрывает услуги: get_video_archive_intercom
    """

    INTERCOM_CALLREDIRECT_APP = 8
    """
    Умный домофон.
     Переадресация.
     Право перенаправления входящих вызова от домофона в приложения, используется только на сервере.
     Поведение.
     Закрывает услуги: devices_call_redirect_to_mobile_app_behavior
    """

    INTERCOM_CALLREDIRECT_PSTN = 9
    """
    Умный домофон.
     Переадресация.
     Право перенаправление входящих вызовов от домофона на номера ТФОП, используется только на сервере.
     Поведение.
     Закрывает услуги: devices_call_redirect_to_pstn_behavior
    """

    INTERCOM_CALLREDIRECT_SIP = 10
    """
    Умный домофон.
     Переадресация.
     Право перенаправление входящих вызовов от домофона на номера SIP, используется только на сервере.
     Поведение.
     Закрывает услуги: devices_call_redirect_to_sip_behavior
    """

    BARRIER_USE = 11
    """
    Умный шлагбаум.
     Базовые функции.
     Право доступа к разделу шлагбаумов.
     Действие.
     Закрывает услуги: get_devices_barrier
    """

    BARRIER_OPEN = 12
    """
    Умный шлагбаум.
     Базовые функции.
     Право использовать функционала поднятия стрелы шлагбаума.
     Действие.
     Закрывает услуги: post_devices_open_barrier
    """

    BARRIER_CODE_USE = 13
    """
    Умный шлагбаум.
     Коды.
     Право использовать функционал открытия шлагбаума по звонку на короткий номер.
     Действие.
     Закрывает услуги: get_devices_codes_barrier, post_devices_codes_barrier, delete_devices_codes_barrier
    """

    BARRIER_EVENT_USE = 14
    """
    Умный шлагбаум.
     События.
     Право использовать функционал журнала событий шлагбаума.
     Действие.
     Закрывает услуги: get_events_barrier
    """

    BARRIER_CAMERA_USE = 15
    """
    Умный шлагбаум.
     Камеры.
     Право использовать функционал просмотра камер и лайв видео с шлагбаумов.
     Действие.
     Закрывает услуги: get_devices_camera_barrier
    """

    BARRIER_CAMERA_ARCHIVE = 16
    """
    Умный шлагбаум.
     Камеры.
     Право использовать функционал архива видео с камер, направленных на шлагбаум.
     Действие.
     Закрывает услуги: get_video_archive_barrier
    """

    FR_USE = 17
    """
    Распознавание лица.
     Фото.
     Право доступа к разделу распознавания лиц.
     Действие.
     Закрывает услуги: get_photo_fr_intercom, fr_intercom_access_behavior, post_photo_fr_intercom, delete_photo_fr_intercom
    """

    TELEMETRY_USE = 18
    """
    Телеметрия.
     Базовые функции.
     Право доступа к разделу показаний приборов учёта.
     Действие.
     Закрывает услуги: get_telemetry_rooms_layout
    """

    CAMERA_USE = 19
    """
    Камеры.
     Базовые функции.
     Право доступа к разделу камер и лайв видео с них.
     Действие.
     Закрывает услуги: get_devices_camera, get_events_camera, get_devices_camera_access_control_panel, get_devices_camera_barrier, get_devices_camera_intercom
    """

    CAMERA_ARCHIVE = 20
    """
    Камеры.
     Базовые функции.
     Право использовать функционал архива видео с камер видеонаблюдения.
     Действие.
     Закрывает услуги: get_video_archive, get_video_archive_access_control_panel
    """

    INTERCOM_CMS_PHONES_USE = 21
    """
    Умный домофон.
     Переадресация.
     Право приёма входящих вызовов от домофона на аналоговую трубку, используется только на сервере.
     Поведение.
     Закрывает услуги: devices_call_to_cms_phones_behavior
    """

    CAMERA_EVENT_USE = 22
    """
    Умный домофон.
     Переадресация.
     Право приёма входящих вызовов от домофона на аналоговую трубку, используется только на сервере.
     Поведение.
     Закрывает услуги: get_events_camera
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PrivilegeStateType(betterproto.Enum):
    """Типы состояний привилегий"""

    STATE_TYPE_UNKNOWN = 0
    """Значение не указано"""

    CAN_BE_PAID = 1
    """
    Услуга доступная для подключения на доме пользователя, но не активна.
     Услуга есть в доступных КВ на ОРПОН, но её нет у пользователя
    """

    NOT_PAID = 2
    """
    Услуга не оплачена и не активна.
     Услуга есть в подписке в статусе: BLOCKED
    """

    TURNS_OFF = 3
    """
    Услуга отключается, но ещё активна.
     Услуга есть в подписке в статусе: SCHEDULED_CANCELED
    """

    PROMO = 4
    """
    Услуга в промо-периоде и активна.
     Услуга есть в подписке в статусе: SETUP.
     Обычно так создают промоподписки
    """

    PAID = 5
    """
    Услуга оплачена и активна.
     Услуга есть в подписке в статусе: ACTIVE.
     Либо услуга есть в подписке с неблокируемой услугой
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PrivilegePagingOrderByType(betterproto.Enum):
    """Справочник типов значений сортировки"""

    ORDER_BY_TYPE_UNKNOWN = 0
    """Значение не указано"""

    KEY = 1
    """По уникальному ключу: orpon+flat_number+type"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PrivilegePagingDirectionType(betterproto.Enum):
    """Справочник типов направлений сортировки"""

    DIRECTION_TYPE_UNKNOWN = 0
    """Значение не указано"""

    DESC = 1
    """От большего к меньшему"""

    ASC = 2
    """От меньшего к большему"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PlanIconType(betterproto.Enum):
    """Справочник типов иконок"""

    ICON_TYPE_UNKNOWN = 0
    """Значение не указано"""

    FAST = 1
    """Быстро"""

    FACE_REC = 2
    """Распознавание лиц"""

    SAFE = 3
    """Безопасно"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PlanPagingOrderByType(betterproto.Enum):
    """Справочник типов значений сортировки"""

    ORDER_BY_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ID = 1
    """По идентификатору"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class PlanPagingDirectionType(betterproto.Enum):
    """Справочник типов направлений сортировки"""

    DIRECTION_TYPE_UNKNOWN = 0
    """Значение не указано"""

    DESC = 1
    """От большего к меньшему"""

    ASC = 2
    """От меньшего к большему"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class ServicePrivilegePagingOrderByType(betterproto.Enum):
    """
    Справочник типов значений сортировки.
     # Тип: byte
    """

    ORDER_BY_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ORPON_THEN_FLAT_NUMBER = 1
    """По ОРПОНу, затем по номеру квартиры"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class ServicePrivilegePagingDirectionType(betterproto.Enum):
    """
    Справочник типов направлений сортировки.
     # Тип: byte
    """

    DIRECTION_TYPE_UNKNOWN = 0
    """Значение не указано"""

    DESC = 1
    """От большего к меньшему"""

    ASC = 2
    """От меньшего к большему"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class OfferType(betterproto.Enum):
    """Типы коммерческих возможностей"""

    TYPE_UNKNOWN = 0
    """Значение не указано"""

    COMPANY = 1
    """
    УК.
     Услуги, которые назначаются на управляющие компанию
    """

    RTK = 2
    """
    Ростелеком.
     Услуги, которые Ростелеком подключает напрямую физическим лицам
    """

    SHARED = 3
    """
    Общая.
     Услуги, которые видят клиенты обоих типов
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class OfferStatusType(betterproto.Enum):
    """Типы статусов коммерческих возможностей"""

    STATUS_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ACTIVE = 1
    """
    Активно.
     Доступно
    """

    BLOCKED = 2
    """
    Заблокировано.
     Приостановлено
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class OfferDiscountRequirementType(betterproto.Enum):
    """Справочник условий на скидки"""

    DISCOUNT_REQUIREMENT_TYPE_UNKNOWN = 0
    """
    Значение не указано.
     Если указана цена по скидке, а условие не проставлено, скидка не отображается и не применяется
    """

    NO_CONDITIONS = 1
    """Безусловная скидка"""

    INTERNET_IS_PAID = 2
    """ШПД интернет оплачен"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class OfferPagingOrderByType(betterproto.Enum):
    """Справочник типов значений сортировки"""

    ORDER_BY_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ID = 1
    """По идентификатору"""

    PRICE = 2
    """По цене"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class OfferPagingDirectionType(betterproto.Enum):
    """Справочник типов направлений сортировки"""

    DIRECTION_TYPE_UNKNOWN = 0
    """Значение не указано"""

    DESC = 1
    """От большего к меньшему"""

    ASC = 2
    """От меньшего к большему"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class SubscriptionStatusType(betterproto.Enum):
    """Типы статусов подписки"""

    STATUS_TYPE_UNKNOWN = 0
    """Значение не указано"""

    SETUP = 1
    """
    Настроена.
     Подписка переведена в статус настройки.
     Это промо-период, либо монтажник проверяет работу оборудования.
     Услуги подписки не оплачены, но доступны для использования.
     Финальный статус
    """

    ACTIVE = 2
    """
    Активна.
     Подписка активирована.
     С этого момента считаем что нужно считать денежки.
     Услуги подписки оплачены и доступны для использования.
     Финальный статус
    """

    BLOCKED = 3
    """
    Заблокирована.
     Подписка фин. заблокирована.
     Подписка в фин. блокировке.
     Услуги подписки не оплачены и не доступны.
     Финальный статус
    """

    CANCELED = 4
    """
    Отменена.
     Подписка отменена.
     Пользователь отменил подписку.
     Услуги подписки больше не существуют и не доступны абоненту
    """

    SCHEDULED_CANCELED = 5
    """
    Запланированная отмена.
     Пользователь решил отказаться от услуги, но уже заплатил.
     Подписка запланирована к отмене, будет действовать до истечения срока действия в подписке.
     Услуги подписки оплачены и доступны для использования.
     Финальный статус
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class SubscriptionBillingType(betterproto.Enum):
    """Типы биллинга подпискии"""

    BILLING_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ASR_MRF = 1
    """
    АСР МРФ.
     Обслуживание счетов и расчёты с клиентами происходят в АСР МРФ
    """

    ASR_KEY = 2
    """
    АСР Ключ.
     Обслуживание счетов и расчёты с клиентами происходят внутри Ключа
    """

    ASR_MC = 3
    """
    АСР УК.
     Обслуживание счетов и расчёты с клиентами происходят во внешнем АСР от управляющей компании
    """

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class SubscriptionPagingOrderByType(betterproto.Enum):
    """Справочник типов значений сортировки"""

    ORDER_BY_TYPE_UNKNOWN = 0
    """Значение не указано"""

    ID = 1
    """По идентификатору"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


class SubscriptionPagingDirectionType(betterproto.Enum):
    """Справочник типов направлений сортировки"""

    DIRECTION_TYPE_UNKNOWN = 0
    """Значение не указано"""

    DESC = 1
    """От большего к меньшему"""

    ASC = 2
    """От меньшего к большему"""

    @classmethod
    def __get_pydantic_core_schema__(cls, _source_type, _handler):
        from pydantic_core import core_schema

        return core_schema.int_schema(ge=0)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Privilege(betterproto.Message):
    """Привилегия"""

    orpon: int = betterproto.int64_field(1)
    """
    ОРПОН.
     Идентификатор дома.
     Уникальный ключ: поля в порядке 1,2,3
    """

    flat_number: str = betterproto.string_field(2)
    """Номер квартиры"""

    type: "PrivilegeType" = betterproto.enum_field(3)
    """Тип привилегии"""

    state_type: "PrivilegeStateType" = betterproto.enum_field(4)
    """Состояние привилегии"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegeFilter(betterproto.Message):
    """Фильтр по привилегиям"""

    orpons: "list[int]" = betterproto.int64_field(1)
    """По ОРПОНам"""

    flat_numbers: "list[str]" = betterproto.string_field(2)
    """Номера квартир"""

    types: "list[PrivilegeType]" = betterproto.enum_field(3)
    """По типам привилегий"""

    state_types: "list[PrivilegeStateType]" = betterproto.enum_field(4)
    """По состояниям привилегий"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegeFilterValidationError(betterproto.Message):
    """
    Ошибка валидации фильтра по привилегиям.
     Эти проверки выполняются до обращения в базу данных
    """

    orpons: "PrivilegeFilterValidationErrorOrponsInvalid | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Формат ОРПОН некорректен"""

    flat_numbers: "PrivilegeFilterValidationErrorFlatNumbersInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Формат квартиры некорректен"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegeFilterValidationErrorOrponsInvalid(betterproto.Message):
    """
    Причины:
     - Формат ОРПОН некорректен;
     - Передано отрицательное значение
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegeFilterValidationErrorFlatNumbersInvalid(betterproto.Message):
    """
    Причины:
     - Формат квартиры некорректен (например, длина номера квартира более 4 знаков);
     - Номер квартиры содержит буквы
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegePaging(betterproto.Message):
    """Пагинация по привилегиям"""

    order_by_type: "PrivilegePagingOrderByType" = betterproto.enum_field(1)
    """
    Тип значения сортировки.
     По умолчанию: KEY
    """

    direction_type: "PrivilegePagingDirectionType" = betterproto.enum_field(2)
    """
    Тип направления сортировки.
     По умолчанию: DESC
    """

    limit: int = betterproto.int32_field(3)
    """
    Количество записей на страницу.
     Минимальное значение: 1.
     Максимальное значение: 100.
     По умолчанию: 20.
     Если значение 0 (не передано), то выставляем значение по умолчанию
    """

    offset: int = betterproto.int32_field(4)
    """
    Сдвиг.
     По умолчанию: 0
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegePagingValidationError(betterproto.Message):
    """
    Ошибка валидации постраничной пагинации по привилегиям.
     Эти проверки выполняются до обращения в базу данных
    """

    limit: "PrivilegePagingValidationErrorLimitInvalid | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Количество передано некорректно"""

    offset: "PrivilegePagingValidationErrorOffsetInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Сдвиг передан некорректно"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegePagingValidationErrorLimitInvalid(betterproto.Message):
    """
    Причины:
     - Значение количества < 0 или > 100
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegePagingValidationErrorOffsetInvalid(betterproto.Message):
    """
    Причины:
     - Значение сдвига < 0
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeListRequest(betterproto.Message):
    """Запрос получения привилегий"""

    filter: "PrivilegeFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "PrivilegePaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Пагинация"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeListResponse(betterproto.Message):
    """Ответ на запрос получения привилегий"""

    data: "Privilege | None" = betterproto.message_field(1, optional=True, group="type")
    """Предоставленная привилегия"""

    error: "GetPrivilegeListResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeListResponseError(betterproto.Message):
    """Ошибка запроса получения привилегий"""

    privilege_filter_validation: "PrivilegeFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации по страницам"""

    privilege_paging_validation: "PrivilegePagingValidationError | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Ошибка пагинации по страницам"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeCountRequest(betterproto.Message):
    """Запрос получения количества привилегий"""

    filter: "PrivilegeFilter" = betterproto.message_field(1)
    """Фильтр"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeCountResponse(betterproto.Message):
    """Ответ на запрос получения количества привилегий"""

    data: "int | None" = betterproto.int32_field(1, optional=True, group="type")
    """Всего привилегий"""

    error: "GetPrivilegeCountResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeCountResponseError(betterproto.Message):
    """Ошибка запроса получения количества привилегий"""

    privilege_filter_validation: "PrivilegeFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации по страницам по привилегиям"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeCheckRequest(betterproto.Message):
    """Запрос проверки предоставленной привилегии"""

    orpon: int = betterproto.int64_field(1)
    """
    ОРПОН.
     Идентификатор дома
    """

    flat_number: str = betterproto.string_field(2)
    """Номер квартиры"""

    privilege_type: "PrivilegeType" = betterproto.enum_field(3)
    """Тип привилегии"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPrivilegeCheckResponse(betterproto.Message):
    """Результат запроса метода проверки предоставленной привилегии"""

    data: "bool | None" = betterproto.bool_field(1, optional=True, group="type")
    """
    Доступна ли привилегия на квартире.
     Вернётся true если статусы:
     - PROMO;
     - PAID;
     - TURNS_OFF.
     Вернётся false если статусы:
     - NOT_PAID;
     - CAN_BE_PAID;
     - STATE_TYPE_UNKNOWN;
     - Не найден
    """

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Plan(betterproto.Message):
    """Технологический план(ТП)"""

    id: int = betterproto.int32_field(1)
    """Идентификатор"""

    title: str = betterproto.string_field(2)
    """Название"""

    description: "str | None" = betterproto.message_field(
        3, wraps=betterproto.TYPE_STRING
    )
    """Описание"""

    created_at: datetime = betterproto.message_field(4)
    """
    Дата создания записи.
     Заполняется сервером
    """

    changed_at: datetime = betterproto.message_field(5)
    """
    Дата последнего изменения.
     Заполняется и обновляется сервером.
     Заполняется при создании и изменении.
     Является версией объекта
    """

    parent_ids: "list[int]" = betterproto.int32_field(6)
    """Идентификаторы родительских технологических планов(ТП)"""

    rf_ids: "list[int]" = betterproto.int32_field(7)
    """Идентификаторы регионов, в которых доступен технологический план(ТП)"""

    summary: "str | None" = betterproto.message_field(8, wraps=betterproto.TYPE_STRING)
    """Краткое описание"""

    icon_type: "PlanIconType" = betterproto.enum_field(9)
    """Тип иконки"""

    option_descriptions: "list[PlanOptionDescription]" = betterproto.message_field(10)
    """Описание опций"""

    privilege_types: "list[PrivilegeType]" = betterproto.enum_field(11)
    """
    Привилегии.
     Массив услуг доступных по технологическому плану
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanOptionDescription(betterproto.Message):
    """Описание опции"""

    icon_type: "PlanIconType" = betterproto.enum_field(1)
    """Тип иконки"""

    title: str = betterproto.string_field(2)
    """Название"""

    summary: "str | None" = betterproto.message_field(3, wraps=betterproto.TYPE_STRING)
    """Краткое описание"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanFilter(betterproto.Message):
    """Фильтр по технологическим планам"""

    text: "str | None" = betterproto.message_field(1, wraps=betterproto.TYPE_STRING)
    """
    По тексту.
     Если значение не передано то поиск по нему не производится.
     # Поиск производится по полям:
     # - Название;
     # - Описание;
     # - Краткое описание
    """

    rf_ids: "list[int]" = betterproto.int32_field(2)
    """По идентификаторам регионов"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanFilterValidationError(betterproto.Message):
    """
    Ошибки валидации фильтра по технологическим планам.
     Эти проверки выполняются до обращения в базу данных
    """

    text: "PlanFilterValidationErrorTextInvalid | None" = betterproto.message_field(
        1, optional=True, group="reason"
    )
    """Текст передан некорректно"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanFilterValidationErrorTextInvalid(betterproto.Message):
    """
    Причины:
     - Длина текста < 3 символов и >= 64
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanPaging(betterproto.Message):
    """Пагинация по технологическим планам"""

    order_by_type: "PlanPagingOrderByType" = betterproto.enum_field(1)
    """
    Тип значения сортировки.
     По умолчанию: ID
    """

    direction_type: "PlanPagingDirectionType" = betterproto.enum_field(2)
    """
    Тип направления сортировки.
     По умолчанию: DESC
    """

    limit: int = betterproto.int32_field(3)
    """
    Количество записей на страницу.
     Минимальное значение: 1.
     Максимальное значение: 100.
     По умолчанию: 20.
     Если значение 0 (не передано), то выставляем значение по умолчанию
    """

    offset: int = betterproto.int32_field(4)
    """
    Сдвиг.
     По умолчанию: 0
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanPagingValidationError(betterproto.Message):
    """
    Ошибка валидации постраничной пагинации по технологическим планам.
     Эти проверки выполняются до обращения в базу данных
    """

    limit: "PlanPagingValidationErrorLimitInvalid | None" = betterproto.message_field(
        1, optional=True, group="reason"
    )
    """Количество передано некорректно"""

    offset: "PlanPagingValidationErrorOffsetInvalid | None" = betterproto.message_field(
        2, optional=True, group="reason"
    )
    """Сдвиг передан некорректно"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanPagingValidationErrorLimitInvalid(betterproto.Message):
    """
    Причины:
     - Значение количества < 0 или > 100
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PlanPagingValidationErrorOffsetInvalid(betterproto.Message):
    """
    Причины:
     - Значение сдвига < 0
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanRequest(betterproto.Message):
    """Запрос получения технологического плана"""

    id: int = betterproto.int32_field(1)
    """Идентификатор"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanResponse(betterproto.Message):
    """Ответ на запрос получения технологического плана"""

    data: "Plan | None" = betterproto.message_field(1, optional=True, group="type")
    """Технологический план"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanListRequest(betterproto.Message):
    """Запрос получения технологических планов"""

    filter: "PlanFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "PlanPaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Пагинация"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanListResponse(betterproto.Message):
    """Ответ на запрос получения технологических планов"""

    data: "Plan | None" = betterproto.message_field(1, optional=True, group="type")
    """Технологический план"""

    error: "GetPlanListResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanListResponseError(betterproto.Message):
    """Ошибка запроса получения технологических планов"""

    plan_filter_validation: "PlanFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации"""

    plan_paging_validation: "PlanPagingValidationError | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Ошибка пагинации по страницам"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanCountRequest(betterproto.Message):
    """Запрос получения количества технологических планов"""

    filter: "PlanFilter" = betterproto.message_field(1)
    """Фильтр"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanCountResponse(betterproto.Message):
    """Ответ на запрос получения количества технологических планов"""

    data: "int | None" = betterproto.int32_field(1, optional=True, group="type")
    """Всего технологических планов"""

    error: "GetPlanCountResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetPlanCountResponseError(betterproto.Message):
    """Ошибка запроса получения количества технологических планов"""

    plan_filter_validation: "PlanFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Sevice(betterproto.Message):
    """
    Услуга.
     TODO: deprecated
    """

    name: str = betterproto.string_field(1)
    """Название услуги на английском"""

    is_active: bool = betterproto.bool_field(2)
    """
    Доступна ли услуга на квартире.
     Вернётся true если статусы привилегии:
     - PROMO;
     - PAID;
     - TURNS_OFF.
     Вернётся false если статусы привилегии:
     - NOT_PAID;
     - CAN_BE_PAID;
     - STATE_TYPE_UNKNOWN;
     - Не найден (нет на кваритре, но есть в справочнике привилегий)
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Service(betterproto.Message):
    """Услуга"""

    name: str = betterproto.string_field(1)
    """Название услуги на английском"""

    is_active: bool = betterproto.bool_field(2)
    """
    Доступна ли услуга на квартире.
     Вернётся true если статусы привилегии:
     - PROMO;
     - PAID;
     - TURNS_OFF.
     Вернётся false если статусы привилегии:
     - NOT_PAID;
     - CAN_BE_PAID;
     - STATE_TYPE_UNKNOWN;
     - Не найден (нет на кваритре, но есть в справочнике привилегий)
    """

    orpon: "int | None" = betterproto.message_field(3, wraps=betterproto.TYPE_INT64)
    """ОРПОН дома"""

    flat_number: "str | None" = betterproto.message_field(
        4, wraps=betterproto.TYPE_STRING
    )
    """Номер квартиры"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class ServiceKind(betterproto.Message):
    """Элемент справочника видов услуг"""

    id: int = betterproto.int32_field(1)
    """Идентификатор услуги"""

    category: str = betterproto.string_field(2)
    """
    Категория услуги.
     Аналогично V1ServiceDto.type
    """

    name: str = betterproto.string_field(3)
    """Название услуги на английском"""

    title: str = betterproto.string_field(4)
    """Название услуги"""

    description: "str | None" = betterproto.message_field(
        5, wraps=betterproto.TYPE_STRING
    )
    """Описание услуги"""

    parent_id: "int | None" = betterproto.message_field(6, wraps=betterproto.TYPE_INT32)
    """Идентификатор родительской услуги"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServiceListRequest(betterproto.Message):
    """Запрос получения списка услуг квартиры"""

    orpon: int = betterproto.int64_field(1)
    """
    ОРПОН.
     Идентификатор дома
    """

    flat_number: str = betterproto.string_field(2)
    """Номер квартиры"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServiceListResponse(betterproto.Message):
    """Результат запроса получения списка услуг квартиры"""

    data: "Sevice | None" = betterproto.message_field(1, optional=True, group="type")
    """Услуга"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServicePrivilegeListRequest(betterproto.Message):
    """Запрос получения списка услуг"""

    filter: "ServicePrivilegeFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "ServicePrivilegePaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Стандартный постраничный вывод"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServicePrivilegeListResponse(betterproto.Message):
    """Результат запроса получения списка услуг"""

    data: "Service | None" = betterproto.message_field(1, optional=True, group="type")
    """Услуга"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServicePrivilegeCountRequest(betterproto.Message):
    """Запрос получения количества услуг"""

    filter: "ServicePrivilegeFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "ServicePrivilegePaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Стандартный постраничный вывод"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServicePrivilegeCountResponse(betterproto.Message):
    """Результат запроса получения количества услуг"""

    data: "int | None" = betterproto.int32_field(1, optional=True, group="type")
    """Количество"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class ServicePrivilegeFilter(betterproto.Message):
    """Фильтр услуг"""

    orpons: "list[int]" = betterproto.int64_field(1)
    """По ОРПОН"""

    flat_numbers: "list[str]" = betterproto.string_field(2)
    """По номеру квартиры"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class ServicePrivilegePaging(betterproto.Message):
    """Постраничный вывод"""

    order_by_type: "ServicePrivilegePagingOrderByType" = betterproto.enum_field(1)
    """
    Тип значения сортировки.
     Если значение не передано, то будет взято значение по умолчанию.
     # По умолчанию: ORPON_THEN_FLAT_NUMBER
    """

    direction_type: "ServicePrivilegePagingDirectionType" = betterproto.enum_field(2)
    """
    Тип направления сортировки.
     # По умолчанию: DESC
    """

    limit: int = betterproto.int32_field(3)
    """
    Количество записей на страницу.
     Если значение 0 (не передано), то будет взято значение по умолчанию.
     # Диапазон: 0..100.
     # По умолчанию: 20
    """

    offset: int = betterproto.int32_field(4)
    """
    Сдвиг.
     # Диапазон: 0..2147483647
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServiceKindListRequest(betterproto.Message):
    """Запрос получения справочника видов услуг"""

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetServiceKindListResponse(betterproto.Message):
    """Результат запроса получения справочника видов услуг"""

    data: "ServiceKind | None" = betterproto.message_field(
        1, optional=True, group="type"
    )
    """Элемент справочника услуг"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSystemStatusRequest(betterproto.Message):
    """Запрос проверки доступности сервиса"""

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSystemStatusResponse(betterproto.Message):
    """Ответ на запрос проверки доступности сервиса"""

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Offer(betterproto.Message):
    """Коммерческая возможность(КВ)"""

    id: int = betterproto.int32_field(1)
    """Идентификатор"""

    type: "OfferType" = betterproto.enum_field(2)
    """Тип коммерческой возможности"""

    orpon: int = betterproto.int64_field(3)
    """
    ОРПОН.
     Идентификатор дома
    """

    company_id: "int | None" = betterproto.message_field(
        4, wraps=betterproto.TYPE_INT32
    )
    """Идентификатор компании"""

    plan_id: int = betterproto.int32_field(5)
    """Идентификатор технологического плана"""

    is_enable_auto_subscribe: bool = betterproto.bool_field(6)
    """Подключать ли автоматическую подписку"""

    status_type: "OfferStatusType" = betterproto.enum_field(7)
    """Тип статуса заказа"""

    price: "float | None" = betterproto.message_field(8, wraps=betterproto.TYPE_DOUBLE)
    """Цена"""

    is_digital_way: bool = betterproto.bool_field(9)
    """Признак принадлежности к цифровому пути"""

    created_at: datetime = betterproto.message_field(10)
    """
    Дата создания записи.
     Заполняется сервером
    """

    changed_at: datetime = betterproto.message_field(11)
    """
    Дата последнего изменения.
     Заполняется и обновляется сервером.
     Заполняется при создании и изменении.
     Является версией объекта
    """

    offer_url: "str | None" = betterproto.message_field(
        12, wraps=betterproto.TYPE_STRING
    )
    """
    Адрес размещения офферты.
     Полный url до файла
    """

    plan: "Plan" = betterproto.message_field(13)
    """
    Снапшот состояния технологического плана на момент создания предложения.
     В данный момент это ссылка в базе на запись, в будущем это будет снапшот
    """

    discount_price: "float | None" = betterproto.message_field(
        14, wraps=betterproto.TYPE_DOUBLE
    )
    """Цена по скидке"""

    discount_requirement_types: "list[OfferDiscountRequirementType]" = (
        betterproto.enum_field(15)
    )
    """
    Условия на скидку.
     Если условий много то для срабатывания должны выполнять все условия
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferFilter(betterproto.Message):
    """Фильтр по коммерческим возможностям"""

    types: "list[OfferType]" = betterproto.enum_field(1)
    """По типам"""

    orpons: "list[int]" = betterproto.int64_field(2)
    """По ОРПОНам"""

    company_ids: "list[int]" = betterproto.int32_field(3)
    """По идентификаторам компаний"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferFilterValidationError(betterproto.Message):
    """
    Ошибки валидации фильтра по коммерческим возможностям.
     Эти проверки выполняются до обращения в базу данных
    """

    orpons: "OfferFilterValidationErrorOrponsInvalid | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Формат ОРПОН некорректен"""

    company_ids: "OfferFilterValidationErrorCompanyIdsInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Формат идентификатора компании некорректен"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferFilterValidationErrorOrponsInvalid(betterproto.Message):
    """
    - Формат ОРПОН некорректен;
     - ОРПОН передан некорректно, к примеру, значение <= 1
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferFilterValidationErrorCompanyIdsInvalid(betterproto.Message):
    """
    Причины:
     - Формат идентификатора компании некорректен;
     - Идентификатора компании передан некорректно, к примеру, значение <= 1
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferPaging(betterproto.Message):
    """Пагинация по коммерческим возможностям"""

    order_by_type: "OfferPagingOrderByType" = betterproto.enum_field(1)
    """
    Тип значения сортировки.
     По умолчанию: ID
    """

    direction_type: "OfferPagingDirectionType" = betterproto.enum_field(2)
    """
    Тип направления сортировки.
     По умолчанию: DESC
    """

    limit: int = betterproto.int32_field(3)
    """
    Количество записей на страницу.
     Минимальное значение: 1.
     Максимальное значение: 100.
     По умолчанию: 20.
     Если значение 0 (не передано), то выставляем значение по умолчанию
    """

    offset: int = betterproto.int32_field(4)
    """
    Сдвиг.
     По умолчанию: 0
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferPagingValidationError(betterproto.Message):
    """
    Ошибка валидации постраничной пагинации по коммерческим возможностям.
     Эти проверки выполняются до обращения в базу данных
    """

    limit: "OfferPagingValidationErrorLimitInvalid | None" = betterproto.message_field(
        1, optional=True, group="reason"
    )
    """Количество передано некорректно"""

    offset: "OfferPagingValidationErrorOffsetInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Сдвиг передан некорректно"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferPagingValidationErrorLimitInvalid(betterproto.Message):
    """
    Причины:
     - Значение количества < 0 или > 100
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class OfferPagingValidationErrorOffsetInvalid(betterproto.Message):
    """
    Причины:
     - Значение сдвига < 0
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferRequest(betterproto.Message):
    """Запрос получения коммерческой возможности"""

    id: str = betterproto.string_field(1)
    """Идентификатор коммерческой возможности"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferResponse(betterproto.Message):
    """Ответ на запрос получения коммерческой возможности"""

    data: "Offer | None" = betterproto.message_field(1, optional=True, group="type")
    """Коммерческая возможность"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferListRequest(betterproto.Message):
    """Запрос получения коммерческих возможностей"""

    filter: "OfferFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "OfferPaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Пагинация"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferListResponse(betterproto.Message):
    """Ответ на запрос получения коммерческих возможностей"""

    data: "Offer | None" = betterproto.message_field(1, optional=True, group="type")
    """Коммерческая возможность"""

    error: "GetOfferListResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferListResponseError(betterproto.Message):
    """Ошибка запроса получения коммерческих возможностей"""

    offer_filter_validation: "OfferFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации"""

    offer_paging_validation: "OfferPagingValidationError | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Ошибка пагинации по страницам"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferCountRequest(betterproto.Message):
    """Запрос получения количества коммерческих возможностей"""

    filter: "OfferFilter" = betterproto.message_field(1)
    """Фильтр"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferCountResponse(betterproto.Message):
    """Ответ на запрос получения количества коммерческих возможностей"""

    data: "int | None" = betterproto.int32_field(1, optional=True, group="type")
    """Всего коммерческих возможностей"""

    error: "GetOfferCountResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetOfferCountResponseError(betterproto.Message):
    """Ошибка запроса получения количества коммерческих возможностей"""

    offer_filter_validation: "OfferFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class CommercialOfferCmsAvailableTask(betterproto.Message):
    """
    Событие о появлении коммерческой возможности с услугой аналоговой трубки.
     Очередь key.subscription.cms_available
    """

    request_id: str = betterproto.string_field(1)
    """Идентификатор запроса"""

    orpon_id: int = betterproto.int64_field(2)
    """Идентификатор ОРПОН дома"""

    privileged_room_numbers: "list[str]" = betterproto.string_field(3)
    """
    Номера квартир, с привилегией "Аналоговая трубка" в статусе: Оплачено, Промо, Отключается
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class CommercialOfferCmsUnavailableTask(betterproto.Message):
    """
    Событие о прекращении действия коммерческой возможности с услугой аналоговой трубки.
     Очередь key.subscription.cms_unavailable
    """

    request_id: str = betterproto.string_field(1)
    """Идентификатор запроса"""

    orpon_id: int = betterproto.int64_field(2)
    """Идентификатор ОРПОН дома"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class PrivilegeStateChangeTask(betterproto.Message):
    """
    Сообщение об изменении состояния привилегии.
     Очередь key.subscription.privilege_state_change
    """

    request_id: str = betterproto.string_field(1)
    """Идентификатор запроса"""

    orpon_id: int = betterproto.int64_field(2)
    """Идентификатор ОРПОН дома"""

    room_number: str = betterproto.string_field(3)
    """Номер квартиры"""

    privilege_type: "PrivilegeType" = betterproto.enum_field(4)
    """Тип привилегии"""

    state_type: "PrivilegeStateType" = betterproto.enum_field(5)
    """Тип состояния привилегий"""

    previous_state_type: "PrivilegeStateType" = betterproto.enum_field(6)
    """Предыдущий тип состояния привилегии"""

    updated_at: datetime = betterproto.message_field(7)
    """Дата обновления состояния привилегии"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class CmsInitTask(betterproto.Message):
    """
    Событие инициализации сценария обновления статусов аналоговых трубок.
     Очередь key.subscription.cms_init
    """

    request_id: str = betterproto.string_field(1)
    """Идентификатор запроса"""

    orpons: "list[int]" = betterproto.int64_field(2)
    """ОРПОНы домов"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class Subscription(betterproto.Message):
    """Подписка"""

    id: str = betterproto.string_field(1)
    """
    Идентификатор.
     Может быть явно задан при создании.
     Тип: Guid
    """

    orpon: int = betterproto.int64_field(2)
    """
    ОРПОН.
     Идентификатор дома
    """

    flat_number: str = betterproto.string_field(3)
    """Номер квартиры"""

    offer_id: int = betterproto.int32_field(4)
    """
    Идентификатор коммерческой возможности(КВ).
     Заполняется сервером на основе идентификатора из технологического плана(ТП)
    """

    status_type: "SubscriptionStatusType" = betterproto.enum_field(5)
    """
    Cтатус подписки.
     При создании может быть: SETUP, ACTIVE
    """

    previous_status_type: "SubscriptionStatusType" = betterproto.enum_field(6)
    """
    Предыдущий статус подписки.
     В справочник входят только финальные статусы.
     Заполняется сервером при изменении статусов
    """

    price: "float | None" = betterproto.message_field(7, wraps=betterproto.TYPE_DOUBLE)
    """Цена"""

    created_at: datetime = betterproto.message_field(8)
    """
    Дата создания записи.
     Заполняется сервером
    """

    changed_at: datetime = betterproto.message_field(9)
    """
    Дата последнего изменения.
     Заполняется и обновляется сервером.
     Заполняется при создании и изменении.
     Является версией объекта
    """

    is_enable_auto_subscribe: bool = betterproto.bool_field(10)
    """
    Признак для определения автоподписок.
     Редактировать флаг запрещено.
     Проставляется сервером в true при создании через задачу на автоподписку
    """

    billing_type: "SubscriptionBillingType" = betterproto.enum_field(11)
    """Тип биллинга"""

    expired_at: datetime = betterproto.message_field(12)
    """
    Срок действия.
     Проставляется при создании
    """

    parent_id: "str | None" = betterproto.message_field(
        13, wraps=betterproto.TYPE_STRING
    )
    """
    Идентификатор подписки, в зависимости от которой подключена данная.
     Заполняется в подписках на опции.
     Тип: Guid
    """

    account: "int | None" = betterproto.message_field(14, wraps=betterproto.TYPE_INT64)
    """Аккаунт"""

    offer: "Offer" = betterproto.message_field(15)
    """
    Снапшот состояния коммерческой возможности на момент создания подписки.
     В данный момент это ссылка в базе на запись, в будущем это будет снапшот
    """

    discount_price: "float | None" = betterproto.message_field(
        16, wraps=betterproto.TYPE_DOUBLE
    )
    """
    Цена по скидки.
     Заполнена если оплата подписки прошла по скидке, иначе очищается
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionFilter(betterproto.Message):
    """Фильтр подписок"""

    orpons: "list[int]" = betterproto.int64_field(1)
    """По ОРПОНам"""

    flat_numbers: "list[str]" = betterproto.string_field(2)
    """По номерам квартир"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionFilterValidationError(betterproto.Message):
    """
    Ошибки валидации фильтра по подпискам.
     Эти проверки выполняются до обращения в базу данных
    """

    orpons: "SubscriptionFilterValidationErrorOrponsInvalid | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Формат ОРПОН некорректен"""

    flat_numbers: "SubscriptionFilterValidationErrorFlatNumbersInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Формат квартиры некорректен"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionFilterValidationErrorOrponsInvalid(betterproto.Message):
    """
    Причины:
     - Формат ОРПОН некорректен;
     - ОРПОН передан некорректно, к примеру, значение <= 1
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionFilterValidationErrorFlatNumbersInvalid(betterproto.Message):
    """
    Причины:
     - Формат квартиры некорректен (например, длина номера квартира более 4 знаков или отрицательное значение)
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionPaging(betterproto.Message):
    """Пагинация по подпискам"""

    order_by_type: "SubscriptionPagingOrderByType" = betterproto.enum_field(1)
    """
    Тип значения сортировки.
     По умолчанию: ID
    """

    direction_type: "SubscriptionPagingDirectionType" = betterproto.enum_field(2)
    """
    Тип направления сортировки.
     По умолчанию: DESC
    """

    limit: int = betterproto.int32_field(3)
    """
    Количество записей на страницу.
     Минимальное значение: 1.
     Максимальное значение: 100.
     По умолчанию: 20.
     Если значение 0 (не передано), то выставляем значение по умолчанию
    """

    offset: int = betterproto.int32_field(4)
    """
    Сдвиг.
     По умолчанию: 0
    """


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionPagingValidationError(betterproto.Message):
    """
    Ошибка валидации постраничной пагинации по подпискам.
     Эти проверки выполняются до обращения в базу данных
    """

    limit: "SubscriptionPagingValidationErrorLimitInvalid | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Количество передано некорректно"""

    offset: "SubscriptionPagingValidationErrorOffsetInvalid | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Сдвиг передан некорректно"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionPagingValidationErrorLimitInvalid(betterproto.Message):
    """
    Причины:
     - Значение количества < 0 или > 100
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class SubscriptionPagingValidationErrorOffsetInvalid(betterproto.Message):
    """
    Причины:
     - Значение сдвига < 0
    """

    pass


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionRequest(betterproto.Message):
    """Запрос получения подписки"""

    id: str = betterproto.string_field(1)
    """Идентификатор подписки"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionResponse(betterproto.Message):
    """Ответ на запрос получения подписки"""

    data: "Subscription | None" = betterproto.message_field(
        1, optional=True, group="type"
    )
    """Подписка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionListRequest(betterproto.Message):
    """Запрос получения списка подписок"""

    filter: "SubscriptionFilter" = betterproto.message_field(1)
    """Фильтр"""

    paging: "SubscriptionPaging | None" = betterproto.message_field(
        2, optional=True, group="pagination"
    )
    """Пагинация"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionListResponse(betterproto.Message):
    """Ответ на запрос получения списка подписок"""

    data: "Subscription | None" = betterproto.message_field(
        1, optional=True, group="type"
    )
    """Подписка"""

    error: "GetSubscriptionListResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionListResponseError(betterproto.Message):
    """Ошибка запроса получения списка подписки"""

    subscription_filter_validation: "SubscriptionFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации"""

    subscription_paging_validation: "SubscriptionPagingValidationError | None" = (
        betterproto.message_field(2, optional=True, group="reason")
    )
    """Ошибка пагинации  по страницам"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionCountRequest(betterproto.Message):
    """Запрос получения количества подписок"""

    filter: "SubscriptionFilter" = betterproto.message_field(1)
    """Фильтр"""


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionCountResponse(betterproto.Message):
    """Ответ на запрос получения количества подписок"""

    data: "int | None" = betterproto.int32_field(1, optional=True, group="type")
    """Всего подписок"""

    error: "GetSubscriptionCountResponseError | None" = betterproto.message_field(
        2, optional=True, group="type"
    )
    """Ошибка"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


@dataclass(eq=False, repr=False, config={"extra": "forbid"})
class GetSubscriptionCountResponseError(betterproto.Message):
    """Ошибка запроса получения количества подписок"""

    subscription_filter_validation: "SubscriptionFilterValidationError | None" = (
        betterproto.message_field(1, optional=True, group="reason")
    )
    """Ошибка фильтрации подписок"""

    @model_validator(mode="after")
    def check_oneof(cls, values):
        return cls._validate_field_groups(values)


class PrivilegeServiceStub(betterproto.ServiceStub):
    async def get_privilege_list(
        self,
        get_privilege_list_request: "GetPrivilegeListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetPrivilegeListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeList",
            get_privilege_list_request,
            GetPrivilegeListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_privilege_count(
        self,
        get_privilege_count_request: "GetPrivilegeCountRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetPrivilegeCountResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeCount",
            get_privilege_count_request,
            GetPrivilegeCountResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_privilege_check(
        self,
        get_privilege_check_request: "GetPrivilegeCheckRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetPrivilegeCheckResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeCheck",
            get_privilege_check_request,
            GetPrivilegeCheckResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class PlanServiceStub(betterproto.ServiceStub):
    async def get_plan(
        self,
        get_plan_request: "GetPlanRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetPlanResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.PlanService/GetPlan",
            get_plan_request,
            GetPlanResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_plan_list(
        self,
        get_plan_list_request: "GetPlanListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetPlanListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.PlanService/GetPlanList",
            get_plan_list_request,
            GetPlanListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_plan_count(
        self,
        get_plan_count_request: "GetPlanCountRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetPlanCountResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.PlanService/GetPlanCount",
            get_plan_count_request,
            GetPlanCountResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class ServiceServiceStub(betterproto.ServiceStub):
    async def get_service_list(
        self,
        get_service_list_request: "GetServiceListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetServiceListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.ServiceService/GetServiceList",
            get_service_list_request,
            GetServiceListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_service_privilege_list(
        self,
        get_service_privilege_list_request: "GetServicePrivilegeListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetServicePrivilegeListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.ServiceService/GetServicePrivilegeList",
            get_service_privilege_list_request,
            GetServicePrivilegeListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_service_privilege_count(
        self,
        get_service_privilege_count_request: "GetServicePrivilegeCountRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetServicePrivilegeCountResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.ServiceService/GetServicePrivilegeCount",
            get_service_privilege_count_request,
            GetServicePrivilegeCountResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_service_kind_list(
        self,
        get_service_kind_list_request: "GetServiceKindListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetServiceKindListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.ServiceService/GetServiceKindList",
            get_service_kind_list_request,
            GetServiceKindListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response


class SystemServiceStub(betterproto.ServiceStub):
    async def get_system_status(
        self,
        get_system_status_request: "GetSystemStatusRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetSystemStatusResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.SystemService/GetSystemStatus",
            get_system_status_request,
            GetSystemStatusResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class OfferServiceStub(betterproto.ServiceStub):
    async def get_offer(
        self,
        get_offer_request: "GetOfferRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetOfferResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.OfferService/GetOffer",
            get_offer_request,
            GetOfferResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_offer_list(
        self,
        get_offer_list_request: "GetOfferListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetOfferListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.OfferService/GetOfferList",
            get_offer_list_request,
            GetOfferListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_offer_count(
        self,
        get_offer_count_request: "GetOfferCountRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetOfferCountResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.OfferService/GetOfferCount",
            get_offer_count_request,
            GetOfferCountResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class SubscriptionServiceStub(betterproto.ServiceStub):
    async def get_subscription(
        self,
        get_subscription_request: "GetSubscriptionRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetSubscriptionResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.SubscriptionService/GetSubscription",
            get_subscription_request,
            GetSubscriptionResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_subscription_list(
        self,
        get_subscription_list_request: "GetSubscriptionListRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "AsyncIterator[GetSubscriptionListResponse]":
        async for response in self._unary_stream(
            "/keyapis.subscription.v1.SubscriptionService/GetSubscriptionList",
            get_subscription_list_request,
            GetSubscriptionListResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def get_subscription_count(
        self,
        get_subscription_count_request: "GetSubscriptionCountRequest",
        *,
        timeout: "float | None" = None,
        deadline: "Deadline | None" = None,
        metadata: "MetadataLike | None" = None
    ) -> "GetSubscriptionCountResponse":
        return await self._unary_unary(
            "/keyapis.subscription.v1.SubscriptionService/GetSubscriptionCount",
            get_subscription_count_request,
            GetSubscriptionCountResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class PrivilegeServiceBase(ServiceBase):

    async def get_privilege_list(
        self, get_privilege_list_request: "GetPrivilegeListRequest"
    ) -> "AsyncIterator[GetPrivilegeListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetPrivilegeListResponse()

    async def get_privilege_count(
        self, get_privilege_count_request: "GetPrivilegeCountRequest"
    ) -> "GetPrivilegeCountResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_privilege_check(
        self, get_privilege_check_request: "GetPrivilegeCheckRequest"
    ) -> "GetPrivilegeCheckResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_privilege_list(
        self,
        stream: "grpclib.server.Stream[GetPrivilegeListRequest, GetPrivilegeListResponse]",
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_privilege_list,
            stream,
            request,
        )

    async def __rpc_get_privilege_count(
        self,
        stream: "grpclib.server.Stream[GetPrivilegeCountRequest, GetPrivilegeCountResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_privilege_count(request)
        await stream.send_message(response)

    async def __rpc_get_privilege_check(
        self,
        stream: "grpclib.server.Stream[GetPrivilegeCheckRequest, GetPrivilegeCheckResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_privilege_check(request)
        await stream.send_message(response)

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeList": grpclib.const.Handler(
                self.__rpc_get_privilege_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetPrivilegeListRequest,
                GetPrivilegeListResponse,
            ),
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeCount": grpclib.const.Handler(
                self.__rpc_get_privilege_count,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPrivilegeCountRequest,
                GetPrivilegeCountResponse,
            ),
            "/keyapis.subscription.v1.PrivilegeService/GetPrivilegeCheck": grpclib.const.Handler(
                self.__rpc_get_privilege_check,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPrivilegeCheckRequest,
                GetPrivilegeCheckResponse,
            ),
        }


class PlanServiceBase(ServiceBase):

    async def get_plan(self, get_plan_request: "GetPlanRequest") -> "GetPlanResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_plan_list(
        self, get_plan_list_request: "GetPlanListRequest"
    ) -> "AsyncIterator[GetPlanListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetPlanListResponse()

    async def get_plan_count(
        self, get_plan_count_request: "GetPlanCountRequest"
    ) -> "GetPlanCountResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_plan(
        self, stream: "grpclib.server.Stream[GetPlanRequest, GetPlanResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_plan(request)
        await stream.send_message(response)

    async def __rpc_get_plan_list(
        self, stream: "grpclib.server.Stream[GetPlanListRequest, GetPlanListResponse]"
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_plan_list,
            stream,
            request,
        )

    async def __rpc_get_plan_count(
        self, stream: "grpclib.server.Stream[GetPlanCountRequest, GetPlanCountResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_plan_count(request)
        await stream.send_message(response)

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.PlanService/GetPlan": grpclib.const.Handler(
                self.__rpc_get_plan,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPlanRequest,
                GetPlanResponse,
            ),
            "/keyapis.subscription.v1.PlanService/GetPlanList": grpclib.const.Handler(
                self.__rpc_get_plan_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetPlanListRequest,
                GetPlanListResponse,
            ),
            "/keyapis.subscription.v1.PlanService/GetPlanCount": grpclib.const.Handler(
                self.__rpc_get_plan_count,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPlanCountRequest,
                GetPlanCountResponse,
            ),
        }


class ServiceServiceBase(ServiceBase):

    async def get_service_list(
        self, get_service_list_request: "GetServiceListRequest"
    ) -> "AsyncIterator[GetServiceListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetServiceListResponse()

    async def get_service_privilege_list(
        self, get_service_privilege_list_request: "GetServicePrivilegeListRequest"
    ) -> "AsyncIterator[GetServicePrivilegeListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetServicePrivilegeListResponse()

    async def get_service_privilege_count(
        self, get_service_privilege_count_request: "GetServicePrivilegeCountRequest"
    ) -> "GetServicePrivilegeCountResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_service_kind_list(
        self, get_service_kind_list_request: "GetServiceKindListRequest"
    ) -> "AsyncIterator[GetServiceKindListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetServiceKindListResponse()

    async def __rpc_get_service_list(
        self,
        stream: "grpclib.server.Stream[GetServiceListRequest, GetServiceListResponse]",
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_service_list,
            stream,
            request,
        )

    async def __rpc_get_service_privilege_list(
        self,
        stream: "grpclib.server.Stream[GetServicePrivilegeListRequest, GetServicePrivilegeListResponse]",
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_service_privilege_list,
            stream,
            request,
        )

    async def __rpc_get_service_privilege_count(
        self,
        stream: "grpclib.server.Stream[GetServicePrivilegeCountRequest, GetServicePrivilegeCountResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_service_privilege_count(request)
        await stream.send_message(response)

    async def __rpc_get_service_kind_list(
        self,
        stream: "grpclib.server.Stream[GetServiceKindListRequest, GetServiceKindListResponse]",
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_service_kind_list,
            stream,
            request,
        )

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.ServiceService/GetServiceList": grpclib.const.Handler(
                self.__rpc_get_service_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetServiceListRequest,
                GetServiceListResponse,
            ),
            "/keyapis.subscription.v1.ServiceService/GetServicePrivilegeList": grpclib.const.Handler(
                self.__rpc_get_service_privilege_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetServicePrivilegeListRequest,
                GetServicePrivilegeListResponse,
            ),
            "/keyapis.subscription.v1.ServiceService/GetServicePrivilegeCount": grpclib.const.Handler(
                self.__rpc_get_service_privilege_count,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetServicePrivilegeCountRequest,
                GetServicePrivilegeCountResponse,
            ),
            "/keyapis.subscription.v1.ServiceService/GetServiceKindList": grpclib.const.Handler(
                self.__rpc_get_service_kind_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetServiceKindListRequest,
                GetServiceKindListResponse,
            ),
        }


class SystemServiceBase(ServiceBase):

    async def get_system_status(
        self, get_system_status_request: "GetSystemStatusRequest"
    ) -> "GetSystemStatusResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_system_status(
        self,
        stream: "grpclib.server.Stream[GetSystemStatusRequest, GetSystemStatusResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_system_status(request)
        await stream.send_message(response)

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.SystemService/GetSystemStatus": grpclib.const.Handler(
                self.__rpc_get_system_status,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetSystemStatusRequest,
                GetSystemStatusResponse,
            ),
        }


class OfferServiceBase(ServiceBase):

    async def get_offer(
        self, get_offer_request: "GetOfferRequest"
    ) -> "GetOfferResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_offer_list(
        self, get_offer_list_request: "GetOfferListRequest"
    ) -> "AsyncIterator[GetOfferListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetOfferListResponse()

    async def get_offer_count(
        self, get_offer_count_request: "GetOfferCountRequest"
    ) -> "GetOfferCountResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_offer(
        self, stream: "grpclib.server.Stream[GetOfferRequest, GetOfferResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_offer(request)
        await stream.send_message(response)

    async def __rpc_get_offer_list(
        self, stream: "grpclib.server.Stream[GetOfferListRequest, GetOfferListResponse]"
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_offer_list,
            stream,
            request,
        )

    async def __rpc_get_offer_count(
        self,
        stream: "grpclib.server.Stream[GetOfferCountRequest, GetOfferCountResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_offer_count(request)
        await stream.send_message(response)

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.OfferService/GetOffer": grpclib.const.Handler(
                self.__rpc_get_offer,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetOfferRequest,
                GetOfferResponse,
            ),
            "/keyapis.subscription.v1.OfferService/GetOfferList": grpclib.const.Handler(
                self.__rpc_get_offer_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetOfferListRequest,
                GetOfferListResponse,
            ),
            "/keyapis.subscription.v1.OfferService/GetOfferCount": grpclib.const.Handler(
                self.__rpc_get_offer_count,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetOfferCountRequest,
                GetOfferCountResponse,
            ),
        }


class SubscriptionServiceBase(ServiceBase):

    async def get_subscription(
        self, get_subscription_request: "GetSubscriptionRequest"
    ) -> "GetSubscriptionResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_subscription_list(
        self, get_subscription_list_request: "GetSubscriptionListRequest"
    ) -> "AsyncIterator[GetSubscriptionListResponse]":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield GetSubscriptionListResponse()

    async def get_subscription_count(
        self, get_subscription_count_request: "GetSubscriptionCountRequest"
    ) -> "GetSubscriptionCountResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_subscription(
        self,
        stream: "grpclib.server.Stream[GetSubscriptionRequest, GetSubscriptionResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_subscription(request)
        await stream.send_message(response)

    async def __rpc_get_subscription_list(
        self,
        stream: "grpclib.server.Stream[GetSubscriptionListRequest, GetSubscriptionListResponse]",
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.get_subscription_list,
            stream,
            request,
        )

    async def __rpc_get_subscription_count(
        self,
        stream: "grpclib.server.Stream[GetSubscriptionCountRequest, GetSubscriptionCountResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_subscription_count(request)
        await stream.send_message(response)

    def __mapping__(self) -> "dict[str, grpclib.const.Handler]":
        return {
            "/keyapis.subscription.v1.SubscriptionService/GetSubscription": grpclib.const.Handler(
                self.__rpc_get_subscription,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetSubscriptionRequest,
                GetSubscriptionResponse,
            ),
            "/keyapis.subscription.v1.SubscriptionService/GetSubscriptionList": grpclib.const.Handler(
                self.__rpc_get_subscription_list,
                grpclib.const.Cardinality.UNARY_STREAM,
                GetSubscriptionListRequest,
                GetSubscriptionListResponse,
            ),
            "/keyapis.subscription.v1.SubscriptionService/GetSubscriptionCount": grpclib.const.Handler(
                self.__rpc_get_subscription_count,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetSubscriptionCountRequest,
                GetSubscriptionCountResponse,
            ),
        }


rebuild_dataclass(Privilege)  # type: ignore
rebuild_dataclass(PrivilegeFilter)  # type: ignore
rebuild_dataclass(PrivilegeFilterValidationError)  # type: ignore
rebuild_dataclass(PrivilegePaging)  # type: ignore
rebuild_dataclass(PrivilegePagingValidationError)  # type: ignore
rebuild_dataclass(GetPrivilegeListRequest)  # type: ignore
rebuild_dataclass(GetPrivilegeListResponse)  # type: ignore
rebuild_dataclass(GetPrivilegeListResponseError)  # type: ignore
rebuild_dataclass(GetPrivilegeCountRequest)  # type: ignore
rebuild_dataclass(GetPrivilegeCountResponse)  # type: ignore
rebuild_dataclass(GetPrivilegeCountResponseError)  # type: ignore
rebuild_dataclass(GetPrivilegeCheckRequest)  # type: ignore
rebuild_dataclass(Plan)  # type: ignore
rebuild_dataclass(PlanOptionDescription)  # type: ignore
rebuild_dataclass(PlanFilter)  # type: ignore
rebuild_dataclass(PlanFilterValidationError)  # type: ignore
rebuild_dataclass(PlanPaging)  # type: ignore
rebuild_dataclass(PlanPagingValidationError)  # type: ignore
rebuild_dataclass(GetPlanResponse)  # type: ignore
rebuild_dataclass(GetPlanListRequest)  # type: ignore
rebuild_dataclass(GetPlanListResponse)  # type: ignore
rebuild_dataclass(GetPlanListResponseError)  # type: ignore
rebuild_dataclass(GetPlanCountRequest)  # type: ignore
rebuild_dataclass(GetPlanCountResponse)  # type: ignore
rebuild_dataclass(GetPlanCountResponseError)  # type: ignore
rebuild_dataclass(Service)  # type: ignore
rebuild_dataclass(ServiceKind)  # type: ignore
rebuild_dataclass(GetServiceListResponse)  # type: ignore
rebuild_dataclass(GetServicePrivilegeListRequest)  # type: ignore
rebuild_dataclass(GetServicePrivilegeListResponse)  # type: ignore
rebuild_dataclass(GetServicePrivilegeCountRequest)  # type: ignore
rebuild_dataclass(ServicePrivilegePaging)  # type: ignore
rebuild_dataclass(GetServiceKindListResponse)  # type: ignore
rebuild_dataclass(Offer)  # type: ignore
rebuild_dataclass(OfferFilter)  # type: ignore
rebuild_dataclass(OfferFilterValidationError)  # type: ignore
rebuild_dataclass(OfferPaging)  # type: ignore
rebuild_dataclass(OfferPagingValidationError)  # type: ignore
rebuild_dataclass(GetOfferResponse)  # type: ignore
rebuild_dataclass(GetOfferListRequest)  # type: ignore
rebuild_dataclass(GetOfferListResponse)  # type: ignore
rebuild_dataclass(GetOfferListResponseError)  # type: ignore
rebuild_dataclass(GetOfferCountRequest)  # type: ignore
rebuild_dataclass(GetOfferCountResponse)  # type: ignore
rebuild_dataclass(GetOfferCountResponseError)  # type: ignore
rebuild_dataclass(PrivilegeStateChangeTask)  # type: ignore
rebuild_dataclass(Subscription)  # type: ignore
rebuild_dataclass(SubscriptionFilterValidationError)  # type: ignore
rebuild_dataclass(SubscriptionPaging)  # type: ignore
rebuild_dataclass(SubscriptionPagingValidationError)  # type: ignore
rebuild_dataclass(GetSubscriptionResponse)  # type: ignore
rebuild_dataclass(GetSubscriptionListRequest)  # type: ignore
rebuild_dataclass(GetSubscriptionListResponse)  # type: ignore
rebuild_dataclass(GetSubscriptionListResponseError)  # type: ignore
rebuild_dataclass(GetSubscriptionCountRequest)  # type: ignore
rebuild_dataclass(GetSubscriptionCountResponse)  # type: ignore
rebuild_dataclass(GetSubscriptionCountResponseError)  # type: ignore
