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 IBPReglement3
/// Représente un mode de règlement dans Sage 100c
#[derive(Debug)]
pub struct Reglement {
    pub dispatch: IDispatch,
}

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

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

    /// Code du mode de règlement (ex: "CHQ", "VIR", "CB")
    pub fn rg_code(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("RG_Code", &[])?
            .to_string()
    }

    /// Intitulé du mode de règlement (ex: "Chèque", "Virement", "Carte bancaire")
    pub fn rg_intitule(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("RG_Intitule", &[])?
            .to_string()
    }

    /// Type de règlement (0=Espèces, 1=Chèque, 2=Traite, 3=Virement, etc.)
    pub fn rg_type(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("RG_Type", &[])?
            .to_i32()
    }

    /// Condition de règlement (0=Aucune, 1=Jour net, 2=Fin de mois, etc.)
    pub fn rg_condition(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("RG_Condition", &[])?
            .to_i32()
    }

    /// Nombre de jours pour le règlement
    pub fn rg_nb_jour(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("RG_NbJour", &[])?
            .to_i32()
    }

    /// Indique si le règlement est en fin de mois
    pub fn rg_fin_mois(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("RG_FinMois", &[])?
            .to_bool()
    }

    /// Jour du mois pour le règlement (1-31)
    pub fn rg_jour(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("RG_Jour", &[])?
            .to_i32()
    }

    /// Jour de règlement "le" (pour conditions spécifiques)
    pub fn rg_le(&self) -> SageResult<i32> {
        self.dispatch().call_method_by_name("RG_Le", &[])?.to_i32()
    }

    /// Compte comptable associé au règlement
    pub fn rg_compte(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("RG_Compte", &[])?
            .to_string()
    }

    /// Taux d'escompte associé (en pourcentage)
    pub fn rg_taux_escompte(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("RG_TauxEscompte", &[])?
            .to_f64()
    }

    /// Compte d'escompte
    pub fn rg_compte_escompte(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("RG_CompteEscompte", &[])?
            .to_string()
    }

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

    /// Définit le code du règlement
    pub fn set_rg_code(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch().call_method_by_name("RG_Code", &[variant])?;
        Ok(())
    }

    /// Définit l'intitulé du règlement
    pub fn set_rg_intitule(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch()
            .call_method_by_name("RG_Intitule", &[variant])?;
        Ok(())
    }

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

    /// Définit la condition de règlement
    pub fn set_rg_condition(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch()
            .call_method_by_name("RG_Condition", &[variant])?;
        Ok(())
    }

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

    /// Définit si le règlement est en fin de mois
    pub fn set_rg_fin_mois(&mut self, value: bool) -> SageResult<()> {
        let variant = SafeVariant::from_bool(value);
        self.dispatch()
            .call_method_by_name("RG_FinMois", &[variant])?;
        Ok(())
    }

    /// Définit le jour du mois
    pub fn set_rg_jour(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch().call_method_by_name("RG_Jour", &[variant])?;
        Ok(())
    }

    /// Définit le compte comptable
    pub fn set_rg_compte(&mut self, value: &str) -> SageResult<()> {
        let variant = SafeVariant::from_string(value);
        self.dispatch()
            .call_method_by_name("RG_Compte", &[variant])?;
        Ok(())
    }

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

    /// Définit le jour de règlement "le"
    pub fn set_rg_le(&self, le: i32) -> SageResult<()> {
        let le_variant = SafeVariant::from_i32(le);
        self.dispatch().call_property_put("RG_Le", &[le_variant])?;
        Ok(())
    }

    /// Définit le compte d'escompte
    pub fn set_rg_compte_escompte(&self, compte: &str) -> SageResult<()> {
        let compte_variant = SafeVariant::from_string(compte);
        self.dispatch()
            .call_property_put("RG_CompteEscompte", &[compte_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 Reglement {
    fn clone(&self) -> Self {
        Self {
            dispatch: self.dispatch.clone(),
        }
    }
}

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

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

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

        // Utilisation typique :
        // let factory = app.factory_reglement()?;
        // let reglement = factory.read_intitule("Chèque")?;
        //
        // println!("Règlement: {} - {}", reglement.rg_code()?, reglement.rg_intitule()?);
        // println!("Type: {}", reglement.rg_type()?);
        // println!("Nb jours: {}", reglement.rg_nb_jour()?);
    }
}