← back to Designer Wallcoverings

DW-Agents/dw-agents/agent-new-client-signup/shopify-customers.ts

213 lines

/**
 * Shopify Customer Data Fetcher
 * Fetches real customer data from Shopify store
 */

import fetch from 'node-fetch';

const SHOPIFY_STORE_DOMAIN = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN || '';

export interface ShopifyCustomer {
  id: number;
  email: string;
  first_name: string;
  last_name: string;
  created_at: string;
  updated_at: string;
  orders_count: number;
  total_spent: string;
  phone?: string;
  company?: string;
  city?: string;
  province?: string;
  country?: string;
  tags?: string;
  note?: string;
}

export interface CustomerSignup {
  timestamp: Date;
  customerName: string;
  email: string;
  company: string;
  interest: string;
  source: string;
  phone?: string;
  location?: string;
  ordersCount: number;
  totalSpent: string;
  tags?: string;
}

/**
 * Fetch customers from Shopify Orders API (since customer API requires different permissions)
 */
export async function fetchShopifyCustomers(limit: number = 50): Promise<ShopifyCustomer[]> {
  try {
    const url = `https://${SHOPIFY_STORE_DOMAIN}/admin/api/2024-01/orders.json?limit=${limit}&status=any&order=created_at desc`;

    console.log('🛍️ Fetching customers from Shopify orders...');

    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'X-Shopify-Access-Token': SHOPIFY_ACCESS_TOKEN,
        'Content-Type': 'application/json',
      },
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`Shopify API error: ${response.status} ${response.statusText} - ${errorText}`);
    }

    const data = await response.json() as { orders: any[] };
    console.log(`✅ Fetched ${data.orders.length} orders from Shopify`);

    // Extract unique customers from orders
    const customerMap = new Map<number, ShopifyCustomer>();

    for (const order of data.orders) {
      if (order.customer && order.customer.id) {
        const customer = order.customer;
        if (!customerMap.has(customer.id) || new Date(order.created_at) > new Date(customerMap.get(customer.id)!.created_at)) {
          customerMap.set(customer.id, {
            id: customer.id,
            email: customer.email,
            first_name: customer.first_name,
            last_name: customer.last_name,
            created_at: customer.created_at || order.created_at,
            updated_at: customer.updated_at || order.updated_at,
            orders_count: customer.orders_count || 1,
            total_spent: customer.total_spent || order.total_price,
            phone: customer.phone || order.billing_address?.phone,
            company: order.billing_address?.company || order.shipping_address?.company,
            city: order.billing_address?.city || order.shipping_address?.city,
            province: order.billing_address?.province || order.shipping_address?.province,
            country: order.billing_address?.country || order.shipping_address?.country,
            tags: customer.tags,
            note: customer.note
          });
        }
      }
    }

    const customers = Array.from(customerMap.values());
    console.log(`✅ Extracted ${customers.length} unique customers from orders`);

    return customers;
  } catch (error) {
    console.error('❌ Error fetching Shopify customers:', error);
    return [];
  }
}

/**
 * Fetch recent customer signups (last 30 days)
 */
export async function fetchRecentSignups(days: number = 30): Promise<CustomerSignup[]> {
  try {
    const customers = await fetchShopifyCustomers(250);

    // Filter for recent signups
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - days);

    const recentCustomers = customers.filter(customer => {
      const createdDate = new Date(customer.created_at);
      return createdDate >= cutoffDate;
    });

    // Convert to signup format
    const signups: CustomerSignup[] = recentCustomers.map(customer => {
      const name = `${customer.first_name || ''} ${customer.last_name || ''}`.trim() || 'Anonymous';
      const location = [customer.city, customer.province, customer.country]
        .filter(Boolean)
        .join(', ');

      // Determine interest based on tags or note
      let interest = 'General wallpaper inquiry';
      if (customer.tags) {
        if (customer.tags.includes('grasscloth')) interest = 'Grasscloth wallpaper';
        else if (customer.tags.includes('flocked')) interest = 'Flocked wallpaper';
        else if (customer.tags.includes('beaded')) interest = 'Glass beaded wallpaper';
        else if (customer.tags.includes('suede')) interest = 'Novasuede wallpaper';
      }

      // Determine source
      let source = 'Website Form';
      if (customer.note?.includes('phone')) source = 'Phone Inquiry';
      else if (customer.note?.includes('email')) source = 'Email Inquiry';
      else if (customer.tags?.includes('wholesale')) source = 'Wholesale';

      return {
        id: customer.id,
        timestamp: new Date(customer.created_at),
        customerName: name,
        email: customer.email || 'N/A',
        company: customer.company || 'Individual',
        interest,
        source,
        phone: customer.phone,
        location: location || 'N/A',
        ordersCount: customer.orders_count,
        totalSpent: customer.total_spent,
        tags: customer.tags,
      };
    });

    // Sort by timestamp, newest first
    signups.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());

    console.log(`✅ Converted ${signups.length} recent signups`);
    return signups;
  } catch (error) {
    console.error('❌ Error fetching recent signups:', error);
    return [];
  }
}

/**
 * Get signup statistics
 */
export function getSignupStats(signups: CustomerSignup[]) {
  const now = new Date();
  const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const weekStart = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);

  return {
    today: signups.filter(s => s.timestamp >= todayStart).length,
    thisWeek: signups.filter(s => s.timestamp >= weekStart).length,
    thisMonth: signups.filter(s => s.timestamp >= monthStart).length,
    total: signups.length,
  };
}

// Test function
if (require.main === module) {
  (async () => {
    console.log('🧪 Testing Shopify customer fetcher...\n');

    const signups = await fetchRecentSignups(30);
    console.log(`\n📊 Found ${signups.length} signups in last 30 days`);

    const stats = getSignupStats(signups);
    console.log('\n📈 Stats:');
    console.log(`   Today: ${stats.today}`);
    console.log(`   This Week: ${stats.thisWeek}`);
    console.log(`   This Month: ${stats.thisMonth}`);
    console.log(`   Total: ${stats.total}`);

    if (signups.length > 0) {
      console.log('\n👤 Most Recent Signup:');
      const recent = signups[0];
      console.log(`   Name: ${recent.customerName}`);
      console.log(`   Email: ${recent.email}`);
      console.log(`   Company: ${recent.company}`);
      console.log(`   Date: ${recent.timestamp.toLocaleString()}`);
    }
  })();
}