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::{FromDispatchNew, SafeDispatch, SafeVariant};
use crate::errors::SageResult;
use windows::Win32::System::Com::IDispatch;

/// Wrapper complet pour IBPDevise2
/// Représente une devise (monnaie) dans Sage 100c
#[derive(Debug)]
pub struct Devise {
    pub dispatch: IDispatch,
}

impl Devise {
    fn dispatch(&self) -> SafeDispatch<'_> {
        SafeDispatch::new(&self.dispatch)
    }

    // ========== PROPRIÉTÉS DE LECTURE ==========

    /// Code ISO de la devise (ex: "EUR", "USD")
    pub fn code(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("Code", &[])?
            .to_string()
    }

    /// Intitulé de la devise (ex: "Euro", "Dollar américain")
    pub fn intitule(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("Intitule", &[])?
            .to_string()
    }

    /// Code ISO (alias de code())
    pub fn d_code_iso(&self) -> SageResult<String> {
        self.code()
    }

    /// Intitulé (alias de intitule())
    pub fn d_intitule(&self) -> SageResult<String> {
        self.intitule()
    }

    /// Symbole de la devise (ex: "€", "$")
    pub fn d_symbole(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("D_Symbole", &[])?
            .to_string()
    }

    /// Format d'affichage de la devise
    pub fn d_format(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("D_Format", &[])?
            .to_string()
    }

    /// Cours de la devise (taux de change)
    pub fn d_cours(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("D_Cours", &[])?
            .to_f64()
    }

    /// Taux d'achat de la devise
    pub fn d_taux_achat(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("D_TauxAchat", &[])?
            .to_f64()
    }

    /// Taux de vente de la devise
    pub fn d_taux_vente(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("D_TauxVente", &[])?
            .to_f64()
    }

    /// Nombre de décimales pour les quantités
    pub fn d_decimale_qte(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("D_DecimaleQte", &[])?
            .to_i32()
    }

    /// Nombre de décimales pour les prix
    pub fn d_decimale_prix(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("D_DecimalePrix", &[])?
            .to_i32()
    }

    /// Date du cours de la devise
    pub fn d_cours_date(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("D_CoursDate", &[])?
            .to_string()
    }

    /// Type de cotation (0=Incertain, 1=Certain)
    pub fn d_type_cotation(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("D_TypeCotation", &[])?
            .to_i32()
    }

    /// Unité de cotation
    pub fn d_unite_cotation(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("D_UniteCotation", &[])?
            .to_f64()
    }

    /// Vérifie si c'est la devise de référence (monnaie de base)
    pub fn d_reference(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("D_Reference", &[])?
            .to_bool()
    }

    // ========== PROPRIÉTÉS D'ÉCRITURE ==========

    /// Définit le code ISO de la devise
    pub fn set_code(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch().call_method_by_name("Code", &[variant])?;
        Ok(())
    }

    /// Définit l'intitulé de la devise
    pub fn set_intitule(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch()
            .call_method_by_name("Intitule", &[variant])?;
        Ok(())
    }

    /// Définit le symbole de la devise
    pub fn set_d_symbole(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch()
            .call_method_by_name("D_Symbole", &[variant])?;
        Ok(())
    }

    /// Définit le format d'affichage
    pub fn set_d_format(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch()
            .call_method_by_name("D_Format", &[variant])?;
        Ok(())
    }

    /// Définit le cours de la devise
    pub fn set_d_cours(&mut self, value: f64) -> SageResult<()> {
        let variant = SafeVariant::from_f64(value);
        self.dispatch().call_method_by_name("D_Cours", &[variant])?;
        Ok(())
    }

    /// Définit le taux d'achat
    pub fn set_d_taux_achat(&mut self, value: f64) -> SageResult<()> {
        let variant = SafeVariant::from_f64(value);
        self.dispatch()
            .call_method_by_name("D_TauxAchat", &[variant])?;
        Ok(())
    }

    /// Définit le taux de vente
    pub fn set_d_taux_vente(&mut self, value: f64) -> SageResult<()> {
        let variant = SafeVariant::from_f64(value);
        self.dispatch()
            .call_method_by_name("D_TauxVente", &[variant])?;
        Ok(())
    }

    /// Définit le nombre de décimales pour les quantités
    pub fn set_d_decimale_qte(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch()
            .call_method_by_name("D_DecimaleQte", &[variant])?;
        Ok(())
    }

    /// Définit le nombre de décimales pour les prix
    pub fn set_d_decimale_prix(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch()
            .call_method_by_name("D_DecimalePrix", &[variant])?;
        Ok(())
    }

    /// Définit le type de cotation
    pub fn set_d_type_cotation(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch()
            .call_method_by_name("D_TypeCotation", &[variant])?;
        Ok(())
    }

    /// Définit l'unité de cotation
    pub fn set_d_unite_cotation(&mut self, value: f64) -> SageResult<()> {
        let variant = SafeVariant::from_f64(value);
        self.dispatch()
            .call_method_by_name("D_UniteCotation", &[variant])?;
        Ok(())
    }

    /// Définit la date du cours de la devise
    pub fn set_d_cours_date(&self, date: &str) -> SageResult<()> {
        let date_variant = SafeVariant::from_string(date);
        self.dispatch()
            .call_property_put("D_CoursDate", &[date_variant])?;
        Ok(())
    }

    // ========== MÉTHODES COMMUNES (IBIPersistObject) ==========

    /// Vérifie si l'objet est persistant (existe en base)
    pub fn is_persistant(&self) -> SageResult<bool> {
        let result = self
            .dispatch()
            .call_method_by_name("IsPersistant", &[])?
            .to_i32()?;
        Ok(result != 0)
    }

    /// Vérifie si l'objet a été modifié
    pub fn is_modified(&self) -> SageResult<bool> {
        let result = self
            .dispatch()
            .call_method_by_name("IsModified", &[])?
            .to_i32()?;
        Ok(result != 0)
    }

    /// Initialise les valeurs par défaut
    pub fn set_default(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("SetDefault", &[])?;
        Ok(())
    }

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

    /// Sauvegarde l'objet avec les valeurs par défaut
    pub fn write_default(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("WriteDefault", &[])?;
        Ok(())
    }

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

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

// Implémentation de traits utiles
impl Clone for Devise {
    fn clone(&self) -> Self {
        Self {
            dispatch: self.dispatch.clone(),
        }
    }
}

impl PartialEq for Devise {
    fn eq(&self, other: &Self) -> bool {
        // Comparaison basée sur le code ISO
        match (self.code(), other.code()) {
            (Ok(code1), Ok(code2)) => code1 == code2,
            _ => false,
        }
    }
}

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

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

        // Utilisation typique :
        // let factory = app.factory_devise()?;
        // let devise = factory.read_code_iso("EUR")?;
        //
        // println!("Devise: {} - {}", devise.code()?, devise.intitule()?);
        // println!("Cours: {}", devise.d_cours()?);
        // println!("Symbole: {}", devise.d_symbole()?);
    }
}