AkurAI Build
Menu

Public repository / d7881502b38897a157bd49340f35ea33e81cbaa7

AkurAI-CRM / crates/crm-cli/src/cmd_seed.rs

Latest change d7881502b38897a157bd49340f35ea33e81cbaa7 - feat: initial AkurAI-CRM implementation by Ólafur B. J.

use crm_api::CrmState;
use akurai_json::Value;

pub fn run(db_path: &str) -> Result<(), String> {
    println!("🌱 Seeding CRM database: {db_path}");

    let frontend_dir = std::path::PathBuf::from("site/frontend");
    let state = CrmState::new(db_path, frontend_dir)?;
    let mut db = state.db.lock().map_err(|e| format!("lock: {e}"))?;

    let mut insert = |entity: &str, id: u64, fields: Vec<(&str, Value)>| -> Result<(), String> {
        use std::time::{SystemTime, UNIX_EPOCH};
        let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs() as i64;
        let mut obj = Vec::new();
        obj.push(("id".into(), Value::Int(id as i64)));
        obj.push(("createdAt".into(), Value::Int(now)));
        obj.push(("updatedAt".into(), Value::Int(now)));
        for (k, v) in fields {
            obj.push((k.to_string(), v));
        }
        let record = Value::Object(obj);
        let key = format!("{}:{}", entity, id);
        let json = record.to_json();
        db.insert(key.as_bytes(), json.as_bytes())
            .map_err(|e| format!("insert {key}: {e}"))
    };

    // People
    insert("people", 1, vec![
        ("firstName", Value::Str("Anna".into())),
        ("lastName", Value::Str("Jónsdóttir".into())),
        ("email", Value::Str("anna@example.is".into())),
        ("jobTitle", Value::Str("CEO".into())),
        ("companyId", Value::Int(1)),
    ])?;
    insert("people", 2, vec![
        ("firstName", Value::Str("Björn".into())),
        ("lastName", Value::Str("Guðmundsson".into())),
        ("email", Value::Str("bjorn@example.is".into())),
        ("jobTitle", Value::Str("CTO".into())),
        ("companyId", Value::Int(1)),
    ])?;
    insert("people", 3, vec![
        ("firstName", Value::Str("Dóra".into())),
        ("lastName", Value::Str("Sigurðardóttir".into())),
        ("email", Value::Str("dora@acme.is".into())),
        ("jobTitle", Value::Str("VP Engineering".into())),
        ("companyId", Value::Int(2)),
    ])?;
    insert("people", 4, vec![
        ("firstName", Value::Str("Einar".into())),
        ("lastName", Value::Str("Pálsson".into())),
        ("email", Value::Str("einar@startup.is".into())),
        ("jobTitle", Value::Str("Founder".into())),
    ])?;
    insert("people", 5, vec![
        ("firstName", Value::Str("Fríða".into())),
        ("lastName", Value::Str("Jónsdóttir".into())),
        ("email", Value::Str("frida@nordic.is".into())),
        ("jobTitle", Value::Str("Sales Director".into())),
        ("companyId", Value::Int(3)),
    ])?;

    println!("  ✓ 5 people created");

    // Companies
    insert("companies", 1, vec![
        ("name", Value::Str("AkurAI".into())),
        ("domainName", Value::Str("akurai.is".into())),
        ("annualRevenue", Value::Int(500_000_00)),
        ("employeeCount", Value::Int(25)),
        ("websiteUrl", Value::Str("https://akurai.is".into())),
    ])?;
    insert("companies", 2, vec![
        ("name", Value::Str("Acme Corp".into())),
        ("domainName", Value::Str("acme.is".into())),
        ("annualRevenue", Value::Int(12_000_000_00)),
        ("employeeCount", Value::Int(150)),
    ])?;
    insert("companies", 3, vec![
        ("name", Value::Str("Nordic Technologies".into())),
        ("domainName", Value::Str("nordic.is".into())),
        ("annualRevenue", Value::Int(8_500_000_00)),
        ("employeeCount", Value::Int(75)),
    ])?;
    insert("companies", 4, vec![
        ("name", Value::Str("Startup Iceland".into())),
        ("domainName", Value::Str("startup.is".into())),
        ("annualRevenue", Value::Int(500_000_00)),
        ("employeeCount", Value::Int(5)),
    ])?;

    println!("  ✓ 4 companies created");

    // Opportunities
    insert("opportunities", 1, vec![
        ("name", Value::Str("AkurAI Platform Deal".into())),
        ("amount", Value::Int(250_000_00)),
        ("stage", Value::Str("negotiation".into())),
        ("probability", Value::Int(70)),
        ("personId", Value::Int(1)),
        ("companyId", Value::Int(1)),
    ])?;
    insert("opportunities", 2, vec![
        ("name", Value::Str("Acme Enterprise License".into())),
        ("amount", Value::Int(500_000_00)),
        ("stage", Value::Str("proposal".into())),
        ("probability", Value::Int(50)),
        ("personId", Value::Int(2)),
        ("companyId", Value::Int(2)),
    ])?;
    insert("opportunities", 3, vec![
        ("name", Value::Str("Nordic Consulting".into())),
        ("amount", Value::Int(85_000_00)),
        ("stage", Value::Str("meeting".into())),
        ("probability", Value::Int(30)),
        ("personId", Value::Int(5)),
        ("companyId", Value::Int(3)),
    ])?;
    insert("opportunities", 4, vec![
        ("name", Value::Str("Startup Iceland Partnership".into())),
        ("amount", Value::Int(25_000_00)),
        ("stage", Value::Str("new".into())),
        ("probability", Value::Int(10)),
        ("personId", Value::Int(4)),
        ("companyId", Value::Int(4)),
    ])?;
    insert("opportunities", 5, vec![
        ("name", Value::Str("Lost Deal - Legacy Migrate".into())),
        ("amount", Value::Int(100_000_00)),
        ("stage", Value::Str("lost".into())),
        ("probability", Value::Int(0)),
    ])?;

    println!("  ✓ 5 opportunities created");

    // Tasks
    insert("tasks", 1, vec![
        ("title", Value::Str("Follow up with Anna about AkurAI deal".into())),
        ("status", Value::Str("in_progress".into())),
        ("dueAt", Value::Int(
            (std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs() as i64) + 86400 * 3
        )),
    ])?;
    insert("tasks", 2, vec![
        ("title", Value::Str("Prepare proposal for Acme Corp".into())),
        ("status", Value::Str("todo".into())),
        ("dueAt", Value::Int(
            (std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs() as i64) + 86400 * 7
        )),
    ])?;
    insert("tasks", 3, vec![
        ("title", Value::Str("Send NDA to Nordic Technologies".into())),
        ("status", Value::Str("done".into())),
    ])?;
    insert("tasks", 4, vec![
        ("title", Value::Str("Review Q3 pipeline forecast".into())),
        ("status", Value::Str("todo".into())),
        ("dueAt", Value::Int(
            (std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs() as i64) + 86400 * 14
        )),
    ])?;

    println!("  ✓ 4 tasks created");

    // Notes
    insert("notes", 1, vec![
        ("title", Value::Str("Initial meeting with Anna".into())),
        ("body", Value::Str("Anna is very interested in our platform. Key concerns are security and compliance. Needs board approval for deals over $200k. Follow up next week with technical deep-dive for Björn.".into())),
    ])?;
    insert("notes", 2, vec![
        ("title", Value::Str("Acme Corp requirements".into())),
        ("body", Value::Str("Acme needs: SSO/SAML integration, custom fields for their industry, API rate limits at 10k/min minimum. Decision maker is Björn, budget holder is CFO Kristín.".into())),
    ])?;

    println!("  ✓ 2 notes created");
    println!("✅ Database seeded successfully!");

    Ok(())
}