fix: mostrar Google Ads desde ad_daily cuando kpi_weekly está vacío

kpi_weekly es una MV de solo lectura sin canales paid; canal/seguimiento
ahora hacen fallback a ad_daily. Bump Google Ads API a v21 en sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-23 12:13:41 +02:00
parent a1a00840d5
commit fba025da76
7 changed files with 159 additions and 24 deletions

View File

@@ -4,7 +4,7 @@ import { serviceHeaders, supabaseUrl } from '@/lib/agency';
import { resolveMetaAccessToken } from '@/lib/ads-discovery';
const META_GRAPH = 'https://graph.facebook.com/v21.0';
const GADS_API = 'https://googleads.googleapis.com/v18';
const GADS_API = 'https://googleads.googleapis.com/v21';
export type SyncTenantResult = {
tenantId: string;
@@ -285,14 +285,16 @@ async function fetchGoogleCampaignDaily(
const date = row.segments?.date;
if (!date) continue;
const spend = Math.round((n(row.metrics?.costMicros) / 1_000_000) * 100) / 100;
const campaignId = row.campaign?.id ? String(row.campaign.id) : null;
out.push({
tenant_id: tenantId,
date,
platform: 'google',
campaign_id: row.campaign?.id ? String(row.campaign.id) : null,
campaign_id: campaignId,
campaign_name: row.campaign?.name || null,
ad_id: null,
ad_name: null,
// ad_daily.ad_id is NOT NULL — campaign-level rows reuse campaign id
ad_id: campaignId || '',
ad_name: '',
impressions: n(row.metrics?.impressions),
clicks: n(row.metrics?.clicks),
spend,

View File

@@ -284,4 +284,31 @@ export function weeklyFromDaily(rows: AdDailyRow[]): KpiWeeklyRow[] {
});
}
const ADS_CHANNELS = new Set(['meta', 'google']);
/**
* kpi_weekly is often a non-writable MV without paid channels.
* Prefer ad_daily rollups when they carry meta/google (or more spend).
*/
export function resolveWeeklyRows(
weekly: KpiWeeklyRow[],
daily: AdDailyRow[]
): KpiWeeklyRow[] {
const fromDaily = weeklyFromDaily(daily);
if (!fromDaily.length) return weekly;
const weeklySpend = weekly.reduce((a, r) => a + n(r.total_spend), 0);
const dailySpend = daily.reduce((a, r) => a + n(r.spend), 0);
const weeklyAds = weekly.some((r) =>
ADS_CHANNELS.has((r.channel || '').toLowerCase())
);
const dailyAds = daily.some((r) =>
ADS_CHANNELS.has((r.platform || '').toLowerCase())
);
if (dailyAds && !weeklyAds) return fromDaily;
if (dailySpend >= weeklySpend) return fromDaily;
return weekly;
}
export { isoDate, weekStart };