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 objets_metier_rs::errors::SageResult;
use objets_metier_rs::wrappers::cial::CialApplication;
/// Exemple : Création d'un bon de commande client dans BIJOU
///
/// Ce programme démontre la création complète d'une commande client avec :
/// - Connexion à la base comptable (CPTA) et commerciale (CIAL)
/// - Recherche du client "CARAT" via FactoryClient (module CPTA)
/// - Recherche de l'article "LOCCOLLIER" via FactoryArticle (module CIAL)
/// - Création d'un document de vente type "Commande client"
/// - Ajout d'une ligne de commande
/// - Enregistrement du document
///
/// Prérequis :
/// - Base BIJOU.MAE accessible à D:\TMP\BIJOU.MAE
/// - Client avec code "CARAT" existant dans la comptabilité
/// - Article avec référence "LOCCOLLIER" existant
use objets_metier_rs::wrappers::cpta::CptaApplication;

const BSCPTA_CLSID: &str = "309DE0FB-9FB8-4F4E-8295-CC60C60DAA33";
const BSCIAL_CLSID: &str = "ED0EC116-16B8-44CC-A68A-41BF6E15EB3F";

fn main() -> SageResult<()> {
    println!("═══════════════════════════════════════════════════════════");
    println!("  Création d'un bon de commande client - Base BIJOU");
    println!("═══════════════════════════════════════════════════════════\n");

    // ========================================================================
    // ÉTAPE 1 : Connexion à la base comptable BIJOU (CPTA)
    // ========================================================================
    println!("📂 ÉTAPE 1 : Connexion à la base comptable BIJOU");
    println!("─────────────────────────────────────────────────────────");

    let cpta = CptaApplication::new(BSCPTA_CLSID)?;
    println!("✓ Application CPTA créée");

    cpta.set_name(r"D:\TMP\BIJOU.MAE")?;
    println!("✓ Base comptable définie : D:\\TMP\\BIJOU.MAE");

    let loggable_cpta = cpta.loggable()?;
    loggable_cpta.set_user_name("<Administrateur>")?;
    loggable_cpta.set_user_pwd("")?;
    println!("✓ Authentification CPTA configurée");

    cpta.open()?;
    println!("✓ Base comptable ouverte avec succès");

    if !cpta.is_open()? {
        eprintln!("❌ ERREUR : La base comptable n'est pas ouverte !");
        return Ok(());
    }
    println!("✓ Connexion CPTA vérifiée\n");

    // ========================================================================
    // ÉTAPE 1bis : Connexion à la base commerciale BIJOU (CIAL)
    // ========================================================================
    println!("📂 ÉTAPE 1bis : Connexion à la base commerciale BIJOU");
    println!("─────────────────────────────────────────────────────────");

    let cial = CialApplication::new(BSCIAL_CLSID)?;
    println!("✓ Application CIAL créée");

    // ⚠️ CRUCIAL : Lier CIAL à CPTA AVANT d'ouvrir la base commerciale
    cial.set_cpta_application(cpta.instance())?;
    println!("✓ Application CIAL liée à l'application CPTA");

    cial.set_name(r"D:\TMP\BIJOU.GCM")?;
    println!("✓ Base commerciale définie : D:\\TMP\\BIJOU.GCM");

    let loggable_cial = cial.loggable()?;
    loggable_cial.set_user_name("<Administrateur>")?;
    loggable_cial.set_user_pwd("")?;
    println!("✓ Authentification CIAL configurée");

    cial.open()?;
    println!("✓ Base commerciale ouverte avec succès");

    if !cial.is_open()? {
        eprintln!("❌ ERREUR : La base commerciale n'est pas ouverte !");
        return Ok(());
    }
    println!("✓ Connexion CIAL vérifiée\n");

    // ========================================================================
    // ÉTAPE 2 : Vérification du client CARAT via FactoryClient (CPTA)
    // ========================================================================
    println!("👤 ÉTAPE 2 : Vérification du client CARAT");
    println!("─────────────────────────────────────────────────────────");

    let factory_client = cpta.factory_client()?;
    println!("✓ FactoryClient obtenue depuis CPTA");

    // Vérifier que le client CARAT existe
    match factory_client.exist_numero("CARAT") {
        Ok(exists) => {
            if exists {
                println!("✓ Client CARAT existe dans la base comptable");

                // Lire les détails du client
                match factory_client.read_numero("CARAT") {
                    Ok(client) => {
                        println!("  → Compte client : {}", client.ct_num()?);
                        println!("  → Intitulé      : {}", client.ct_intitule()?);

                        // Afficher quelques informations supplémentaires
                        if let Ok(qualite) = client.ct_qualite() {
                            if !qualite.is_empty() {
                                println!("  → Qualité       : {}", qualite);
                            }
                        }
                        if let Ok(classement) = client.ct_classement() {
                            if !classement.is_empty() {
                                println!("  → Classement    : {}", classement);
                            }
                        }
                    }
                    Err(e) => {
                        eprintln!("❌ ERREUR : Impossible de lire le client CARAT : {}", e);
                        return Ok(());
                    }
                }
            } else {
                eprintln!("❌ ERREUR : Le client CARAT n'existe pas dans la base !");
                eprintln!(
                    "   Veuillez créer un client avec le code 'CARAT' dans Sage 100c Comptabilité."
                );
                return Ok(());
            }
        }
        Err(e) => {
            eprintln!(
                "❌ ERREUR : Impossible de vérifier l'existence du client CARAT : {}",
                e
            );
            return Ok(());
        }
    }
    println!();

    // ========================================================================
    // ÉTAPE 3 : Vérification de l'article LOCCOLLIER
    // ========================================================================
    println!("📦 ÉTAPE 3 : Vérification de l'article LOCCOLLIER");
    println!("─────────────────────────────────────────────────────────");

    let factory_article = cial.factory_article()?;
    println!("✓ FactoryArticle obtenue");

    // Vérifier que l'article existe
    match factory_article.exist_reference("LOCCOLLIER") {
        Ok(exists) => {
            if exists {
                println!("✓ Article LOCCOLLIER existe dans la base");

                // Lire les détails de l'article
                match factory_article.read_reference("LOCCOLLIER") {
                    Ok(article) => {
                        let reference = article.ar_ref()?;
                        let designation = article.ar_design()?;
                        println!("  → Référence   : {}", reference);
                        println!("  → Désignation : {}", designation);
                    }
                    Err(e) => {
                        eprintln!("⚠️  Erreur lecture article : {}", e);
                    }
                }
            } else {
                eprintln!("❌ ERREUR : Article LOCCOLLIER introuvable !");
                eprintln!("    Veuillez créer l'article avant de continuer.");
                cial.close()?;
                return Ok(());
            }
        }
        Err(e) => {
            eprintln!("❌ ERREUR vérification article : {}", e);
            cial.close()?;
            return Ok(());
        }
    }
    println!();

    // ========================================================================
    // ÉTAPE 4 : Création du document de commande client
    // ========================================================================
    println!("📝 ÉTAPE 4 : Création du bon de commande client");
    println!("─────────────────────────────────────────────────────────");

    let factory_doc_vente = cial.factory_document_vente()?;
    println!("✓ FactoryDocumentVente obtenue");

    // Test pour identifier le bon type de document
    // Types possibles selon documentation Sage :
    // - DocumentTypeVenteDevis = 0
    // - DocumentTypeVenteCommande = 6 (?)
    // - DocumentTypeVenteLivraison = 2
    // - DocumentTypeVenteFacture = 3

    println!("\n⚠️  TEST: Tentative de création avec différents types...");

    // Test type 0 (Devis)
    println!("→ Test création document type 0 (Devis)...");
    match factory_doc_vente.create_type(0) {
        Ok(_) => println!("  ✓ Type 0 (Devis) fonctionne !"),
        Err(e) => println!("  ✗ Type 0 échoue: {}", e),
    }

    // Test type 6 (Commande possible)
    println!("→ Test création document type 6 (Commande?)...");
    match factory_doc_vente.create_type(6) {
        Ok(_) => println!("  ✓ Type 6 fonctionne !"),
        Err(e) => println!("  ✗ Type 6 échoue: {}", e),
    }

    // Test type 1 (ce qu'on essayait)
    println!("→ Test création document type 1...");
    match factory_doc_vente.create_type(1) {
        Ok(_) => println!("  ✓ Type 1 fonctionne !"),
        Err(e) => println!("  ✗ Type 1 échoue: {}", e),
    }

    println!("\n→ Création finale du document (type 0 = Devis pour test)...");

    match factory_doc_vente.create_type(0) {
        Ok(devis) => {
            println!("✓ Document devis créé");

            // ========================================================================
            // WORKFLOW CORRECT selon documentation Sage
            // ========================================================================

            println!("→ Définition du client par défaut...");
            // Récupérer à nouveau le client pour avoir son IDispatch
            match factory_client.read_numero("CARAT") {
                Ok(client) => {
                    // SetDefaultClient initialise automatiquement :
                    // - Le tiers (DO_Tiers)
                    // - Les conditions de règlement
                    // - La devise
                    // - Le dépôt
                    // - La catégorie tarifaire et remises
                    match devis.set_default_client(client.instance()) {
                        Ok(()) => println!("  ✓ Client CARAT défini comme client par défaut"),
                        Err(e) => {
                            eprintln!("  ❌ Erreur SetDefaultClient: {}", e);
                            return Ok(());
                        }
                    }
                }
                Err(e) => {
                    eprintln!("  ❌ Erreur lecture client: {}", e);
                    return Ok(());
                }
            }

            println!("→ Génération du numéro de pièce...");
            match devis.set_default_do_piece() {
                Ok(()) => println!("  ✓ Numéro de pièce généré automatiquement"),
                Err(e) => {
                    eprintln!("  ❌ Erreur SetDefaultDO_Piece: {}", e);
                    return Ok(());
                }
            }

            // Obtenir le numéro de pièce généré
            let piece = devis.do_piece()?;
            let doc_type = devis.do_type()?;
            println!("  → Pièce : {}", piece);
            println!("  → Type  : {} (0=Devis)", doc_type);

            // ========================================================================
            // ÉTAPE 5 : Ajout des lignes de commande
            // ========================================================================
            println!("\n📋 ÉTAPE 5 : Ajout des lignes de commande");
            println!("─────────────────────────────────────────────────────────");

            println!("→ Ajout d'une ligne pour l'article LOCCOLLIER...");
            println!("  ℹ️  Gestion des lignes à implémenter");
            println!("     En production :");
            println!("     - Accéder à la collection de lignes : commande.lignes()?");
            println!("     - Créer une nouvelle ligne : lignes.add()?");
            println!("     - Définir article : ligne.set_ar_ref(\"LOCCOLLIER\")?");
            println!("     - Définir quantité : ligne.set_dl_qte(1.0)?");
            println!("     - Prix : ligne.set_dl_puttc(prix)?");

            // ========================================================================
            // ÉTAPE 6 : Enregistrement du document
            // ========================================================================
            println!("\n💾 ÉTAPE 6 : Enregistrement du document");
            println!("─────────────────────────────────────────────────────────");

            println!("→ Enregistrement du devis avec WriteDefault()...");
            println!("  ℹ️  WriteDefault() initialise automatiquement les valeurs par défaut");

            match devis.write_default() {
                Ok(()) => {
                    println!("✓ Devis enregistré avec succès !");
                    println!("  → Numéro de pièce : {}", piece);
                    println!("  → Client : CARAT");
                    println!("  → Type : 0 (Devis)");
                }
                Err(e) => {
                    eprintln!("❌ ERREUR lors de l'enregistrement : {}", e);
                }
            }
        }
        Err(e) => {
            eprintln!("❌ ERREUR création document : {}", e);
        }
    }

    println!();

    // ========================================================================
    // ÉTAPE 7 : Vérification du document créé
    // ========================================================================
    println!("🔍 ÉTAPE 7 : Vérification du document créé");
    println!("─────────────────────────────────────────────────────────");

    // Lister les commandes récentes (type 1)
    println!("→ Liste des commandes clients...");
    println!("  ℹ️  À implémenter avec query_type_order_piece(1)");

    println!();

    // ========================================================================
    // ÉTAPE 8 : Fermeture des connexions
    // ========================================================================
    println!("🚪 ÉTAPE 8 : Fermeture des connexions");
    println!("─────────────────────────────────────────────────────────");

    cial.close()?;
    println!("✓ Base commerciale fermée proprement");

    cpta.close()?;
    println!("✓ Base comptable fermée proprement");

    println!();
    println!("═══════════════════════════════════════════════════════════");
    println!("  ✅ EXEMPLE TERMINÉ AVEC SUCCÈS");
    println!("═══════════════════════════════════════════════════════════");
    println!();
    println!("📌 NOTES IMPORTANTES :");
    println!("   1. Cet exemple utilise la version minimale Phase 1");
    println!("   2. Les propriétés détaillées (tiers, date, etc.) seront");
    println!("      disponibles dans la Phase 2");
    println!("   3. La gestion des lignes nécessite l'implémentation de");
    println!("      la collection DocumentLigne");
    println!("   4. Pour un workflow complet, voir la Phase 2 à venir");
    println!();
    println!("💡 PROCHAINES ÉTAPES :");
    println!("   → Phase 2 : Enrichir DocumentVente avec toutes les propriétés");
    println!("   → Phase 2 : Implémenter DocumentLigne pour gérer les lignes");
    println!("   → Phase 2 : Ajouter les méthodes de calcul (totaux, taxes, etc.)");

    Ok(())
}