Organic social channels per client in the agency hub, separate from paid Meta Ads. Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
3.4 KiB
TypeScript
94 lines
3.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { createClient } from '@/lib/supabase/server';
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const supabase = await createClient();
|
|
const { data: { user } } = await supabase.auth.getUser();
|
|
|
|
if (!user) {
|
|
return NextResponse.json({ error: 'No autorizado. Inicia sesión.' }, { status: 401 });
|
|
}
|
|
|
|
const userRole = user.app_metadata?.role || user.user_metadata?.role || 'client';
|
|
if (userRole !== 'admin' && userRole !== 'team') {
|
|
return NextResponse.json({ error: 'Permisos insuficientes. Solo administradores pueden crear clientes.' }, { status: 403 });
|
|
}
|
|
|
|
const body = await req.json();
|
|
const { companyName, slug, email, password, role } = body;
|
|
|
|
if (!companyName || !slug || !email || !password) {
|
|
return NextResponse.json({ error: 'Todos los campos son obligatorios.' }, { status: 400 });
|
|
}
|
|
|
|
const sanitizedSlug = slug.toLowerCase().trim().replace(/[^a-z0-9-]/g, '-');
|
|
const targetRole = role === 'admin' || role === 'team' ? role : 'client';
|
|
|
|
const { data, error } = await supabase.rpc('provision_client', {
|
|
p_company_name: companyName.trim(),
|
|
p_slug: sanitizedSlug,
|
|
p_email: email.toLowerCase().trim(),
|
|
p_password: password,
|
|
p_role: targetRole,
|
|
});
|
|
|
|
if (error) {
|
|
console.error('Error in provision_client RPC:', error);
|
|
return NextResponse.json({ error: error.message || 'Error al provisionar cliente en base de datos.' }, { status: 500 });
|
|
}
|
|
|
|
// Seed integration slots (best-effort; ignore if table missing)
|
|
try {
|
|
const tenantId =
|
|
data?.tenant_id || data?.id || data?.client?.tenant_id || null;
|
|
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY?.trim();
|
|
const url = process.env.NEXT_PUBLIC_SUPABASE_URL || 'https://supabase.4ventures.es';
|
|
if (tenantId && serviceKey) {
|
|
const providers = [
|
|
['meta_ads', 'Meta Ads'],
|
|
['google_ads', 'Google Ads (MCC)'],
|
|
['ga4', 'Google Analytics 4'],
|
|
['search_console', 'Search Console'],
|
|
['tag_manager', 'Tag Manager'],
|
|
['clientify', 'Clientify'],
|
|
['klaviyo', 'Klaviyo'],
|
|
['mailchimp', 'Mailchimp'],
|
|
['google_drive', 'Google Drive'],
|
|
['wordpress', 'WordPress'],
|
|
['prestashop', 'PrestaShop'],
|
|
['shopify', 'Shopify'],
|
|
['instagram', 'Instagram'],
|
|
['facebook', 'Facebook Page'],
|
|
['tiktok', 'TikTok'],
|
|
['linkedin', 'LinkedIn'],
|
|
];
|
|
await fetch(`${url}/rest/v1/integrations`, {
|
|
method: 'POST',
|
|
headers: {
|
|
apikey: serviceKey,
|
|
Authorization: `Bearer ${serviceKey}`,
|
|
'Content-Type': 'application/json',
|
|
Prefer: 'resolution=ignore-duplicates',
|
|
},
|
|
body: JSON.stringify(
|
|
providers.map(([provider, label]) => ({
|
|
tenant_id: tenantId,
|
|
provider,
|
|
status: 'disconnected',
|
|
label,
|
|
}))
|
|
),
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.warn('seed integrations skipped', e);
|
|
}
|
|
|
|
return NextResponse.json({ success: true, client: data });
|
|
} catch (err: any) {
|
|
console.error('Server error creating client:', err);
|
|
return NextResponse.json({ error: err?.message || 'Error interno del servidor.' }, { status: 500 });
|
|
}
|
|
}
|