Comparativas WoW/MoM/YoY muestran prev/Δ además del %; sync ads admite histórico desde 2025; tabla ads↔CRM añade cierres, ventas y ROAS. Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
/**
|
|
* 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);
|
|
});
|