objets_metier_rs 1.0.2

Bibliothèque Rust moderne et sûre pour l'API COM Objets Métier Sage 100c - Production Ready
// Exemple complet d'utilisation du processus PMEncoder
// Création d'une pièce comptable avec le processus de saisie
//
// Ce processus garantit :
// - L'équilibre de la pièce (Débit = Crédit)
// - L'atomicité de l'insertion (tout ou rien)
// - La validation des données avant enregistrement
// - La génération automatique des écritures analytiques et échéances
//
// Pour exécuter cet exemple :
//     cargo run --example pm_encoder_example

use objets_metier_rs::errors::SageResult;
use objets_metier_rs::wrappers::cpta::CptaApplication;

const BSCPTA_CLSID: &str = "309DE0FB-9FB8-4F4E-8295-CC60C60DAA33";

fn main() -> SageResult<()> {
    println!("🚀 Exemple PMEncoder - Création de pièce comptable\n");
    println!("{}", "=".repeat(70));

    // =========================================================================
    // 1. Connexion à la base comptable
    // =========================================================================
    println!("\n📂 Connexion à la base BIJOU...");

    let app = CptaApplication::new(BSCPTA_CLSID)?;
    app.set_name(r"D:\TMP\BIJOU.MAE")?;

    let loggable = app.loggable()?;
    loggable.set_user_name("<Administrateur>")?;
    loggable.set_user_pwd("")?;

    app.open()?;
    println!("   ✓ Connecté à la base BIJOU");

    // =========================================================================
    // 2. Création du processus PMEncoder
    // =========================================================================
    println!("\n🔧 Création du processus PMEncoder...");
    let process = app.create_process_encoder()?;
    println!("   ✓ Processus créé");

    // =========================================================================
    // 3. Configuration de l'entête de la pièce
    // =========================================================================
    println!("\n📋 Configuration de l'entête de la pièce...");

    // Récupération du journal
    let factory_journal = app.factory_journal()?;
    let journal = factory_journal.read_numero("OD")?;
    println!(
        "   ✓ Journal : {} - {}",
        journal.jo_num()?,
        journal.jo_intitule()?
    );

    // Définition du journal sur le processus
    process.set_journal(&journal)?;

    // Date de la pièce
    let date = "2025-07-31";
    process.set_date(date)?;
    println!("   ✓ Date : {}", date);

    // Date d'échéance (optionnelle)
    let date_echeance = "2025-08-31";
    println!("   ✓ Date d'échéance : 2025-08-31");

    // Numéro de pièce (obtenu du journal)
    let num_piece = journal.next_ec_piece(date)?;
    process.set_ec_piece(&num_piece)?;
    println!("   ✓ N° Pièce : {}", num_piece);

    // Intitulé de la pièce
    process.set_ec_intitule("Règlement facture fournisseur")?;
    println!("   ✓ Intitulé : Règlement facture fournisseur");

    // Référence (facultatif)
    process.set_ec_reference("REF-2025-001")?;
    println!("   ✓ Référence : REF-2025-001");

    // Configuration des options automatiques
    process.set_analytique_auto(true)?;
    process.set_multi_echeance_auto(true)?;
    println!("   ✓ Génération automatique : analytique et échéances activées");

    // =========================================================================
    // 4. Création des écritures
    // =========================================================================
    println!("\n✍️  Création des écritures...");

    let factory_ecriture = process.factory_ecriture_in()?;
    let factory_compte_g = app.factory_compte_g()?;
    let factory_tiers = app.factory_tiers()?;

    // ------------------------------------
    // Écriture 1 : DÉBIT - Compte Fournisseur
    // ------------------------------------
    println!("\n   📝 Écriture 1 : DÉBIT Compte Fournisseur");
    let ecriture1 = factory_ecriture.create()?;

    // Compte général fournisseur
    let compte_fournisseur = factory_compte_g.read_numero("4010000")?;
    ecriture1.set_compte_g(&compte_fournisseur)?;
    println!(
        "      - Compte : {} - {}",
        compte_fournisseur.cg_num()?,
        compte_fournisseur.cg_intitule()?
    );

    // Tiers (optionnel mais recommandé)
    if let Ok(tiers) = factory_tiers.read_numero("CARAT") {
        ecriture1.set_tiers(&tiers)?;
        println!("      - Tiers : {}", tiers.ct_intitule()?);
    }

    // Montant au DÉBIT
    ecriture1.set_ec_sens(0)?; // 0 = Débit
    ecriture1.set_ec_montant(1200.00)?;
    println!("      - Débit : 1 200,00 €");

    // Intitulé spécifique (héritera de l'intitulé global si non défini)
    ecriture1.set_ec_intitule("Règlement facture F2025-456")?;

    // Date d'échéance (obligatoire pour compte 401)
    ecriture1.set_ec_echeance(date_echeance)?;

    // Validation de l'écriture
    ecriture1.write()?;
    println!("      ✓ Écriture 1 validée");

    // ------------------------------------
    // Écriture 2 : CRÉDIT - Compte Banque
    // ------------------------------------
    println!("\n   📝 Écriture 2 : CRÉDIT Compte Banque");
    let ecriture2 = factory_ecriture.create()?;

    // Compte général banque
    let compte_banque = factory_compte_g.read_numero("5121000")?;
    ecriture2.set_compte_g(&compte_banque)?;
    println!(
        "      - Compte : {} - {}",
        compte_banque.cg_num()?,
        compte_banque.cg_intitule()?
    );

    // Montant au CRÉDIT
    ecriture2.set_ec_sens(1)?; // 1 = Crédit
    ecriture2.set_ec_montant(1200.00)?;
    println!("      - Crédit : 1 200,00 €");

    // Validation de l'écriture
    ecriture2.write()?;
    println!("      ✓ Écriture 2 validée");

    // =========================================================================
    // 5. Vérification de l'équilibre
    // =========================================================================
    println!("\n⚖️  Vérification de l'équilibre...");

    let debit = process.debit()?;
    let credit = process.credit()?;
    let solde = process.solde()?;

    println!("   - Débit total  : {:.2}", debit);
    println!("   - Crédit total : {:.2}", credit);
    println!("   - Solde        : {:.2}", solde);

    if solde == 0.0 {
        println!("   ✓ Pièce équilibrée !");
    } else {
        println!("   ⚠️  Pièce déséquilibrée de {:.2}", solde);
    }

    // =========================================================================
    // 6. Validation du processus
    // =========================================================================
    println!("\n✅ Validation du processus...");

    if process.can_process()? {
        println!("   ✓ Le processus peut être validé");

        // =========================================================================
        // 7. Enregistrement en base
        // =========================================================================
        println!("\n💾 Enregistrement en base...");

        process.process()?;
        println!("   ✓ Pièce comptable enregistrée avec succès !");

        // Affichage des écritures créées
        println!("\n📊 Écritures créées :");
        let ecritures_out = process.list_ecritures_out()?;
        println!("   Type : {:?}", ecritures_out);
    } else {
        println!("   ❌ Le processus contient des erreurs");

        // =========================================================================
        // Affichage des erreurs
        // =========================================================================
        afficher_erreurs(&process)?;
    }

    // =========================================================================
    // 8. Fermeture de la connexion
    // =========================================================================
    println!("\n🔒 Fermeture de la connexion...");
    app.close()?;
    println!("   ✓ Connexion fermée");

    println!("\n{}", "=".repeat(70));
    println!("✅ Exemple terminé avec succès !");

    Ok(())
}

/// Affiche les erreurs de validation du processus
fn afficher_erreurs(
    process: &objets_metier_rs::wrappers::cpta::process::PMEncoder,
) -> SageResult<()> {
    println!("\n❌ Erreurs détectées :");

    let errors = process.errors()?;
    let count = errors.count()?;

    println!("   Nombre d'erreurs : {}", count);

    for i in 1..=count {
        let error = errors.item(i)?;

        let code = error.error_code()?;
        let text = error.text()?;
        let indice = error.indice()?;

        println!("\n   Erreur #{} :", i);
        println!("      - Code   : {}", code);
        println!("      - Ligne  : {}", indice);
        println!("      - Message: {}", text);
    }

    Ok(())
}

// =========================================================================
// Exemple avancé : Utilisation de AddTiersPart()
// =========================================================================

#[allow(dead_code)]
fn exemple_add_tiers_part() -> SageResult<()> {
    println!("\n🔧 Exemple avancé : AddTiersPart()");
    println!("{}", "-".repeat(70));

    // Connexion...
    let app = CptaApplication::new(BSCPTA_CLSID)?;
    app.set_name(r"D:\TMP\BIJOU.MAE")?;
    let loggable = app.loggable()?;
    loggable.set_user_name("<Administrateur>")?;
    loggable.set_user_pwd("")?;
    app.open()?;

    // Création du processus
    let process = app.create_process_encoder()?;

    // Configuration entête
    let factory_journal = app.factory_journal()?;
    let journal = factory_journal.read_numero("VTE")?; // Journal de vente
    process.set_journal(&journal)?;
    process.set_date("2024-12-31")?;

    let num_piece = journal.next_ec_piece("2024-12-31")?;
    process.set_ec_piece(&num_piece)?;
    process.set_ec_intitule("Facture client avec TVA")?;

    // Méthode AddTiersPart() pour générer automatiquement
    // les écritures HT, TVA et TTC
    println!("\n   📝 Utilisation de AddTiersPart()...");

    // NOTE: Cette méthode nécessite un objet TiersPart3
    // Pour cet exemple, consultez la documentation complète
    // de l'objet IBOTiersPart3

    println!("   ℹ️  AddTiersPart() génère automatiquement :");
    println!("      - Écriture HT (charge/produit)");
    println!("      - Écriture TVA");
    println!("      - Écriture TTC (compte tiers)");
    println!("      - Échéances selon le mode de règlement");

    app.close()?;
    Ok(())
}

// =========================================================================
// Exemple avancé : Utilisation de Equilibrer()
// =========================================================================

#[allow(dead_code)]
fn exemple_equilibrer() -> SageResult<()> {
    println!("\n🔧 Exemple avancé : Equilibrer()");
    println!("{}", "-".repeat(70));

    // Connexion...
    let app = CptaApplication::new(BSCPTA_CLSID)?;
    app.set_name(r"D:\TMP\BIJOU.MAE")?;
    let loggable = app.loggable()?;
    loggable.set_user_name("<Administrateur>")?;
    loggable.set_user_pwd("")?;
    app.open()?;

    // Création du processus
    let process = app.create_process_encoder()?;

    // Configuration entête
    let factory_journal = app.factory_journal()?;
    let journal = factory_journal.read_numero("OD")?;
    process.set_journal(&journal)?;
    process.set_date("2024-12-31")?;

    let num_piece = journal.next_ec_piece("2024-12-31")?;
    process.set_ec_piece(&num_piece)?;

    // Création d'écritures déséquilibrées
    let factory_ecriture = process.factory_ecriture_in()?;
    let factory_compte_g = app.factory_compte_g()?;

    // Écriture au débit
    let ecriture1 = factory_ecriture.create()?;
    let compte1 = factory_compte_g.read_numero("607000")?;
    ecriture1.set_compte_g(&compte1)?;
    ecriture1.set_ec_sens(0)?; // Débit
    ecriture1.set_ec_montant(500.00)?;
    ecriture1.write()?;

    println!("   Avant équilibrage :");
    println!("      - Débit  : {:.2}", process.debit()?);
    println!("      - Crédit : {:.2}", process.credit()?);
    println!("      - Solde  : {:.2}", process.solde()?);

    // Équilibrage automatique
    println!("\n   🔄 Appel de Equilibrer()...");
    process.equilibrer()?;

    println!("\n   Après équilibrage :");
    println!("      - Débit  : {:.2}", process.debit()?);
    println!("      - Crédit : {:.2}", process.credit()?);
    println!("      - Solde  : {:.2}", process.solde()?);
    println!("      ✓ Pièce automatiquement équilibrée !");

    app.close()?;
    Ok(())
}