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 Adresse de Sage 100c (IBOAdresse3)
///
/// Représente une adresse postale d'un tiers (client/fournisseur).
/// Permet de gérer plusieurs adresses par tiers : principale, livraison, facturation.
pub struct Adresse {
    pub dispatch: IDispatch,
}

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

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

    /// Obtient le numéro interne de l'adresse
    pub fn a_numero(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("A_Numero", &[])?
            .to_i32()
    }

    /// Obtient le code tiers rattaché
    pub fn a_tiers(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Tiers", &[])?
            .to_string()
    }

    /// Définit le code tiers rattaché
    pub fn set_a_tiers(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("A_Tiers", &[param])?;
        Ok(())
    }

    /// Obtient le type d'adresse
    /// 0 = Principale, 1 = Livraison, 2 = Facturation
    pub fn a_type(&self) -> SageResult<i32> {
        self.dispatch().call_method_by_name("A_Type", &[])?.to_i32()
    }

    /// Définit le type d'adresse
    /// 0 = Principale, 1 = Livraison, 2 = Facturation
    pub fn set_a_type(&self, value: i32) -> SageResult<()> {
        let param = SafeVariant::from_i32(value);
        self.dispatch().call_property_put("A_Type", &[param])?;
        Ok(())
    }

    /// Obtient l'intitulé de l'adresse
    pub fn a_intitule(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Intitule", &[])?
            .to_string()
    }

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

    // ==================== ADRESSE ====================

    /// Obtient l'adresse ligne 1
    pub fn a_adresse(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Adresse", &[])?
            .to_string()
    }

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

    /// Obtient le complément d'adresse (ligne 2)
    pub fn a_complement(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Complement", &[])?
            .to_string()
    }

    /// Définit le complément d'adresse
    pub fn set_a_complement(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch()
            .call_property_put("A_Complement", &[param])?;
        Ok(())
    }

    /// Obtient le code postal
    pub fn a_code_postal(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_CodePostal", &[])?
            .to_string()
    }

    /// Définit le code postal
    pub fn set_a_code_postal(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch()
            .call_property_put("A_CodePostal", &[param])?;
        Ok(())
    }

    /// Obtient la ville
    pub fn a_ville(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Ville", &[])?
            .to_string()
    }

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

    /// Obtient la région/état
    pub fn a_region(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Region", &[])?
            .to_string()
    }

    /// Définit la région/état
    pub fn set_a_region(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("A_Region", &[param])?;
        Ok(())
    }

    /// Obtient le code pays
    pub fn a_pays(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_Pays", &[])?
            .to_string()
    }

    /// Définit le code pays
    pub fn set_a_pays(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("A_Pays", &[param])?;
        Ok(())
    }

    // ==================== CONTACT ====================

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

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

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

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

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

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

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

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

    /// Obtient le site web
    pub fn a_site_web(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("A_SiteWeb", &[])?
            .to_string()
    }

    /// Définit le site web
    pub fn set_a_site_web(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("A_SiteWeb", &[param])?;
        Ok(())
    }

    // ==================== INFORMATIONS COMPLÉMENTAIRES ====================

    /// Indique si c'est l'adresse principale
    pub fn a_principal(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("A_Principal", &[])?
            .to_bool()
    }

    /// Définit si c'est l'adresse principale
    pub fn set_a_principal(&self, value: bool) -> SageResult<()> {
        let param = SafeVariant::from_bool(value);
        self.dispatch().call_property_put("A_Principal", &[param])?;
        Ok(())
    }

    /// Indique si c'est l'adresse d'expédition par défaut
    pub fn a_expedition(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("A_Expedition", &[])?
            .to_bool()
    }

    /// Définit si c'est l'adresse d'expédition par défaut
    pub fn set_a_expedition(&self, value: bool) -> SageResult<()> {
        let param = SafeVariant::from_bool(value);
        self.dispatch()
            .call_property_put("A_Expedition", &[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 de l'adresse
    /// Format: "Adresse [Type] - [Ville]"
    pub fn description(&self) -> SageResult<String> {
        let type_val = self.a_type()?;
        let ville = self.a_ville()?;

        let type_str = match type_val {
            0 => "Principale",
            1 => "Livraison",
            2 => "Facturation",
            _ => "Autre",
        };

        Ok(format!("Adresse {} - {}", type_str, ville))
    }

    /// Retourne l'adresse complète formatée
    /// Format multiligne avec adresse, CP, ville, pays
    pub fn adresse_complete(&self) -> SageResult<String> {
        let adresse = self.a_adresse()?;
        let complement = self.a_complement().unwrap_or_else(|_| String::new());
        let code_postal = self.a_code_postal()?;
        let ville = self.a_ville()?;
        let pays = self.a_pays().unwrap_or_else(|_| String::new());

        let mut result = adresse.clone();
        if !complement.is_empty() {
            result.push('\n');
            result.push_str(&complement);
        }
        result.push_str(&format!("\n{} {}", code_postal, ville));
        if !pays.is_empty() {
            result.push_str(&format!("\n{}", pays));
        }

        Ok(result)
    }
}

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

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

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

        // Utilisation typique :
        // let factory = app.factory_adresse()?;
        // let adresse = factory.read_by_tiers("CLIENT01")?;
        //
        // println!("Adresse: {}", adresse.description()?);
        // println!("Type: {}", adresse.a_type()?);
        // println!("\n{}", adresse.adresse_complete()?);
        //
        // // Création d'une nouvelle adresse
        // let nouvelle = factory.create()?;
        // nouvelle.set_a_tiers("CLIENT01")?;
        // nouvelle.set_a_type(1)?; // Livraison
        // nouvelle.set_a_adresse("123 Rue de la Paix")?;
        // nouvelle.set_a_code_postal("75001")?;
        // nouvelle.set_a_ville("Paris")?;
        // nouvelle.set_a_pays("France")?;
        // nouvelle.write()?;
    }
}