/** * Sync Meta + Google Ads → ad_daily (+ kpi_weekly rollup). * * Usage: * npx tsx scripts/sync_ads_only.ts # last 30d all tenants * DAYS=640 npx tsx scripts/sync_ads_only.ts # backfill ~from Jan 2025 * TENANT_SLUG=bps DAYS=640 npx tsx ... */ import { config } from 'dotenv'; import { resolve } from 'path'; config({ path: resolve(process.cwd(), '.env.local') }); import { ADS_BACKFILL_MAX_DAYS, syncAdsForTenants, } from '../src/lib/ads-sync'; async function main() { const slug = process.env.TENANT_SLUG?.trim(); let tenantId: string | undefined; if (slug) { const { serviceHeaders, supabaseUrl } = await import('../src/lib/agency'); const headers = serviceHeaders()!; const r = await fetch( `${supabaseUrl()}/rest/v1/tenants?slug=eq.${encodeURIComponent(slug)}&select=id&limit=1`, { headers } ); const rows = (await r.json()) as { id: string }[]; tenantId = rows[0]?.id; if (!tenantId) throw new Error(`Tenant slug not found: ${slug}`); } // Days since 2025-01-01 (inclusive) when DAYS unset and BACKFILL=1 const backfill = process.env.BACKFILL === '1' || process.env.BACKFILL === 'true'; const daysFrom2025 = Math.ceil( (Date.now() - Date.UTC(2025, 0, 1)) / 86400000 ); const rawDays = Number(process.env.DAYS); const days = Math.min( ADS_BACKFILL_MAX_DAYS, Math.max( 1, Number.isFinite(rawDays) && rawDays > 0 ? rawDays : backfill ? daysFrom2025 : 30 ) ); console.log( `Ads sync · days=${days} · since≈${new Date(Date.now() - days * 86400000).toISOString().slice(0, 10)}` + (tenantId ? ` · tenant=${slug || tenantId}` : ' · all tenants') ); const { results } = await syncAdsForTenants({ tenantId, days }); let ok = 0; let err = 0; for (const x of results) { const rows = x.metaRows + x.googleRows; if (rows > 0) ok += 1; if (x.errors.length) err += 1; console.log( `${x.tenantName}: meta=${x.metaRows} google=${x.googleRows} weekly=${x.weeklyRows}` + (x.errors.length ? ` · ERR ${x.errors.join('; ').slice(0, 200)}` : '') ); } console.log(`\nDone · synced=${ok} withErrors=${err} / ${results.length}`); } main().catch((e) => { console.error(e); process.exit(1); });