from collections.abc import Generator
from typing import Any, Optional
from pydantic import Field
from wxc_sdk.base import ApiModel
from wxc_sdk.common import IdAndName, PrimaryOrShared, UserType
from wxc_sdk.person_settings.common import PersonSettingsApiChild
__all__ = ['HotDeskingApi', 'HotDeskingAvailableMember', 'HotDeskingMember', 'HotDeskingMembers']
[docs]
class HotDeskingAvailableMember(ApiModel):
#: Unique identifier for the member.
id: Optional[str] = None
#: First name of the member.
first_name: Optional[str] = None
#: Last name of the member.
last_name: Optional[str] = None
#: Phone number of the member. Currently, E.164 format is not supported.
phone_number: Optional[str] = None
#: Phone extension of the member.
extension: Optional[str] = None
#: Routing prefix of the location.
routing_prefix: Optional[str] = None
#: Routing prefix plus extension of a person or workspace.
esn: Optional[str] = None
#: Indicates if the line is acting as a primary line or a shared line for this device.
line_type: Optional[PrimaryOrShared] = None
member_type: Optional[UserType] = None
#: Location object containing a unique identifier for the location and its name.
location: Optional[IdAndName] = None
[docs]
class HotDeskingMember(ApiModel):
#: Unique identifier for the assigned member.
id: Optional[str] = None
#: First name of the person or workspace.
first_name: Optional[str] = None
#: Last name of the person or workspace.
last_name: Optional[str] = None
#: Phone number of the person or workspace. Currently, E.164 format is not supported. This will be supported in a
#: future update.
phone_number: Optional[str] = None
#: Phone extension of the person or workspace.
extension: Optional[str] = None
#: Routing prefix of the location.
routing_prefix: Optional[str] = None
#: Routing prefix plus extension of a person or workspace.
esn: Optional[str] = None
#: If `true`, the person or workspace is the owner of the device. Points to the primary line/port of the device.
primary_owner: Optional[bool] = None
#: Device port number assigned to the person or workspace.
port: Optional[int] = None
#: T.38 Fax Compression setting. Valid only for ATA Devices. Overrides user-level compression options.
t38_fax_compression_enabled: Optional[bool] = None
#: Indicates if the line is acting as a primary line or a shared line for this device.
line_type: Optional[PrimaryOrShared] = None
#: Number of lines configured for the member on the hot desking guest profile endpoint.
line_weight: Optional[int] = None
#: Registration home IP address for the line port.
host_ip: Optional[str] = Field(alias='hostIP', default=None)
#: Registration remote IP address for the line port.
remote_ip: Optional[str] = Field(alias='remoteIP', default=None)
#: Configure this line to automatically call a predefined number whenever taken off-hook. Once enabled, the line
#: can only make calls to the predefined number set in `hotlineDestination`.
hotline_enabled: Optional[bool] = None
#: Preconfigured number for the hotline. Required when `hotlineEnabled` is `true`.
hotline_destination: Optional[str] = None
#: Set how a device behaves when a call is declined. When set to `true`, a call decline request is extended to all
#: endpoints on the device. When set to `false`, a call decline request is only declined at the current endpoint.
allow_call_decline_enabled: Optional[bool] = None
#: Indicates if the member is of type `PEOPLE` or `PLACE`.
member_type: Optional[UserType] = None
#: Location object containing a unique identifier for the location and its name.
location: Optional[IdAndName] = None
def update(self) -> dict[str, Any]:
"""
Data for update_members()
:meta private:
"""
data = self.model_dump(
mode='json',
by_alias=True,
exclude_none=True,
include={
'id',
'port',
'primary_owner',
'line_type',
'line_weight',
't38_fax_compression_enabled',
'hotline_enabled',
'hotline_destination',
'allow_call_decline_enabled',
'member_type',
},
)
return data
[docs]
@classmethod
def from_available_member(cls, available_member: HotDeskingAvailableMember) -> 'HotDeskingMember':
"""
Create a HotDeskingMember instance from a HotDeskingAvailableMember instance.
:param available_member: The available member to convert.
:type available_member: HotDeskingAvailableMember
:return: A new HotDeskingMember instance with data copied from the available member.
:rtype: HotDeskingMember
"""
return cls(
id=available_member.id,
first_name=available_member.first_name,
last_name=available_member.last_name,
phone_number=available_member.phone_number,
extension=available_member.extension,
routing_prefix=available_member.routing_prefix,
esn=available_member.esn,
line_type=available_member.line_type,
member_type=available_member.member_type,
location=available_member.location,
)
[docs]
class HotDeskingMembers(ApiModel):
#: Name of the hot desking guest profile endpoint.
model: Optional[str] = None
#: List of primary and shared-line members assigned to the person's hot desking guest profile.
members: Optional[list[HotDeskingMember]] = None
#: Maximum number of lines that can be configured on the hot desking guest profile endpoint.
max_line_count: Optional[int] = None
[docs]
class HotDeskingApi(PersonSettingsApiChild):
"""
API for hot desking settings; so far only used for persons
"""
feature = 'hotDesking'
[docs]
def available_members(
self,
person_id: str,
location_id: str = None,
member_name: str = None,
phone_number: str = None,
extension: str = None,
order: list[str] = None,
org_id: str = None,
**params: Any,
) -> Generator[HotDeskingAvailableMember, None, None]:
"""
Search Available Hot Desking Members
Retrieve members available for assignment to a person's hot desking guest profile.
Available members can include people, workspaces, and virtual lines that can be added as shared lines on the
hot desking profile.
This API requires a full, user, device, read-only, or location administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param person_id: Unique identifier for the entity.
:type person_id: str
:param location_id: Return only available members in this location.
:type location_id: str
:param member_name: Search for available members by name.
:type member_name: str
:param phone_number: Search for available members by phone number.
:type phone_number: str
:param extension: Search for available members by extension.
:type extension: str
:param order: Sort order for the available member list. Multiple order values may be provided.
:type order: list[str]
:param org_id: ID of the organization in which the person resides. Only admin users of another organization,
such as partners, may use this parameter. If not specified, the organization from the OAuth token is used.
:type org_id: str
:return: Generator yielding :class:`HotDeskingAvailableMember` instances
"""
if org_id is not None:
params['orgId'] = org_id
if location_id is not None:
params['locationId'] = location_id
if member_name is not None:
params['memberName'] = member_name
if phone_number is not None:
params['phoneNumber'] = phone_number
if extension is not None:
params['extension'] = extension
if order is not None:
params['order'] = ','.join(order)
url = self.f_ep(person_id, 'availableMembers')
return self.session.follow_pagination(
url=url, model=HotDeskingAvailableMember, item_key='members', params=params
)
[docs]
def get_members(self, person_id: str, org_id: str = None) -> HotDeskingMembers:
"""
Get Hot Desking Members
Retrieve the primary and shared-line members assigned to a person's hot desking guest profile.
This API requires a full, user, device, read-only, or location administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param person_id: Unique identifier for the person.
:type person_id: str
:param org_id: ID of the organization in which the person resides. Only admin users of another organization,
such as partners, may use this parameter. If not specified, the organization from the OAuth token is used.
:type org_id: str
:rtype: :class:`HotDeskingMembers`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.f_ep(person_id, 'members')
data = super().get(url, params=params)
r = HotDeskingMembers.model_validate(data)
return r
[docs]
def update_members(self, person_id: str, members: list[HotDeskingMember], org_id: str = None) -> None:
"""
Update Hot Desking Members
Modify the primary and shared-line members assigned to a person's hot desking guest profile.
The request replaces the hot desking profile member list with the members supplied in the request body.
This API requires a full, user, device, or location administrator auth token with a scope of
`spark-admin:telephony_config_write`.
:param person_id: Unique identifier for the person.
:type person_id: str
:param members: Members to assign to the person's hot desking guest profile.
:type members: list[HotDeskingMember]
:param org_id: ID of the organization in which the person resides. Only admin users of another organization,
such as partners, may use this parameter. If not specified, the organization from the OAuth token is used.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['members'] = [m.update() for m in members]
# assert that all members have "port" and "lineWeight" set, as required by the API, and set default values if
# not provided
port = 1
for m in body['members']:
if m.get('port') is None:
m['port'] = port
# default lineWeight is 1
w = m.get('lineWeight', 1)
m['lineWeight'] = w
port += w
m['primaryOwner'] = m['id'] == person_id
url = self.f_ep(person_id, 'members')
super().put(url, params=params, json=body)