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:
@@ -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,
|
||||
|
||||
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user