feat(canva): support asset_final, created_by, include=client filters in GET and merge meta in PATCH
This commit is contained in:
@@ -34,10 +34,23 @@ export async function GET(
|
|||||||
if (include === 'client') {
|
if (include === 'client') {
|
||||||
const { data: client } = await adminClient
|
const { data: client } = await adminClient
|
||||||
.from('tenants')
|
.from('tenants')
|
||||||
.select('id, name, slug, meta_ad_account_id, meta_page_id, meta_ig_user_id, default_landing_url, meta_publish_status, slack_channel_id')
|
.select('id, name, slug, meta_ad_account_id, meta_page_id, meta_ig_user_id, default_landing_url, meta_publish_status, slack_channel_id, canva_templates, drive_folder_id')
|
||||||
.eq('id', tenantId)
|
.eq('id', tenantId)
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
|
const defaultBpsTemplate = process.env.BPS_CANVA_TEMPLATE_ID || 'EAHRb38v_WY';
|
||||||
|
let canvaTemplates = (client as any)?.canva_templates || {};
|
||||||
|
if (
|
||||||
|
client?.slug === 'bps' &&
|
||||||
|
(!canvaTemplates || Object.keys(canvaTemplates).length === 0)
|
||||||
|
) {
|
||||||
|
canvaTemplates = {
|
||||||
|
'foto-con-franja': defaultBpsTemplate,
|
||||||
|
tipografico: null,
|
||||||
|
default: defaultBpsTemplate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
data: {
|
data: {
|
||||||
creative,
|
creative,
|
||||||
@@ -51,6 +64,8 @@ export async function GET(
|
|||||||
default_landing_url: client?.default_landing_url,
|
default_landing_url: client?.default_landing_url,
|
||||||
meta_publish_status: client?.meta_publish_status || 'PAUSED',
|
meta_publish_status: client?.meta_publish_status || 'PAUSED',
|
||||||
slack_channel_id: client?.slack_channel_id,
|
slack_channel_id: client?.slack_channel_id,
|
||||||
|
canva_templates: canvaTemplates,
|
||||||
|
drive_folder_id: (client as any)?.drive_folder_id || null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -105,8 +120,13 @@ export async function PATCH(
|
|||||||
if (body.campaign_name !== undefined) updates.campaign_name = body.campaign_name;
|
if (body.campaign_name !== undefined) updates.campaign_name = body.campaign_name;
|
||||||
if (body.asset_url !== undefined) updates.asset_url = body.asset_url;
|
if (body.asset_url !== undefined) updates.asset_url = body.asset_url;
|
||||||
if (body.thumbnail_url !== undefined) updates.thumbnail_url = body.thumbnail_url;
|
if (body.thumbnail_url !== undefined) updates.thumbnail_url = body.thumbnail_url;
|
||||||
if (body.asset_final !== undefined) updates.asset_final = body.asset_final;
|
if (body.asset_final !== undefined) updates.asset_final = Boolean(body.asset_final);
|
||||||
if (body.meta !== undefined) updates.meta = body.meta;
|
if (body.meta !== undefined && typeof body.meta === 'object' && body.meta !== null) {
|
||||||
|
updates.meta = {
|
||||||
|
...(creative.meta && typeof creative.meta === 'object' ? creative.meta : {}),
|
||||||
|
...body.meta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const { data: updated, error: updateErr } = await adminClient
|
const { data: updated, error: updateErr } = await adminClient
|
||||||
.from('creatives')
|
.from('creatives')
|
||||||
@@ -120,23 +140,28 @@ export async function PATCH(
|
|||||||
return NextResponse.json({ error: updateErr.message }, { status: 500 });
|
return NextResponse.json({ error: updateErr.message }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si pasa a publicada o cambia meta_ad_id, registrar en creative_events
|
// Si pasa a publicada, cambia meta_ad_id o se sube asset_final, registrar en creative_events
|
||||||
if (updates.status === 'publicada' || updates.meta_ad_id) {
|
if (updates.status === 'publicada' || updates.meta_ad_id || updates.asset_final) {
|
||||||
await adminClient.from('creative_events').insert({
|
await adminClient.from('creative_events').insert({
|
||||||
tenant_id: tenantId,
|
tenant_id: tenantId,
|
||||||
creative_id: id,
|
creative_id: id,
|
||||||
event_type: updates.status === 'publicada' ? 'published' : 'creative_updated',
|
event_type: updates.status === 'publicada' ? 'published' : updates.asset_final ? 'asset_final_composed' : 'creative_updated',
|
||||||
actor: auth.caller || 'n8n',
|
actor: auth.caller || 'n8n',
|
||||||
from_status: prevStatus,
|
from_status: prevStatus,
|
||||||
to_status: updates.status || prevStatus,
|
to_status: updates.status || prevStatus,
|
||||||
payload: {
|
payload: {
|
||||||
meta_ad_id: updates.meta_ad_id || creative.meta_ad_id,
|
meta_ad_id: updates.meta_ad_id || creative.meta_ad_id,
|
||||||
adset_id: updates.adset_id,
|
adset_id: updates.adset_id,
|
||||||
|
asset_final: updates.asset_final,
|
||||||
meta: updates.meta,
|
meta: updates.meta,
|
||||||
},
|
},
|
||||||
visibility: 'client',
|
visibility: updates.status === 'publicada' ? 'client' : 'agency',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(updated);
|
return NextResponse.json({
|
||||||
|
ok: true,
|
||||||
|
data: updated,
|
||||||
|
...updated,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,13 +110,18 @@ export async function POST(req: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const auth = await authenticateIntegrationRequest(req, { requireTenant: true });
|
const auth = await authenticateIntegrationRequest(req, { requireTenant: false });
|
||||||
if (!auth.ok) {
|
if (!auth.ok) {
|
||||||
return auth.errorResponse!;
|
return auth.errorResponse!;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tenantId = auth.tenantId!;
|
const searchParams = req.nextUrl.searchParams;
|
||||||
const status = req.nextUrl.searchParams.get('status');
|
const tenantId = searchParams.get('tenant_id') || searchParams.get('client_id');
|
||||||
|
const status = searchParams.get('status');
|
||||||
|
const assetFinal = searchParams.get('asset_final');
|
||||||
|
const createdBy = searchParams.get('created_by');
|
||||||
|
const include = searchParams.get('include');
|
||||||
|
const limitParam = searchParams.get('limit');
|
||||||
|
|
||||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
|
||||||
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
|
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
|
||||||
@@ -124,18 +129,87 @@ export async function GET(req: NextRequest) {
|
|||||||
|
|
||||||
let query = adminClient
|
let query = adminClient
|
||||||
.from('creatives')
|
.from('creatives')
|
||||||
.select('*')
|
.select('*, tenant:tenants(id, name, slug, canva_templates, drive_folder_id, creatives_enabled)');
|
||||||
.eq('tenant_id', tenantId);
|
|
||||||
|
if (tenantId) {
|
||||||
|
query = query.eq('tenant_id', tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
query = query.eq('status', status);
|
query = query.eq('status', status);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: creatives, error } = await query;
|
if (assetFinal === 'true') {
|
||||||
|
query = query.eq('asset_final', true);
|
||||||
|
} else if (assetFinal === 'false') {
|
||||||
|
query = query.eq('asset_final', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdBy) {
|
||||||
|
query = query.eq('created_by', createdBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.order('created_at', { ascending: true });
|
||||||
|
|
||||||
|
if (limitParam) {
|
||||||
|
const parsedLimit = Number(limitParam);
|
||||||
|
if (!isNaN(parsedLimit) && parsedLimit > 0) {
|
||||||
|
query = query.limit(parsedLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: rows, error } = await query;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(creatives || []);
|
const defaultBpsTemplate = process.env.BPS_CANVA_TEMPLATE_ID || 'EAHRb38v_WY';
|
||||||
|
|
||||||
|
const enriched = (rows || [])
|
||||||
|
.filter((row: any) => {
|
||||||
|
if (tenantId) return true;
|
||||||
|
return row.tenant?.creatives_enabled !== false;
|
||||||
|
})
|
||||||
|
.map((row: any) => {
|
||||||
|
const { tenant, ...rest } = row;
|
||||||
|
let canvaTemplates = tenant?.canva_templates || {};
|
||||||
|
if (
|
||||||
|
tenant?.slug === 'bps' &&
|
||||||
|
(!canvaTemplates || Object.keys(canvaTemplates).length === 0)
|
||||||
|
) {
|
||||||
|
canvaTemplates = {
|
||||||
|
'foto-con-franja': defaultBpsTemplate,
|
||||||
|
tipografico: null,
|
||||||
|
default: defaultBpsTemplate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const item: Record<string, any> = {
|
||||||
|
...rest,
|
||||||
|
client_id: rest.tenant_id,
|
||||||
|
meta: rest.meta || {},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (include === 'client') {
|
||||||
|
item.client = tenant
|
||||||
|
? {
|
||||||
|
id: tenant.id,
|
||||||
|
name: tenant.name,
|
||||||
|
slug: tenant.slug,
|
||||||
|
canva_templates: canvaTemplates,
|
||||||
|
drive_folder_id: tenant.drive_folder_id || null,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
ok: true,
|
||||||
|
count: enriched.length,
|
||||||
|
data: enriched,
|
||||||
|
creatives: enriched,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user