feat(integrations): support history_days in fatigue candidates and ensure data envelope for WF2
This commit is contained in:
@@ -24,11 +24,20 @@ export async function GET(req: NextRequest) {
|
||||
return NextResponse.json({ error: rulesErr.message }, { status: 500 });
|
||||
}
|
||||
|
||||
const lookbackDays = rules?.lookback_days || 7;
|
||||
const lookbackDays = Number(rules?.lookback_days || 7);
|
||||
const minHistory = lookbackDays * 2;
|
||||
|
||||
// 2. Calcular fecha de inicio según lookback_days
|
||||
// Query param history_days (por defecto 28, mínimo lookback_days * 2)
|
||||
const url = new URL(req.url);
|
||||
const rawHistory = url.searchParams.get('history_days');
|
||||
let historyDays = rawHistory ? parseInt(rawHistory, 10) : 28;
|
||||
if (isNaN(historyDays) || historyDays < minHistory) {
|
||||
historyDays = Math.max(28, minHistory);
|
||||
}
|
||||
|
||||
// 2. Calcular fecha de inicio según history_days
|
||||
const sinceDate = new Date();
|
||||
sinceDate.setDate(sinceDate.getDate() - lookbackDays);
|
||||
sinceDate.setDate(sinceDate.getDate() - historyDays);
|
||||
const sinceStr = sinceDate.toISOString().split('T')[0];
|
||||
|
||||
// 3. Buscar creatividades actualmente publicadas para este cliente
|
||||
@@ -51,7 +60,7 @@ export async function GET(req: NextRequest) {
|
||||
if (metaIds.length > 0) {
|
||||
const { data: metrics, error: metricsErr } = await adminClient
|
||||
.from('creative_metrics_daily')
|
||||
.select('*')
|
||||
.select('date, impressions, reach, clicks, ctr, frequency, spend, results, cpa, meta_ad_id')
|
||||
.eq('tenant_id', tenantId)
|
||||
.in('meta_ad_id', metaIds)
|
||||
.gte('date', sinceStr)
|
||||
@@ -63,22 +72,43 @@ export async function GET(req: NextRequest) {
|
||||
|
||||
(metrics || []).forEach((m: any) => {
|
||||
const list = metricsMap.get(m.meta_ad_id) || [];
|
||||
list.push(m);
|
||||
list.push({
|
||||
date: m.date,
|
||||
impressions: Number(m.impressions || 0),
|
||||
reach: Number(m.reach || 0),
|
||||
clicks: Number(m.clicks || 0),
|
||||
ctr: Number(m.ctr || 0),
|
||||
frequency: Number(m.frequency || 0),
|
||||
spend: Number(m.spend || 0),
|
||||
results: Number(m.results || 0),
|
||||
cpa: m.cpa !== null && m.cpa !== undefined ? Number(m.cpa) : null,
|
||||
});
|
||||
metricsMap.set(m.meta_ad_id, list);
|
||||
});
|
||||
}
|
||||
|
||||
const candidates = (publishedCreatives || []).map((c: any) => ({
|
||||
...c,
|
||||
client_id: c.tenant_id,
|
||||
const creatives = (publishedCreatives || []).map((c: any) => ({
|
||||
id: c.id,
|
||||
meta_ad_id: c.meta_ad_id,
|
||||
hook: c.hook,
|
||||
angle: c.angle,
|
||||
campaign_name: c.campaign_name,
|
||||
metrics: metricsMap.get(c.meta_ad_id) || [],
|
||||
}));
|
||||
|
||||
const dataPayload = {
|
||||
rules: rules || null,
|
||||
creatives,
|
||||
};
|
||||
|
||||
return NextResponse.json({
|
||||
data: dataPayload,
|
||||
client_id: tenantId,
|
||||
tenant_id: tenantId,
|
||||
lookback_days: lookbackDays,
|
||||
history_days: historyDays,
|
||||
rules: rules || null,
|
||||
candidates,
|
||||
creatives,
|
||||
candidates: creatives,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,5 +131,11 @@ export async function POST(req: NextRequest) {
|
||||
status: 'fatigada',
|
||||
signals,
|
||||
generation_request: generationRequest,
|
||||
data: {
|
||||
creative_id: creativeId,
|
||||
status: 'fatigada',
|
||||
signals,
|
||||
generation_request: generationRequest,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user