backbone-events 0.4.0

Events core + the sale/booth/crm/sms/desk overlay — registrations under one authoritative seat counter, the sale seam (order-minted registrations, forward-only paid heal, SO-cancel mirror cascade), booth bookings with the DB exclusivity wall, closed-vocabulary lead rules through a host sink port, the dual-channel (mail/sms) self-arming scheduler, and the exact-match desk verb (Odoo event port, core + overlay)
//! Database seeder binary for module: event
//!
//! Generated by metaphor-schema. Do not edit manually.
//!
//! Run with: cargo run --bin event-seeder
//! Or via CLI: backbone seed run --module event
//!
//! This binary runs all registered seeders in order.

use anyhow::Result;
use sqlx::postgres::PgPoolOptions;
use std::env;

// Import seeders
use backbone_events::seeders::SeedBoothCategorySeeder;
use backbone_events::seeders::SeedBoothSeeder;
use backbone_events::seeders::SeedTypeBoothSeeder;
use backbone_events::seeders::SeedBoothBookingSeeder;
use backbone_events::seeders::SeedEventSeeder;
use backbone_events::seeders::SeedEventTypeSeeder;
use backbone_events::seeders::SeedLeadProvenanceSeeder;
use backbone_events::seeders::SeedLeadProvenanceRegistrationSeeder;
use backbone_events::seeders::SeedLeadRequestSeeder;
use backbone_events::seeders::SeedLeadRuleSeeder;
use backbone_events::seeders::SeedLeadRulePredicateSeeder;
use backbone_events::seeders::SeedMailSeeder;
use backbone_events::seeders::SeedMailRegistrationSeeder;
use backbone_events::seeders::SeedMailSlotSeeder;
use backbone_events::seeders::SeedQuestionSeeder;
use backbone_events::seeders::SeedQuestionAnswerSeeder;
use backbone_events::seeders::SeedRegistrationQuestionSeeder;
use backbone_events::seeders::SeedRegistrationSeeder;
use backbone_events::seeders::SeedRegistrationAnswerSeeder;
use backbone_events::seeders::SeedSlotSeeder;
use backbone_events::seeders::SeedStageSeeder;
use backbone_events::seeders::SeedTagCategorySeeder;
use backbone_events::seeders::SeedTagSeeder;
use backbone_events::seeders::SeedTicketSeeder;
use backbone_events::seeders::SeedTypeMailSeeder;
use backbone_events::seeders::Seeder;

#[tokio::main]
async fn main() -> Result<()> {
    let args: Vec<String> = env::args().collect();
    let force = args.iter().any(|a| a == "--force");
    let filter: Option<&str> = args.iter()
        .skip(1)
        .find(|a| !a.starts_with("-"))
        .map(|s| s.as_str());

    let database_url = env::var("DATABASE_URL")
        .map_err(|e| anyhow::anyhow!("DATABASE_URL must be set: {e}"))?;

    println!("Connecting to database...");

    let pool = PgPoolOptions::new()
        .max_connections(5)
        .connect(&database_url)
        .await?;

    println!("Connected to database");
    println!();
    println!("Running seeders for module: event");
    println!();

    // Register seeders in order
    let mut seeders: Vec<Box<dyn Seeder + Send + Sync>> = Vec::new();
    seeders.push(Box::new(SeedBoothCategorySeeder::new()));
    seeders.push(Box::new(SeedBoothSeeder::new()));
    seeders.push(Box::new(SeedTypeBoothSeeder::new()));
    seeders.push(Box::new(SeedBoothBookingSeeder::new()));
    seeders.push(Box::new(SeedEventSeeder::new()));
    seeders.push(Box::new(SeedEventTypeSeeder::new()));
    seeders.push(Box::new(SeedLeadProvenanceSeeder::new()));
    seeders.push(Box::new(SeedLeadProvenanceRegistrationSeeder::new()));
    seeders.push(Box::new(SeedLeadRequestSeeder::new()));
    seeders.push(Box::new(SeedLeadRuleSeeder::new()));
    seeders.push(Box::new(SeedLeadRulePredicateSeeder::new()));
    seeders.push(Box::new(SeedMailSeeder::new()));
    seeders.push(Box::new(SeedMailRegistrationSeeder::new()));
    seeders.push(Box::new(SeedMailSlotSeeder::new()));
    seeders.push(Box::new(SeedQuestionSeeder::new()));
    seeders.push(Box::new(SeedQuestionAnswerSeeder::new()));
    seeders.push(Box::new(SeedRegistrationQuestionSeeder::new()));
    seeders.push(Box::new(SeedRegistrationSeeder::new()));
    seeders.push(Box::new(SeedRegistrationAnswerSeeder::new()));
    seeders.push(Box::new(SeedSlotSeeder::new()));
    seeders.push(Box::new(SeedStageSeeder::new()));
    seeders.push(Box::new(SeedTagCategorySeeder::new()));
    seeders.push(Box::new(SeedTagSeeder::new()));
    seeders.push(Box::new(SeedTicketSeeder::new()));
    seeders.push(Box::new(SeedTypeMailSeeder::new()));

    // Sort by order
    seeders.sort_by_key(|s| s.order());

    // Run seeders
    for seeder in &seeders {
        let name = seeder.name();

        // Apply filter if specified
        if let Some(f) = filter {
            if !name.contains(f) {
                continue;
            }
        }

        if force {
            println!("   Running {}...", name);
            seeder.run(&pool).await?;
            println!("   {} completed", name);
        } else {
            println!("   Checking {}...", name);
            if seeder.should_run(&pool).await? {
                println!("   Running {}...", name);
                seeder.run(&pool).await?;
                println!("   {} completed", name);
            } else {
                println!("   {} already applied, skipping", name);
            }
        }
    }

    println!();
    println!("All seeders completed successfully!");

    Ok(())
}