cal-core 0.2.158

Callable core lib
Documentation
// File: cal-core/src/user.rs

use crate::{object_id_as_string, RecordReference};
use bson::DateTime;
use serde::{Deserialize, Deserializer, Serialize};
#[cfg(feature = "openapi")]
use utoipa::ToSchema;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct User {
    #[serde(deserialize_with = "object_id_as_string", rename = "_id")]
    pub id: String,
    pub email: String,
    pub password: String,
    #[serde(rename = "firstName")]
    pub first_name: String,
    #[serde(rename = "lastName")]
    pub last_name: String,
    pub groups: Vec<String>,
    pub account: RecordReference,
    #[serde(default)]
    pub customers: Vec<RecordReference>,
    #[serde(rename = "emailVerified", default)]
    pub email_verified: bool,
    #[serde(rename = "recordingFilter", skip_serializing_if = "Option::is_none")]
    pub recording_filter: Option<RecordingFilter>,
    #[serde(rename = "lastLogin", skip_serializing_if = "Option::is_none")]
    pub last_login: Option<DateTime>,
    #[serde(rename = "agentSettings", skip_serializing_if = "Option::is_none")]
    pub agent_settings: Option<AgentSettings>,
    #[serde(rename = "_class", skip_serializing_if = "Option::is_none")]
    pub class: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserLite {
    pub id: String,
    pub email: String,
    #[serde(rename = "firstName")]
    pub first_name: String,
    #[serde(rename = "lastName")]
    pub last_name: String,
    pub groups: Vec<String>,
    pub account: RecordReference,
    #[serde(default)]
    pub customers: Vec<RecordReference>,
}

impl From<User> for UserLite {
    fn from(user: User) -> Self {
        UserLite {
            id: user.id.clone(),
            email: user.email,
            first_name: user.first_name,
            last_name: user.last_name,
            groups: user.groups,
            account: user.account,
            customers: user.customers,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecordingFilter {
    #[serde(default)]
    pub caller: String,
    #[serde(default)]
    pub called: String,
    #[serde(default)]
    pub extension: String,
}

// Create a flexible type that can handle any value
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FlexibleValue {
    String(String),
    RecordReference(RecordReference),
    Other(serde_json::Value), // Catch any other type
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentSettings {
    #[serde(rename = "agentName", skip_serializing_if = "Option::is_none")]
    pub agent_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ddi: Option<RecordReference>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub whatsapp: Option<RecordReference>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub client: Option<RecordReference>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub account: Option<RecordReference>,
    #[serde(default, deserialize_with = "deserialize_flexible_vec")]
    pub favourites: Vec<RecordReference>,
    #[serde(default, deserialize_with = "deserialize_flexible_vec")]
    pub apps: Vec<RecordReference>,
    #[serde(default, deserialize_with = "deserialize_flexible_vec")]
    pub channels: Vec<RecordReference>,
    #[serde(rename = "contactGroups", default, deserialize_with = "deserialize_flexible_vec")]
    pub contact_groups: Vec<RecordReference>,
    #[serde(default)]
    pub queues: Vec<RecordReference>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub park: Option<RecordReference>,
    #[serde(default = "default_status")]
    pub status: String,
    #[serde(rename = "wrapUpTime", default = "default_wrap_up_time")]
    pub wrap_up_time: i32,
    #[serde(rename = "representTime", default = "default_represent_time")]
    pub represent_time: i32,
    #[serde(rename = "notifyTime", default = "default_notify_time")]
    pub notify_time: i32,
    #[serde(rename = "autoAnswer", default)]
    pub auto_answer: bool,
    #[serde(default)]
    pub wall_boards: Vec<String>,
    #[serde(rename = "wallboardRotateTime", default = "default_wallboard_rotate_time")]
    pub wallboard_rotate_time: i32,
    #[serde(rename = "disableNotifyAudio", default)]
    pub disable_notify_audio: bool,
    #[serde(default)]
    pub disposition: bool,
    #[serde(default)]
    pub transcribe: bool,
    #[serde(default)]
    pub summary: bool,
}

// More flexible deserializer that handles any type
fn deserialize_flexible_vec<'de, D>(deserializer: D) -> Result<Vec<RecordReference>, D::Error>
where
    D: Deserializer<'de>,
{
    // First, try to deserialize as an Option to handle null/missing values
    let opt_items: Option<Vec<FlexibleValue>> = Option::deserialize(deserializer)?;

    match opt_items {
        None => Ok(Vec::new()),
        Some(items) => {
            Ok(items.into_iter().filter_map(|item| {
                match item {
                    FlexibleValue::RecordReference(r) => Some(r),
                    FlexibleValue::String(_) => None, // Skip string values
                    FlexibleValue::Other(_) => None,  // Skip any other values
                }
            }).collect())
        }
    }
}

// Default value functions
fn default_status() -> String {
    "available".to_string()
}

fn default_wrap_up_time() -> i32 {
    5
}

fn default_represent_time() -> i32 {
    5
}

fn default_notify_time() -> i32 {
    6
}

fn default_wallboard_rotate_time() -> i32 {
    30
}