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 IBOTaxe3
/// Représente une taxe (TVA, etc.) dans Sage 100c
#[derive(Debug)]
pub struct Taxe {
    pub dispatch: IDispatch,
}

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

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

    /// Code de la taxe (ex: "TVA20", "TVA10")
    pub fn ta_code(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("TA_Code", &[])?
            .to_string()
    }

    /// Taux de la taxe (en pourcentage, ex: 20.0 pour 20%)
    pub fn ta_taux(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("TA_Taux", &[])?
            .to_f64()
    }

    /// Intitulé de la taxe (ex: "TVA à 20%")
    pub fn ta_intitule(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("TA_Intitule", &[])?
            .to_string()
    }

    /// Type de taxe (0=Déductible, 1=Non déductible, 2=TVA/CA3)
    pub fn ta_type(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("TA_Type", &[])?
            .to_i32()
    }

    /// Compte comptable associé à la taxe
    pub fn ta_compte(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("TA_Compte", &[])?
            .to_string()
    }

    /// Sens de la taxe (0=Débit, 1=Crédit)
    pub fn ta_sens(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("TA_Sens", &[])?
            .to_i32()
    }

    /// Provenance de la taxe (0=Aucune, 1=CEE, 2=Export, 3=France)
    pub fn ta_provenance(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("TA_Provenance", &[])?
            .to_i32()
    }

    /// Indique si la taxe est hors taxe
    pub fn ta_hors_taxe(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("TA_HorsTaxe", &[])?
            .to_bool()
    }

    /// Indique si la taxe est soumise à NPR (Non Perçu Récupérable)
    pub fn ta_npr(&self) -> SageResult<bool> {
        self.dispatch()
            .call_method_by_name("TA_NPR", &[])?
            .to_bool()
    }

    /// Taux de NPR (Non Perçu Récupérable)
    pub fn ta_taux_npr(&self) -> SageResult<f64> {
        self.dispatch()
            .call_method_by_name("TA_TauxNPR", &[])?
            .to_f64()
    }

    /// Compte de contrepartie pour la NPR
    pub fn ta_compte_npr(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("TA_CompteNPR", &[])?
            .to_string()
    }

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

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

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

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

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

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

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

    /// Définit la provenance de la taxe
    pub fn set_ta_provenance(&mut self, value: i32) -> SageResult<()> {
        let variant = SafeVariant::from_i32(value);
        self.dispatch()
            .call_method_by_name("TA_Provenance", &[variant])?;
        Ok(())
    }

    /// Définit si la taxe est hors taxe
    pub fn set_ta_hors_taxe(&self, hors_taxe: bool) -> SageResult<()> {
        let hors_taxe_variant = SafeVariant::from_bool(hors_taxe);
        self.dispatch()
            .call_property_put("TA_HorsTaxe", &[hors_taxe_variant])?;
        Ok(())
    }

    /// Définit si la taxe est soumise à NPR
    pub fn set_ta_npr(&self, npr: bool) -> SageResult<()> {
        let npr_variant = SafeVariant::from_bool(npr);
        self.dispatch()
            .call_property_put("TA_NPR", &[npr_variant])?;
        Ok(())
    }

    /// Définit le taux NPR
    pub fn set_ta_taux_npr(&self, taux: f64) -> SageResult<()> {
        let taux_variant = SafeVariant::R8(taux);
        self.dispatch()
            .call_property_put("TA_TauxNPR", &[taux_variant])?;
        Ok(())
    }

    /// Définit le compte de contrepartie pour la NPR
    pub fn set_ta_compte_npr(&self, compte: &str) -> SageResult<()> {
        let compte_variant = SafeVariant::from_string(compte);
        self.dispatch()
            .call_property_put("TA_CompteNPR", &[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 Taxe {
    fn clone(&self) -> Self {
        Self {
            dispatch: self.dispatch.clone(),
        }
    }
}

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

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

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

        // Utilisation typique :
        // let factory = app.factory_taxe()?;
        // let taxe = factory.read_code("TVA20")?;
        //
        // println!("Taxe: {} - {}", taxe.ta_code()?, taxe.ta_intitule()?);
        // println!("Taux: {}%", taxe.ta_taux()?);
        // println!("Compte: {}", taxe.ta_compte()?);
    }
}