objets_metier_rs 1.0.2

Bibliothèque Rust moderne et sûre pour l'API COM Objets Métier Sage 100c - Production Ready
use crate::com::{FromDispatch, FromDispatchNew, SafeDispatch, SafeVariant};
use crate::errors::SageResult;
use windows::Win32::System::Com::IDispatch;

/// Wrapper pour l'objet Collaborateur de Sage 100c (IBOCollaborateur3)
///
/// Représente un collaborateur ou responsable de comptes dans l'entreprise.
/// Les collaborateurs peuvent être affectés aux tiers (clients/fournisseurs)
/// pour le suivi commercial et administratif.
pub struct Collaborateur {
    pub dispatch: IDispatch,
}

impl Collaborateur {
    /// Crée un SafeDispatch temporaire pour les appels
    fn dispatch(&self) -> SafeDispatch<'_> {
        SafeDispatch::new(&self.dispatch)
    }

    // ==================== IDENTIFICATION ====================

    /// Obtient le numéro du collaborateur
    pub fn co_numero(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Numero", &[])?
            .to_string()
    }

    /// Définit le numéro du collaborateur
    pub fn set_co_numero(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Numero", &[param])?;
        Ok(())
    }

    /// Obtient l'intitulé/nom complet du collaborateur
    pub fn co_intitule(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Intitule", &[])?
            .to_string()
    }

    /// Définit l'intitulé du collaborateur
    pub fn set_co_intitule(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Intitule", &[param])?;
        Ok(())
    }

    // ==================== IDENTITÉ ====================

    /// Obtient le nom du collaborateur
    pub fn co_nom(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Nom", &[])?
            .to_string()
    }

    /// Définit le nom du collaborateur
    pub fn set_co_nom(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Nom", &[param])?;
        Ok(())
    }

    /// Obtient le prénom du collaborateur
    pub fn co_prenom(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Prenom", &[])?
            .to_string()
    }

    /// Définit le prénom du collaborateur
    pub fn set_co_prenom(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Prenom", &[param])?;
        Ok(())
    }

    // ==================== COORDONNÉES ====================

    /// Obtient le numéro de téléphone
    pub fn co_telephone(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Telephone", &[])?
            .to_string()
    }

    /// Définit le numéro de téléphone
    pub fn set_co_telephone(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch()
            .call_property_put("CO_Telephone", &[param])?;
        Ok(())
    }

    /// Obtient le numéro de télécopie/fax
    pub fn co_telecopie(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Telecopie", &[])?
            .to_string()
    }

    /// Définit le numéro de télécopie
    pub fn set_co_telecopie(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch()
            .call_property_put("CO_Telecopie", &[param])?;
        Ok(())
    }

    /// Obtient l'adresse email
    pub fn co_email(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Email", &[])?
            .to_string()
    }

    /// Définit l'adresse email
    pub fn set_co_email(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Email", &[param])?;
        Ok(())
    }

    // ==================== FONCTION ET SERVICE ====================

    /// Obtient la fonction du collaborateur
    pub fn co_fonction(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Fonction", &[])?
            .to_string()
    }

    /// Définit la fonction du collaborateur
    pub fn set_co_fonction(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Fonction", &[param])?;
        Ok(())
    }

    /// Obtient le service du collaborateur
    pub fn co_service(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("CO_Service", &[])?
            .to_string()
    }

    /// Définit le service du collaborateur
    pub fn set_co_service(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("CO_Service", &[param])?;
        Ok(())
    }

    // ==================== MÉTHODES IBIPersistObject ====================

    /// Enregistre l'objet dans la base de données
    pub fn write(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("Write", &[])?;
        Ok(())
    }

    /// Lit l'objet depuis la base de données
    pub fn read(&self) -> SageResult<SafeVariant> {
        self.dispatch().call_method_by_name("Read", &[])
    }

    /// Supprime l'objet de la base de données
    pub fn remove(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("Remove", &[])?;
        Ok(())
    }

    // ==================== MÉTHODES UTILITAIRES ====================

    /// Retourne une description formatée du collaborateur
    /// Format: "Collaborateur [Numéro] - [Nom] [Prénom]"
    pub fn description(&self) -> SageResult<String> {
        let numero = self.co_numero()?;
        let nom = self.co_nom()?;
        let prenom = self.co_prenom().unwrap_or_else(|_| String::new());

        let nom_complet = if prenom.is_empty() {
            nom
        } else {
            format!("{} {}", nom, prenom)
        };

        Ok(format!("Collaborateur {} - {}", numero, nom_complet))
    }

    /// Retourne les coordonnées formatées du collaborateur
    pub fn coordonnees(&self) -> SageResult<String> {
        let tel = self.co_telephone().unwrap_or_else(|_| "N/A".to_string());
        let email = self.co_email().unwrap_or_else(|_| "N/A".to_string());

        Ok(format!("Tél: {} - Email: {}", tel, email))
    }
}

impl FromDispatch for Collaborateur {
    fn from_dispatch(dispatch: IDispatch) -> SageResult<Self> {
        Ok(Collaborateur { dispatch })
    }
}

impl FromDispatchNew for Collaborateur {
    fn from_dispatch_new(dispatch: IDispatch) -> SageResult<Self> {
        Ok(Self { dispatch })
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_collaborateur_documentation() {
        // Test de documentation - nécessite un environnement Sage pour s'exécuter

        // Utilisation typique :
        // let factory = app.factory_collaborateur()?;
        // let collab = factory.read_numero("001")?;
        //
        // println!("Collaborateur: {}", collab.co_intitule()?);
        // println!("Nom: {} {}", collab.co_nom()?, collab.co_prenom()?);
        // println!("Fonction: {}", collab.co_fonction()?);
        // println!("Service: {}", collab.co_service()?);
        // println!("Contact: {}", collab.coordonnees()?);
        //
        // // Création
        // let nouveau = factory.create()?;
        // nouveau.set_co_numero("005")?;
        // nouveau.set_co_nom("Dupont")?;
        // nouveau.set_co_prenom("Marie")?;
        // nouveau.set_co_email("marie.dupont@entreprise.com")?;
        // nouveau.set_co_fonction("Responsable Commercial")?;
        // nouveau.write()?;
    }
}