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 crate::wrappers::cpta::objects::EcritureG;
use std::ops::Deref;
use windows::Win32::System::Com::IDispatch;

/// Wrapper pour l'objet EcritureOD de Sage 100c (IBOEcritureOD3)
///
/// Représente une écriture d'opérations diverses (OD).
/// Hérite de toutes les propriétés d'EcritureG avec des spécificités pour les OD.
pub struct EcritureOD {
    pub ecriture: EcritureG,
}

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

    // ==================== PROPRIÉTÉS SPÉCIFIQUES OD ====================

    /// Obtient le type d'opération diverse
    /// 0 = OD Générale, 1 = À-nouveaux, 2 = Situation
    pub fn od_type(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("OD_Type", &[])?
            .to_i32()
    }

    /// Définit le type d'opération diverse
    pub fn set_od_type(&self, value: i32) -> SageResult<()> {
        let param = SafeVariant::from_i32(value);
        self.dispatch().call_property_put("OD_Type", &[param])?;
        Ok(())
    }

    /// Obtient l'origine de l'OD
    /// Chaîne décrivant la source de l'écriture (import, saisie manuelle, etc.)
    pub fn od_origine(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("OD_Origine", &[])?
            .to_string()
    }

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

    /// Obtient la référence externe de l'OD
    pub fn od_reference(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("OD_Reference", &[])?
            .to_string()
    }

    /// Définit la référence externe de l'OD
    pub fn set_od_reference(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch()
            .call_property_put("OD_Reference", &[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'écriture OD
    /// Format: "OD [Type] - [Intitulé] - [Montant] €"
    pub fn description(&self) -> SageResult<String> {
        let type_val = self.od_type().unwrap_or(0);
        let intitule = self.ecriture.ec_intitule()?;
        let montant = self.ecriture.ec_montant()?;

        let type_str = match type_val {
            0 => "Générale",
            1 => "À-nouveaux",
            2 => "Situation",
            _ => "Inconnue",
        };

        Ok(format!("OD {} - {} - {:.2}", type_str, intitule, montant))
    }

    /// Retourne le type d'OD sous forme textuelle
    pub fn type_description(&self) -> SageResult<String> {
        let type_val = self.od_type()?;
        Ok(match type_val {
            0 => "OD Générale".to_string(),
            1 => "À-nouveaux".to_string(),
            2 => "Situation".to_string(),
            _ => format!("Type inconnu ({})", type_val),
        })
    }
}

// Implémentation de Deref pour accéder directement aux méthodes d'EcritureG
impl Deref for EcritureOD {
    type Target = EcritureG;

    fn deref(&self) -> &Self::Target {
        &self.ecriture
    }
}

impl FromDispatch for EcritureOD {
    fn from_dispatch(dispatch: IDispatch) -> SageResult<Self> {
        Ok(EcritureOD {
            ecriture: EcritureG { dispatch },
        })
    }
}

impl FromDispatchNew for EcritureOD {
    fn from_dispatch_new(dispatch: IDispatch) -> SageResult<Self> {
        Ok(Self {
            ecriture: EcritureG { dispatch },
        })
    }
}

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

        // Utilisation typique :
        // let factory = app.factory_ecriture_od()?;
        // let od = factory.read_numero(12345)?;
        //
        // // Propriétés spécifiques OD
        // println!("Type: {}", od.type_description()?);
        // println!("Origine: {}", od.od_origine()?);
        // println!("Référence: {}", od.od_reference()?);
        //
        // // Propriétés héritées d'Ecriture
        // println!("Intitulé: {}", od.ec_intitule()?);
        // println!("Montant: {:.2} €", od.ec_montant()?);
        // println!("Pièce: {}", od.ec_piece()?);
        //
        // // Création d'une nouvelle OD
        // let nouvelle = factory.create()?;
        // nouvelle.set_od_type(0)?; // OD Générale
        // nouvelle.set_od_origine("Import")?;
        // nouvelle.set_od_reference("REF-2025-001")?;
        // nouvelle.write()?;
    }
}