fix: KPIs — ocultar WoW >7d, YoY con histórico completo, ventas en nº

Pagina ad_daily (~420d) para que YoY no quede vacío; Ventas muestra
conteo de deals (importe Clientify en hint/columna Importe).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-28 11:05:21 +02:00
parent dff9c46747
commit 4c8042aa23
3 changed files with 119 additions and 64 deletions

View File

@@ -20,6 +20,55 @@ import { isAgencyRole, serviceHeaders, supabaseUrl, userRole } from '@/lib/agenc
export const dynamic = 'force-dynamic';
/** Enough history for YoY on ad-level Meta rows (can be dense). */
const AD_DAILY_LOOKBACK_DAYS = 420;
const AD_DAILY_PAGE = 1000;
async function fetchAdDaily(
tenantId: string | null,
useServiceRole: boolean
): Promise<AdDailyRow[]> {
const since = new Date();
since.setUTCDate(since.getUTCDate() - AD_DAILY_LOOKBACK_DAYS);
const sinceStr = since.toISOString().slice(0, 10);
const out: AdDailyRow[] = [];
if (useServiceRole) {
const headers = serviceHeaders();
const base = supabaseUrl();
if (!headers || !base) return [];
const tidFilter = tenantId
? `&tenant_id=eq.${encodeURIComponent(tenantId)}`
: '';
for (let offset = 0; offset < 200000; offset += AD_DAILY_PAGE) {
const r = await fetch(
`${base}/rest/v1/ad_daily?select=*&date=gte.${sinceStr}${tidFilter}&order=date.desc&limit=${AD_DAILY_PAGE}&offset=${offset}`,
{ headers, cache: 'no-store' }
);
if (!r.ok) break;
const chunk = (await r.json()) as AdDailyRow[];
out.push(...chunk);
if (chunk.length < AD_DAILY_PAGE) break;
}
return out;
}
const supabase = await createClient();
for (let offset = 0; offset < 200000; offset += AD_DAILY_PAGE) {
const { data, error } = await supabase
.from('ad_daily')
.select('*')
.gte('date', sinceStr)
.order('date', { ascending: false })
.range(offset, offset + AD_DAILY_PAGE - 1);
if (error) break;
const chunk = (data as AdDailyRow[]) || [];
out.push(...chunk);
if (chunk.length < AD_DAILY_PAGE) break;
}
return out;
}
/** Paginate CRM leads (source + created_at + status) for attribution + cohort. */
async function fetchCrmLeads(
tenantId: string | null,
@@ -148,11 +197,8 @@ export default async function KpisPage() {
const w = await restGet<KpiWeeklyRow[]>(
'/rest/v1/kpi_weekly?select=*&order=week.desc'
);
const d = await restGet<AdDailyRow[]>(
'/rest/v1/ad_daily?select=*&order=date.desc&limit=5000'
);
weekly = w.data || [];
daily = d.data || [];
daily = await fetchAdDaily(null, true);
crmLeads = [];
wonDeals = await fetchWonDeals(null, true);
} else if (ctx.tenantId) {
@@ -160,11 +206,8 @@ export default async function KpisPage() {
const w = await restGet<KpiWeeklyRow[]>(
`/rest/v1/kpi_weekly?tenant_id=eq.${tid}&select=*&order=week.desc`
);
const d = await restGet<AdDailyRow[]>(
`/rest/v1/ad_daily?tenant_id=eq.${tid}&select=*&order=date.desc&limit=5000`
);
weekly = w.data || [];
daily = d.data || [];
daily = await fetchAdDaily(ctx.tenantId, true);
crmLeads = await fetchCrmLeads(ctx.tenantId, true);
wonDeals = await fetchWonDeals(ctx.tenantId, true);
}
@@ -173,13 +216,8 @@ export default async function KpisPage() {
.from('kpi_weekly')
.select('*')
.order('week', { ascending: false });
const { data: d } = await supabase
.from('ad_daily')
.select('*')
.order('date', { ascending: false })
.limit(5000);
weekly = (w as KpiWeeklyRow[]) || [];
daily = (d as AdDailyRow[]) || [];
daily = await fetchAdDaily(ctx.tenantId, false);
crmLeads = await fetchCrmLeads(ctx.tenantId, false);
wonDeals = await fetchWonDeals(ctx.tenantId, false);
}