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

/// Wrapper pour un document de vente (IBODocumentVente3)
/// 
/// Représente un document de vente: devis, commande, BL, facture, avoir
/// 
/// Types de documents (DO_Type):
/// - 0 = Devis
/// - 1 = Bon de commande client
/// - 2 = Bon de livraison / Préparation de livraison
/// - 3 = Bon de retour / Facture
/// - 4 = Avoir
/// 
/// ⚠️ IMPLÉMENTATION MINIMALE - Version Phase 1
/// 
/// # Exemple
/// ```no_run
/// use objets_metier_rs::wrappers::cial::CialApplication;
/// 
/// let cial_app = CialApplication::new("Objets100c.CIAL")?;
/// let factory = cial_app.factory_document_vente()?;
/// let facture = factory.create_facture()?;
/// facture.set_do_piece("FA00001")?;
/// facture.write()?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
pub struct DocumentVente {
    pub(crate) dispatch: IDispatch,
}

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

    // ==================== PROPRIÉTÉS PRINCIPALES ====================

    /// Numéro de pièce
    pub fn do_piece(&self) -> SageResult<String> {
        self.dispatch()
            .call_method_by_name("DO_Piece", &[])?
            .to_string()
    }

    pub fn set_do_piece(&self, value: &str) -> SageResult<()> {
        let param = SafeVariant::from_string(value);
        self.dispatch().call_property_put("DO_Piece", &[param])?;
        Ok(())
    }

    /// Type de document
    pub fn do_type(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("DO_Type", &[])?
            .to_i32()
    }

    /// cbMarq - Identifiant unique
    pub fn cbmarq(&self) -> SageResult<i32> {
        self.dispatch()
            .call_method_by_name("cbMarq", &[])?
            .to_i32()
    }

    // ==================== MÉTHODES D'ÉCRITURE ====================

    /// Enregistre le document (sans initialisation automatique)
    pub fn write(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("Write", &[])?;
        Ok(())
    }

    /// Enregistre le document avec initialisation automatique des valeurs par défaut
    /// 
    /// **RECOMMANDÉ** pour la création de nouveaux documents car cette méthode :
    /// - Initialise automatiquement les champs avec valeurs par défaut
    /// - Génère les numéros de pièce automatiquement
    /// - Crée les lignes d'emplacements si multi-emplacements activé
    /// 
    /// # Exemple
    /// ```no_run
    /// # use objets_metier_rs::wrappers::cial::CialApplication;
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// # let cial = CialApplication::new("Objets100c.CIAL")?;
    /// # let factory = cial.factory_document_vente()?;
    /// let doc = factory.create_type(0)?; // Devis
    /// // Définir les propriétés minimales...
    /// doc.write_default()?; // ← Préférer à write() pour nouveaux documents
    /// # Ok(())
    /// # }
    /// ```
    pub fn write_default(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("WriteDefault", &[])?;
        Ok(())
    }

    pub fn remove(&self) -> SageResult<()> {
        self.dispatch().call_method_by_name("Remove", &[])?;
        Ok(())
    }

    // ==================== MÉTHODES D'INITIALISATION ====================

    /// Initialise le document avec un client par défaut
    /// 
    /// Cette méthode DOIT être appelée avant write() ou write_default() pour :
    /// - Définir le tiers (client) du document
    /// - Initialiser automatiquement les propriétés liées au client :
    ///   * Mode de règlement
    ///   * Conditions de règlement
    ///   * Devise
    ///   * Représentant
    ///   * Dépôt de livraison
    ///   * Catégorie tarifaire et remises
    /// 
    /// # Arguments
    /// * `client` - IDispatch du client (obtenu via FactoryClient.read_numero())
    /// 
    /// # Exemple
    /// ```no_run
    /// # use objets_metier_rs::wrappers::cpta::CptaApplication;
    /// # use objets_metier_rs::wrappers::cial::CialApplication;
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// # let cpta = CptaApplication::new("309DE0FB-9FB8-4F4E-8295-CC60C60DAA33")?;
    /// # cpta.open()?;
    /// # let cial = CialApplication::new("Objets100c.CIAL")?;
    /// # cial.set_cpta_application(cpta.instance())?;
    /// # cial.open()?;
    /// // Obtenir le client
    /// let client = cpta.factory_client()?.read_numero("CARAT")?;
    /// 
    /// // Créer le document et définir le client
    /// let doc = cial.factory_document_vente()?.create_type(0)?;
    /// doc.set_default_client(client.as_tiers().instance())?; // ← CRUCIAL !
    /// doc.write_default()?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn set_default_client(&self, client_dispatch: &IDispatch) -> SageResult<()> {
        let param = SafeVariant::from_dispatch(client_dispatch.clone());
        self.dispatch()
            .call_method_by_name("SetDefaultClient", &[param])?;
        Ok(())
    }

    /// Génère automatiquement un numéro de pièce pour le document
    /// 
    /// Le numéro est généré selon les paramètres de numérotation configurés
    /// dans Sage 100c (Fichier / Paramètres société / Documents).
    /// 
    /// # Exemple
    /// ```no_run
    /// # use objets_metier_rs::wrappers::cial::CialApplication;
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// # let cial = CialApplication::new("Objets100c.CIAL")?;
    /// let doc = cial.factory_document_vente()?.create_type(0)?;
    /// doc.set_default_do_piece()?; // Génère DE00001, DE00002, etc.
    /// # Ok(())
    /// # }
    /// ```
    pub fn set_default_do_piece(&self) -> SageResult<()> {
        self.dispatch()
            .call_method_by_name("SetDefaultDO_Piece", &[])?;
        Ok(())
    }
}